您的位置:首页 > 编程语言 > Java开发

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

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

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

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

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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息