——看破楼外楼,历经园中园

写出数据结构系列的文章,目的还是明确各种数据结构的实现逻辑,
然后根据逻辑我们自定义对应的类,并加以使用,实现的功能大同小异;
主要还是
1.结构的生成;2.结构的销毁;3.在结构中查找满足规定条件的数据元素;
4.在结构中插入新的数据元素;5.删除结构中已经存在的数据元素;6.遍历。

之后同系列的文章也会按照这个逻辑写下去了。





一、链表在使用场景的引入



在讲述链表之前,我们可以先回顾最为熟悉的数组,
数组是连续存储,大小固定,按序访问的数据结构。

由于数组空间的固定,我们时常会面临内存空间浪费或越界的情况

java 单链表循环 java 单向链表_链表


java 单链表循环 java 单向链表_i++_02

当数据数量巨大(huge)的时候,进行相关的挪位操作是十分没有效率的;

操作的繁琐性是由于数组在分布内存时的连续性造成的,
为了降低繁琐性,应该有不连续的数据结构用来储存数据,
不同单位之间可以不连续分布,但是相互之间又有一定的联系;



链表就是这么一种满足上述要求的数据结构:)



java 单链表循环 java 单向链表_i++_03



二、链表的组成



* 基本组成单位:节点(Node)



节点的组成

节点由两个部分组成:

  • 数据域:用来储存相关数据,当然你可以用Object来定义属性。
  • 引用域:用来储存有相关联系的节点。
  • 单向链表:储存下一个节点;
  • 双向链表:储存上一个节点与下一个节点;


### 节点的定义代码

package MylinkenList;

public class Node {

	private Object e;
	private Node next;


public Node(Object e)
{
		this.e=e;
}
public Node( )
{
	
}

public Object Obejct()
{
	return e;
}
public Node next()
{
	return next;
}
public void setNode(Node n)
{
	next=n;
}

}



*单向链表组成



  • Size:纪录该链表的长度,进行增添删除时会与传入的索引发生比较,同时改变自身的值;
  • Head(Node): 空节点,用来标志一个链表的开始,遍历时也会使用该节点;
  • Tail(Node):空节点,开始指向头部;按顺序最新添加的节点的下一节点指向该点;


链表定义的代码



public class myLinkedList {

	public Node Head;
	public Node Tail;
	public int  size;
	
	public myLinkedList() {
		
		Head = new Node();
		Tail = new Node();
		Head.setnext(Tail);
		size = 0;
	}
}





三、链表功能的实现



* 前置准备的思考



首先,我们要先考虑方法的返回值:

  • 插入的时候,返回布尔变量true,表示成功;
  • 替换的时候,返回被替代的节点的数据;
  • 删除的时候,返回被删除的节点的数据;

接着,我们要先考虑方法的传入:

  • 插入/ 替换的时候,传入index和obejct;
  • 删除的时候,传入index;

接着我们要写一段用于判断索引值是否合法的语句,
加在所以方法的最前端:

if(index<0||index>=size)
{
	System.out.println("The Index is error!")
	return 0;
}



* 操作位置的考虑



首先呢,无论哪个位置,本质上还是在调整某些节点指向的节点;
替换并不会有情况上的差异;

  • 添加
  • 添加的节点在首位
  • 头节点的next指向新节点;
  • 新节点的next指向头节点的next;

java 单链表循环 java 单向链表_链表_04

  • 添加的节点在尾部;
  • 指定节点的next指向新节点;
  • 新节点的next指向尾节点;

java 单链表循环 java 单向链表_链表_05

  • 添加的节点在中间;
  • 指定节点的上一个节点的next指向新节点;
  • 新节点的next指向指定节点;

java 单链表循环 java 单向链表_System_06

  • 删除
  • 删除的节点在首位
  • 头节点的next指向指定节点的next;
  • 指定节点的next指向null;

java 单链表循环 java 单向链表_System_07

  • 删除的节点在尾部
  • 指定节点的前一个节点的next指向尾节点;
  • 指定节点的next指向null;
  • 删除的节点在中间
  • 指定节点的前一个节点的next指向指定节点的next;
  • 指定节点的next指向null;
  • 替换
  • 替换的节点在首位
  • 头节点的next指向新节点;
  • 新节点的next指向指定节点的next;
  • 指定节点的next指向null;
  • 替换的节点在尾部
  • 指定节点的上一个节点的next指向新节点;
  • 新节点的next指向尾节点;
  • 指定节点的next指向null;
  • 替换的节点在尾部
  • 指定节点的上一个节点的next指向新节点;
  • 新节点的next指向指定节点的下一个节点;
  • 指定节点的next指向null;

java 单链表循环 java 单向链表_i++_08

嗯…如果你和我一样是初学者,建议你还是拿张纸画画,这样会更好理解呀。JDK一览:

java 单链表循环 java 单向链表_i++_09


java 单链表循环 java 单向链表_System_10


2019.2.22:

1.实现了JDK中大部分?的方法.

2.仍未实现的方法

  • clone()
  • pop()
  • toArray()
  • toArray(T[] a)

* 实现的代码

package Mylinkedlist;

import Myarraylist.MyArrayList;

public class MyLinkedlist<E> {
	public String name;
	public Node head;
	public Node tail;
	public int size=0;
	public MyLinkedlist(String name) {
		this.name=name;
		head=new Node();
		tail=new Node();
		head.nextNode=tail;
		tail.nextNode=null;
	}
	
	public  boolean add(E e) 
	{
		Node newNode=new Node();
		newNode.data=e;
		
		if(size==0)
		{
			head.nextNode=newNode;
		}
		else
		{
			Node lastNode=new Node();
			lastNode=head.nextNode;
			for(int i=0;i<size-1;i++)
			{
				lastNode=lastNode.nextNode;
			}
			lastNode.nextNode=newNode;
		}
		
		
		newNode.nextNode=null;
		tail=newNode;
		size++;
		return true;
	}
	public void add(int index,E e)
	{
		if(index<0||index>size)
		{
			System.out.println("error");
		}
		else
		{
			Node newNode=new Node();
			newNode.data=e;
			
			if(size==0)
			{
				head.nextNode=newNode;
			}
			else 
			{
				Node lastNode=new Node();
				lastNode=head.nextNode;
				for(int i=0;i<index-1;i++)
				{
					lastNode=lastNode.nextNode;
				}
				newNode.nextNode=lastNode.nextNode;
				lastNode.nextNode=newNode;
			}
			size++;
		}
		if(index==size)
		{
			add(e);
		}
	}
	public void addFirst(E e)
	{
		if(size>0)
		{
			Node newNode=new Node();
			newNode.data=e;
			newNode.nextNode=head.nextNode;
			head.nextNode=newNode;
			size++;
		}
	}
	public void addLast(E e)
	{
		Node newNode=new Node();
		newNode.data=e;
		
		if(size==0)
		{
			head.nextNode=newNode;
		}
		else
		{
			Node lastNode=new Node();
			lastNode=head.nextNode;
			for(int i=0;i<size-1;i++)
			{
				lastNode=lastNode.nextNode;
			}
			lastNode.nextNode=newNode;
		}
		
		
		newNode.nextNode=null;
		tail=newNode;
		size++;
	}
	public void clear()
	{
		head.nextNode=null;
		size=0;
	}
	public boolean contains(Object o)
	{
		boolean a=false;
		Node Node=head.nextNode;
		for(int i=0;i<size;i++)
		{
			a=(o==null ? Node.data==null : o.equals(Node.data));
			if(a==true)
			{
				return a;
			}
			Node=Node.nextNode;
		}
		return a;
	}
	public void descending()
	{
		if(size<2)
		{
			System.out.println("error");
		}
		else
		{
			Node a=head.nextNode;
			Node b=a.nextNode;
			Node c=b.nextNode;
			tail=a;
			
			b.nextNode=a;
			a.nextNode=null;
			if(size==2)
			{
				head.nextNode=b;
			}
			else
			{	while(c!=null)
				{
					b.nextNode=a;
					a=b;
					b=c;
					c=c.nextNode;
				}
			b.nextNode=a;
			head.nextNode=b;
			}
		}
		
	}
	public int indexOf(Object o)
	{
		Node Node=head.nextNode;
		for(int i=0;i<size;i++)
		{
			if(o.equals(Node.data))
			{
				return i;
			}
			Node=Node.nextNode;
		}
		return -1;
	}
	public int lastIndexOf(Object o)
	{
		Node Node=head.nextNode;
		int a=-1;
		for(int i=0;i<size;i++)
		{
			if(o.equals(Node.data))
			{
				a=i;
			}
			Node=Node.nextNode;
		}
		return a;
	}

	public E element()
	{
		return (E)head;
	}
	public E get(int index)
	{
		if(index<0||index>size)
		{
			System.out.println("error");
			return null;
		}
		else
		{
			Node get=head.nextNode;
			for(int i=0;i<index;i++)
			{
				get=get.nextNode;
			}
			return (E)get.data;
		}
	}
	public E getFirst()
	{
		if(size==0)
		{
			System.out.println("error");
			return (E)null;
		}
		else
		{
			Node a=head.nextNode;
			return (E)a.data;
		}
	}
	public E getLast()
	{
		if(size==0)
		{
			System.out.println("error");
			return (E)null;
		}
		else
		{
			Node a=tail;
			return (E)a.data;
		}
	}
	public E peekFirst()
	{
		if(size==0)
		{
			System.out.println("error");
			return (E)null;
		}
		else
		{
			return (E)head.nextNode.data;
		}
	}
	public E peekLast()
	{
		if(size==0)
		{
			System.out.println("error");
			return (E)null;
		}
		else
		{
			return (E)tail.data;
		}
	}
	public int size()
	{
		return size;
	}
	public E remove(int index)
	{
		if(index<0||index>=size)
		{
			System.out.println("error");
			return (E)null;
		}
		else
		{	Node a=head.nextNode;
			if(index==0)
			{
				head.nextNode=a.nextNode;
				a.nextNode=null;
				size--;
				return (E)a.data;
			}
			else
			{
				for(int i=0;i<index-1;i++)
				{
					a=a.nextNode;
				}
				if(index==size-1)
				{
					tail=a;
				}
				Node b=a.nextNode;
				a.nextNode=b.nextNode;
				b.nextNode=null;
				size--;
				return (E)b.data;
			}
			
		}
	}
	public boolean remove(Object o)
	{
		for(int i=0;i<size;i++)
		{
			if(o==null?get(i)==null:o.equals(get(i)))
			{
				remove(i);
				return true;
			}
		}
		return false;
	}
	public E removeFirst()
	{
		return remove(0);
	}
	public E removeLast()
	{
		return remove(size-1);
	}
	public boolean removeFirstOccurrence(Object o)
	{
			Node Node=head.nextNode;
			Node LNode=head;
			for(int i=0;i<size;i++)
			{
				if(o.equals(Node.data))
				{
					LNode.nextNode=Node.nextNode;
					Node.nextNode=null;
					size--;
					return true;
				}
				Node=Node.nextNode;
				LNode=LNode.nextNode;
			}
		return false;
	}
	public boolean removeLastOccurrence(Object o)
	{
		if(remove(lastIndexOf(o))!=null)
		{
			return true;
		}
		return false;
	}
	public E set(int index,E e)
	{
		add(index,e);
		return remove(index+1);
	}
	
	public  boolean addAll(MyLinkedlist a) 
	{
		Node newNode=a.head.nextNode;
		
		if(size==0)
		{
			head.nextNode=newNode;
		}
		else
		{
			Node lastNode=new Node();
			lastNode=head.nextNode;
			for(int i=0;i<size-1;i++)
			{
				lastNode=lastNode.nextNode;
			}
			lastNode.nextNode=newNode;
		}
		
		
		tail=a.tail;
		size+=a.size;
		return true;
	}
	public  boolean addAll(MyLinkedlist a,int index) 
	{
		
		
		if(index<0||index>size)
		{
			System.out.println("error");
		}
		else if(a.size!=0)
		{
			Node newNode=a.head.nextNode;
			if(size==0)
			{
				head.nextNode=newNode;
				tail=a.tail;
			}
			else if(index==size)
			{
				addAll(a);
			}
			else 
			{
				
				Node lastNode=head.nextNode;
				for(int i=0;i<index-1;i++)
				{
					lastNode=lastNode.nextNode;
				}
				a.tail.nextNode=lastNode.nextNode;
				lastNode.nextNode=newNode;
			}
			size+=a.size;
		}
		
		return true;
	}
	public void toMyString()
	{
		System.out.println("name:"+name+"  size:"+size);
		
		if(size==0)
		{
			System.out.println("空序列");
			System.out.println();
		}
		else
		{
			Node nowNode=head.nextNode;
			for(int i=0;i<size;i++)
			{
				System.out.print("第"+i+"位:"+nowNode.data+"   ");
				if(i%7==0&&i!=0)System.out.println();
				nowNode=nowNode.nextNode;
			}
			System.out.println();
			System.out.println();
		}
	}
	
	public static void main(String [] args)
	{
		MyLinkedlist a=new MyLinkedlist("a");
		MyLinkedlist b=new MyLinkedlist("b");
		MyLinkedlist c=new MyLinkedlist("c");
		
		for(int i=0;i<5;i++)
		{
			a.add(i*3);
			c.add(i*4);
			
		}
		b.add(0, 1);
		a.toMyString();
		b.toMyString();
		c.toMyString();
		
		System.out.println("————————————————————————add:");
		a.add(1, 1);
		b.add(1, 2);
		a.toMyString();
		b.toMyString();
		
		System.out.println("————————————————————————addAll:");
		a.addAll(b);
		a.toMyString();
		
		a.addAll(c,2);
		a.toMyString();
		
		System.out.println("————————————————————————addFirst:");
		a.addFirst(15);
		a.toMyString();
		System.out.println("————————————————————————addLast:");
		a.addLast(25);
		a.toMyString();
		
		System.out.println("————————————————————————clear:");
		b.clear();
		b.toMyString();
		
		System.out.println("————————————————————————contains(1):");
		System.out.println(a.contains(1));
		System.out.println("————————————————————————contains(null):");
		System.out.println(a.contains(null));
		
		System.out.println("————————————————————————descending(反转单向链表):");
		a.descending();
		a.toMyString();
		
		System.out.println("————————————————————————get:");
		System.out.println(a.get(2));
		System.out.println("————————————————————————getFirst:");
		System.out.println(a.getFirst());
		System.out.println("————————————————————————getLast:");
		System.out.println(a.getLast());
		
		System.out.println("————————————————————————size:");
		System.out.println(a.size());
		
		System.out.println("————————————————————————indexOf:");
		System.out.println(a.indexOf(1));
		System.out.println("————————————————————————lastIndexOf:");
		System.out.println(a.lastIndexOf(1));
		
		a.toMyString();
		System.out.println("————————————————————————remove:");
		System.out.println(a.remove(2));
		a.toMyString();
		
		System.out.println("————————————————————————remove(object):");
		int numa=2;
		System.out.println(a.remove((Object)numa));
		a.toMyString();
		
		System.out.println("————————————————————————removeFirst :");
		System.out.println(a.removeFirst());
		a.toMyString();
		
		System.out.println("————————————————————————removeLast :");
		System.out.println(a.removeLast());
		a.toMyString();
		
		System.out.println("————————————————————————removeFirstOccurrence :");
		int numb=0;
		System.out.println(a.removeFirstOccurrence(numb));
		a.toMyString();
		
		System.out.println("————————————————————————removeLastOccurrence :");
		System.out.println(a.removeFirstOccurrence(numb));
		a.toMyString();
		
		System.out.println("————————————————————————set :");
		System.out.println(a.set(3,5));
		a.toMyString();
	}
	
	
}

Node类

package Mylinkedlist;

public class Node {
	public Node nextNode=null;
	public Object data=null;
	
	
	public Node() {}
	
	public void next(Node n) 
	{
		nextNode=n;
	}
	
	public void delelte()
	{
		nextNode=null;
	}
}

运行结果:
name:a size:5
第0位:0 第1位:3 第2位:6 第3位:9 第4位:12

name:b size:1
第0位:1

name:c size:5
第0位:0 第1位:4 第2位:8 第3位:12 第4位:16

————————————————————————add:
name:a size:6
第0位:0 第1位:1 第2位:3 第3位:6 第4位:9 第5位:12

name:b size:2
第0位:1 第1位:2

————————————————————————addAll:
name:a size:8
第0位:0 第1位:1 第2位:3 第3位:6 第4位:9 第5位:12 第6位:1 第7位:2

name:a size:13
第0位:0 第1位:1 第2位:0 第3位:4 第4位:8 第5位:12 第6位:16 第7位:3
第8位:6 第9位:9 第10位:12 第11位:1 第12位:2

————————————————————————addFirst:
name:a size:14
第0位:15 第1位:0 第2位:1 第3位:0 第4位:4 第5位:8 第6位:12 第7位:16
第8位:3 第9位:6 第10位:9 第11位:12 第12位:1 第13位:2

————————————————————————addLast:
name:a size:15
第0位:15 第1位:0 第2位:1 第3位:0 第4位:4 第5位:8 第6位:12 第7位:16
第8位:3 第9位:6 第10位:9 第11位:12 第12位:1 第13位:2 第14位:25

————————————————————————clear:
name:b size:0
空序列

————————————————————————contains(1):
true
————————————————————————contains(null):
false
————————————————————————descending(反转单向链表):
name:a size:15
第0位:25 第1位:2 第2位:1 第3位:12 第4位:9 第5位:6 第6位:3 第7位:16
第8位:12 第9位:8 第10位:4 第11位:0 第12位:1 第13位:0 第14位:15

————————————————————————get:
1
————————————————————————getFirst:
25
————————————————————————getLast:
15
————————————————————————size:
15
————————————————————————indexOf:
2
————————————————————————lastIndexOf:
12
name:a size:15
第0位:25 第1位:2 第2位:1 第3位:12 第4位:9 第5位:6 第6位:3 第7位:16
第8位:12 第9位:8 第10位:4 第11位:0 第12位:1 第13位:0 第14位:15

————————————————————————remove:
1
name:a size:14
第0位:25 第1位:2 第2位:12 第3位:9 第4位:6 第5位:3 第6位:16 第7位:12
第8位:8 第9位:4 第10位:0 第11位:1 第12位:0 第13位:15

————————————————————————remove(object):
true
name:a size:13
第0位:25 第1位:12 第2位:9 第3位:6 第4位:3 第5位:16 第6位:12 第7位:8
第8位:4 第9位:0 第10位:1 第11位:0 第12位:15

————————————————————————removeFirst :
25
name:a size:12
第0位:12 第1位:9 第2位:6 第3位:3 第4位:16 第5位:12 第6位:8 第7位:4
第8位:0 第9位:1 第10位:0 第11位:15

————————————————————————removeLast :
15
name:a size:11
第0位:12 第1位:9 第2位:6 第3位:3 第4位:16 第5位:12 第6位:8 第7位:4
第8位:0 第9位:1 第10位:0

————————————————————————removeFirstOccurrence :
true
name:a size:10
第0位:12 第1位:9 第2位:6 第3位:3 第4位:16 第5位:12 第6位:8 第7位:4
第8位:1 第9位:0

————————————————————————removeLastOccurrence :
true
name:a size:9
第0位:12 第1位:9 第2位:6 第3位:3 第4位:16 第5位:12 第6位:8 第7位:4
第8位:1

————————————————————————set :
3
name:a size:9
第0位:12 第1位:9 第2位:6 第3位:5 第4位:16 第5位:12 第6位:8 第7位:4
第8位:1