单链表与双向链表的Java实现

链表是一种物理存储单元上非连续、非顺序的存储结构。链表的机制灵活,它可以替代数组成为栈、队列的基础存储结构。链表比数组来说,没有大小限制,插入删除不基本需要移动元素。

链表的概念,就像有一群人,其中一个人举起一面旗子。而其他的人必须抓住另一个的后背,而且只能抓住一个。这样,所有的人就形成了一条人链,这个结构就是链表,而人就是链节点。

首先,我们先将链节点的代码写上:

public class Link 
{
	//id,数据,下一个
	public int id;
	public int data;
	public Link next;
	
	public Link(int id,int data)
	{
		this.id = id;
		this.data = data;
		this.next = null;
	}
	
	//显示数据
	public String displayLink()
	{
		return "<ID:" + id +",Data:" + data + ",Next:"+ (next == null?"null":next.id) + ">";
	}

}

然后,构建链表,他包括插入、删除、判空、显示、查找等方法,其代码如下:

public class LinkedList
{
	//链表头
	private Link first;
	
	public LinkedList()
	{
		first = null;
	}
	
	//显示整个链表
	public void displayLinkedList()
	{
		Link current =first;
		StringBuffer sb = new StringBuffer("");
		
		if(current == null )
			sb.append("链表为空。");
		else
			sb.append("链表如下:\n");
		
		while(current != null)
		{
			sb.append(current.displayLink()+"\n");
			current = current.next;
		}
		System.out.println(sb.toString());
	}
	
	//插入
	public void insertFrist(int id,int data)
	{
		Link newLk = new Link(id,data);
		newLk.next = first;
		first = newLk;
	}
	
	//删除
	public Link delectFrist()
	{
		if(!isEmpty())
		{
			Link tempLk = first;
			first = first.next;
			return tempLk;
		}
		else 
			throw new IndexOutOfBoundsException("链表已空");
	}
	
	//判空
	public boolean isEmpty()
	{
		return first == null;
	}
	
	//查找特定元素
	public Link find(int data)
	{
		Link current =first;
		
		while(current != null)
		{
			if(current.data == data)
				return current;
			current = current.next;
		}
		return null;
	}
	
	//删除特定元素
	public Link delete(int data)
	{
		Link current = first;
		Link crtParent = null; 
		
		while(current != null)
		{
			if(current.data == data)
			{
				if(crtParent == null)
					first = first.next;
				else
					crtParent.next = current.next;
				return current;
			}
			crtParent = current;
			current = current.next;
		}
		return null;
	}
	
	public static void main(String[] args) {
		LinkedList ll = new LinkedList();
		ll.insertFrist(1, 0); 
		ll.insertFrist(2, 11);
		ll.insertFrist(3, 9);
		ll.insertFrist(4, 93);
		ll.insertFrist(5, 12);
		ll.insertFrist(6, 16);
		ll.displayLinkedList();
	}
}

这是一个单链表类,只能通过next后继遍历元素,大家可以看出,链头插入元素只需要修改next标志位,不需要移动后面的元素,我们测试一下:

链表如下:
<ID:6,Data:16,Next:5>
<ID:5,Data:12,Next:4>
<ID:4,Data:93,Next:3>
<ID:3,Data:9,Next:2>
<ID:2,Data:11,Next:1>
<ID:1,Data:0,Next:null>

另外,如果单链表中各元素都是有序的,那就叫有序链表,我们为其编写一个新的有序插入方法,其代码如下:

	//插入有序
	public void insertForSort(int id,int data)
	{
		Link current = first;
		Link crtParent = null; 
		Link newLk = new Link(id,data);
		
		while(current != null && current.data <= data)
		{
			crtParent = current;
			current = current.next;
		}
		
		if(crtParent == null)
			first = newLk;
		else
			crtParent.next = newLk;
		newLk.next = current;
	}

将mian方法中的insertFrist修改为insertForSort。测试一下,结果如下:

链表如下:
<ID:1,Data:0,Next:3>
<ID:3,Data:9,Next:2>
<ID:2,Data:11,Next:5>
<ID:5,Data:12,Next:6>
<ID:6,Data:16,Next:4>
<ID:4,Data:93,Next:null>

还有种链表叫双向链表,它的链节点中不仅包括后继next,还包括前继prev,所以他不仅可以从前遍历,还可以从后便遍历,但其代码比单链表的复杂,这里我们将id和data合并成key,链节点代码如下:

public class DuoLink {
	//Key,后继,前继
	public int key;
	public DuoLink next;
	public DuoLink prev;
	
	public DuoLink(int key)
	{
		this.key = key;
		this.next = null;
		this.prev = null;
	}
	
	public String displayLink()
	{
		return "<Key:" + key + ",Next:"+(next==null?"null":next.key)+ ",Prev:"+(prev == null?"null":prev.key)+">";
	}
}

双向链表代码如下:

public class DuoLinkedList {
	//链表头、链表尾
	private DuoLink first;
	private DuoLink last;
	
	public DuoLinkedList(){
		first = null;
		last = null;
	}
	
	//判空
	public boolean isEmpty(){
		return first == null;
	}
	
	//查找
	public DuoLink find(int key)
	{
		DuoLink current = first;
		while(current != null && key != current.key)
		{
			current = current.next;
		}
		return current;
	}
	
	//表头插入
	public void insertFirst(int in)
	{
		DuoLink newDL = new DuoLink(in);
		if(first == null)
			last = newDL;
		else
		{
			first.prev = newDL;
			newDL.next = first;
		}
		first = newDL;
	}
	
	//表尾插入
	public void insertLast(int in)
	{
		DuoLink newDL = new DuoLink(in);
		if(last == null)
			first = newDL;
		else
		{
			newDL.prev = last;
			last.next = newDL;
		}
		last = newDL;
		
	}
	
	//在key后插入
	public void insertAfter(int key,int in) throws Exception
	{
		DuoLink find = find(key);//找到元素
		DuoLink newDL = new DuoLink(in);
		if(find == null)
			throw new Exception("no find");
		else if(find == last)
			insertLast(in);
		else
		{
			find.next.prev = newDL;
			newDL.prev = find;
			newDL.next = find.next;
			find.next = newDL;
		}
	}
	
	//删除表头元素
	public DuoLink deleteFirst() throws Exception
	{
		if(isEmpty())
			throw new Exception("空链表");
		if(first.next == null)
			last = null;
		else
			first.next.prev = null;
		first = first.next;
		return first;
	}
	
	//删除表尾元素
	public DuoLink deleteLast() throws Exception
	{
		if(isEmpty())
			throw new Exception("空链表");
		if(last.prev == null)
			first = null;
		else
			last.prev.next = null;
		last = last.prev;
		return last;
	}
	
	//删除元素
	public DuoLink delete(int key) throws Exception
	{
		DuoLink find = find(key);
		if(find == null)
			throw new Exception("没有找到!");
		else if(find == first)
			deleteFirst();
		else if(find == last)
			deleteLast();
		else
		{
			find.prev.next = find.next;
			find.next.prev = find.prev;
			find.next = null;
			find.prev = null;
		}
		return find;
	}
	
	//从头到尾显示
	public void displayFromFirst()
	{
		DuoLink cr = first;
		StringBuffer sb = new StringBuffer("");
		while(cr != null)
		{
			sb.append(cr.displayLink()+"\n");
			cr = cr.next;
		}
		System.out.println(sb.toString());
	}
	
	//从尾到头显示
	public void displayFromLast()
	{
		DuoLink cr = last;
		StringBuffer sb = new StringBuffer("");
		while(cr != null)
		{
			sb.append(cr.displayLink()+"\n");
			cr = cr.prev;
		}
		System.out.println(sb.toString());
	}
	
	//测试
	public static void main(String[] args) throws Exception {
		DuoLinkedList dll = new DuoLinkedList();
		dll.insertFirst(9);
		dll.insertFirst(4);
		dll.insertFirst(6);
		dll.insertFirst(3);
		dll.delete(4);
		dll.displayFromFirst();
	}
	
}

我们来测试一下:

<Key:3,Next:6,Prev:null>
<Key:6,Next:9,Prev:3>
<Key:9,Next:null,Prev:6>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值