4.雙向連結串列
阿新 • • 發佈:2021-05-22
單鏈表的缺點分析:
- 單向連結串列,查詢的方向只能是一個方向,而雙向連結串列可以向前或者向後查詢;
- 單項鍊表不能自我刪除,需要靠輔助節點輔助刪除,而雙向連結串列可以實現自我刪除
在雙向連結串列中,每個節點不僅存放了下一個節點的地址,還存放了上一個節點的地址,因此,在雙向連結串列中,不僅可以實現順序遍歷,還可以實現逆序遍歷。
雙向連結串列的操作:
首先建立一個節點類,包含以下屬性:
(1)節點值:num
(2)前驅節點:pre
(3)後繼節點:next
//定義一個Node,每個Node物件就是一個節點
class Node2{
public int num;
public Node2 next; //後繼節點:指向下一個節點
public Node2 pre; //前驅節點:指向前一個節點
public Node2(int num) {
this.num = num;
}
public int getNum() {
return num;
}
}
其次,我們需要一個雙向連結串列類,連結串列類先初始化一個頭節點,並提供獲取頭節點的方法
//建立一個雙線連結串列的類
class DoubleLinkedList{
//先初始化一個頭節點,頭節點一般不要動,因為頭節點是為了指示連結串列的最頂端,如果不存在就無法找到整個連結串列
private Node2 head = new Node2(0); //不存放具體的資料
//返回頭節點
public Node2 getHead() {
return head;
}
}
定義完畢後,我們就能開始編寫雙向連結串列的操作功能了:
- 1.新增
思路:
(1)先找到雙向連結串列的最後這個節點
(2)將最後一個節點的next指向新的節點
(3)將新節點的pre指向原連結串列的最後一個節點
//新增節點,按序新增(不允許新增重複元素)
public void addNode(Node2 node){
Node2 cur = head; //令一個輔助節點從頭開始向後遍歷
while (true) {
if (cur.next == null) { //當這個節點的下一個節點為null,說明走到了連結串列的最後,
node.pre = cur; //當前節點是連結串列的最後一個節點,那麼將新節點插入連結串列的最後即可
cur.next = node;
break; //插入完成退出方法
}
else if(cur.next.num > node.getNum()){ //當某個節點的值大於新插入的節點的值時,將新節點插入
node.pre = cur; //將新節點的pre指向當前節點
node.next = cur.next; //新節點的next指向當前節點的下一個節點
cur.next.pre = node; //將當前節點的下一個節點的pre指向新插入的節點
cur.next = node; //將當前節點的next指向新插入的節點
break; //插入完成退出方法
}
else if (cur.next.num == node.getNum()){
System.out.println(node.getNum()+"已存在!");
break;
}
cur = cur.next;
}
}
- 2、遍歷
思路:遍歷的方式和單項鍊表一樣,既可以向前查詢,也可以向後查詢。
//遍歷雙向連結串列的方法
public void getList(Node2 head){
if (head.next==null){
System.out.println("連結串列空!");
return;
}
Node2 cur = head.next;
while (cur!=null){
System.out.println(cur.getNum());
cur = cur.next;
}
}
- 3.刪除
思路:
(1)直接找到要刪除的這個節點,
(2)將這個要被刪除節點的前一個節點的next指向被刪除節點的next;
- (cur.pre.next = cur.next)
(3)將被刪除節點的下一個節點的pre指向被刪除節點的前一個節點,
- (cur.next.pre = cur.pre)
但是需要注意一點,
如果要刪除的是最後一個節點,就不能再對最後一個節點的下一個節點的前驅進行賦值,否則會引起空指標異常,最後一個節點不需要這一步操作
。
//刪除節點
public void delNode(int no){
//判斷當前連結串列是否為空
if (head.next == null){
System.out.println("連結串列空!");
return;
}
Node2 cur = head.next; //輔助節點,單項鍊表中,先找待刪除節點的前一個節點才能再做刪除,雙向連結串列可以自刪除
while (true){
if (cur == null){
System.out.println("未找到值為"+no+"的節點!");
return;
}
if (cur.num == no){
cur.pre.next = cur.next;
if(cur.next != null) {
//此段程式碼不能做最後一個節點的判斷,最後一個節點的下一個節點為null,會引起空指標異常,因此最後一個節點就不需要執行以下判斷
cur.next.pre = cur.pre;
}
return;
}
cur = cur.next;
}
}
測試程式碼:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
DoubleLinkedList list = new DoubleLinkedList();
//新增元素:
for (int i = 0; i < 10; i++) {
int count = new Random().nextInt(10);
System.out.println("新增第"+i+1+"個元素:"+count);
list.addNode(new Node2(count));
}
//遍歷連結串列所有資料
System.out.println("連結串列展示:");
list.getList(list.getHead());
//刪除節點
System.out.println("輸入你要刪除的節點:");
list.delNode(sc.nextInt());
//遍歷連結串列所有資料
System.out.println("連結串列展示:");
list.getList(list.getHead());
}
到此一個雙向連結串列的基本功能就完成了。