這一篇來寫循環雙鏈表,循環雙鏈表,包含兩個關鍵字:雙鏈表,循環。
先說雙鏈表,雙鏈表是在單鏈表的基礎上加上一個指向前面的指針。較之單鏈表,雙鏈表可以從任意位置進行遍歷,而不需要每一次遍歷都要從頭開始。
再說循環,我們在對普通非循環鏈表進行操作時,需要考慮鏈表的索引範圍,容易造成空指針錯誤。循環則可以規避這種情況的發生,因爲即使選擇操作的索引範圍超過鏈表的長度,鏈表會重頭繼續遍歷,可以成功規避索引越界。一般情況下,雙鏈表都是以循環的形式存在。在雙循環鏈表中,頭節點的 pre 指向尾節點,尾節點的 next 指向頭結點。
因爲在雙循環鏈表中,引用了頭結點(區別於首節點),因此對於雙循環鏈表的操作更簡單了一些,不再考慮我們所執行操作的位置是否位於首節點,以及該鏈表是否爲空。不管鏈表是否爲空,鏈表中都存在頭結點head,head可以null,可以存放鏈表相關的信息。即使鏈表爲空,head節點依然存在。
下面是關於雙循環鏈表的基本操作實現代碼,有寫得不周全的地方歡迎討論指正。
package DoubleList;
import ListLink.Node;
import ListLink.Teacher;
/*
* 循環雙鏈表
* 爲了操作方便
* 在鏈表中加入了頭結點
* 使得插入刪除操作不需要再考慮插入刪除數據是位於首節點位置以及鏈表是否爲空的情況
*
*/
public class DoubleLinkList {
public DoubleNode head; //頭結點
public int len=1; //實際節點個數
public int tmp=0; //節點位置
public DoubleLinkList()
{
head=new DoubleNode(null);
head.pre=head.next=head;
}
/*
* 頭插法插入節點
* 頭插法即插入的數據總是在頭結點之後
* 即所在位置爲head.next
*/
public void addNodeHead(Teacher teacher)
{
DoubleNode node=new DoubleNode(teacher);
node.next=head.next;
head.next.pre=node;
head.next=node;
node.pre=head;
len++;
}
/*
* 尾插法插入節點
* 尾插法即插入的數據總是在最後
* 即所在位置爲head.pre
*/
public void addNodeTail(Teacher teacher)
{
DoubleNode node=new DoubleNode(teacher);
node.next=head;
node.pre=head.pre;
head.pre.next=node;
head.pre=node;
len++;
}
//在任何節點插入數據
public void addNode(int index,Teacher teacher)
{
DoubleNode node=new DoubleNode(teacher);
DoubleNode previous=head;
DoubleNode current=head;
while(tmp!=index)
{
previous=current;
current=current.next;
tmp++;
}
node.next=current;
current.pre=node;
previous.next=node;
node.pre=previous;
tmp=0;
len++;
}
//刪除節點
public void deleteNode(int index)
{
int temp=index%len; //這一步是爲了防止將head刪除,這會導致錯誤。
DoubleNode previous=head;
DoubleNode current=head;
while(tmp!=temp)
{
previous=current;
current=current.next;
tmp++;
}
current.next.pre=previous;
previous.next=current.next;
tmp=0;
len--;
}
public void PrintAll()
{
DoubleNode node=head.next;
while(node!=head)
{
node.display();
node=node.next;
}
}
public static void main(String[] args)
{
DoubleLinkList dll=new DoubleLinkList();
Teacher teacher1=new Teacher("001","小明","男",22,"1222","wewew");
dll.addNodeHead(teacher1);
Teacher teacher2=new Teacher("002","小明","男",22,"1222","wewew");
dll.addNodeHead(teacher2);
Teacher teacher3=new Teacher("003","小明","男",22,"1222","wewew");
dll.addNodeTail(teacher3);
Teacher teacher4=new Teacher("004","小明","男",22,"1222","wewew");
dll.addNodeTail(teacher4);
// Teacher teacher5=new Teacher("005","小明","男",22,"1222","wewew");
// dll.addNode(2,teacher5);
dll.deleteNode(5);
dll.PrintAll();
}
}
package DoubleList;
import ListLink.Teacher;
public class DoubleNode {
protected DoubleNode next;
protected DoubleNode pre;
protected Teacher teacher;
public DoubleNode(Teacher teacher)
{
this.teacher=teacher;
}
public void display()
{
System.out.println(" 教工編號: "+teacher.getSno()+" 教工姓名: "+teacher.getSname()+" 性別: "+teacher.getSex()+" 年齡: "+teacher.getAge()+" 電話: "+teacher.getTel()+" 郵箱:"+teacher.getEmail());
}
}
這裏的Teacher類與之前寫的Teacher類一致,可以查看前幾章寫的Teacher類,在代碼中,也是直接引應別的包中的Teacher類。大家可以定義自己的類來測試。