一、雙向連結串列的介紹
一種更復雜的連結串列是“雙向連結串列”或“雙面連結串列”。每個節點有兩個連結:一個指向前一個節點,當此節點為第一個節點時,指向空值;而另一個指向下一個節點,當此節點為最後一個節點時,指向空值。
上圖是雙向連結串列的結構圖,即通過上一個節點可以找到下一個,通過下一個也可以找到上一個節點。
二、雙向連結串列插入和刪除的圖解
1、插入圖解
2、刪除圖解
三、雙向連結串列的python程式碼實現
# 1、建立節點 class Node(object): # 初始化方法 def __init__(self, item): self.item= item self.next = None self.prev = None # 2、建立迴圈連結串列 class DoubleLinKList(object): # 初始化方法 def __init__(self): self._head = None # 3、判斷是否為空 def is_empty(self): """判斷連結串列是否為空""" return self._head == None # 4、求其長度 def length(self): """返回連結串列的長度""" cur = self._head count = 0 while cur != None: count += 1 cur = cur.next return count # 遍歷 def travel(self): """遍歷連結串列""" print("你要遍歷的連結串列元素有:",end=" ") cur = self._head while cur != None: print("%s "%cur.item,end=" ") cur = cur.next print("") # 5、頭插 def add(self, item): """頭部插入元素""" node = Node(item) if self.is_empty(): # 如果是空連結串列,將_head指向node self._head = node else: # 將node的next指向_head的頭節點 node.next = self._head # 將_head的頭節點的prev指向node self._head.prev = node # 將_head 指向node self._head = node # 6、尾插 def append(self, item): """尾部插入元素""" node = Node(item) if self.is_empty(): # 如果是空連結串列,將_head指向node self._head = node else: # 移動到連結串列尾部 cur = self._head while cur.next != None: cur = cur.next # 將尾節點cur的next指向node cur.next = node # 將node的prev指向cur node.prev = cur # 7、查詢 def search(self, item): """查詢元素是否存在""" cur = self._head while cur != None: if cur.item == item: return True cur = cur.next return False # 8、指定位置插入 def insert(self, pos, item): """在指定位置新增節點""" if pos <= 0 or pos>self.length()+1 : print("你輸入的位置有誤,請重新輸入") elif pos == 1: self.add(item) elif pos == self.length()+1: self.append(item) else: node = Node(item) cur = self._head count = 1 # 移動到指定位置的前一個位置 while count < (pos - 1): count += 1 cur = cur.next # 將node的prev指向cur node.prev = cur # 將node的next指向cur的下一個節點 node.next = cur.next # 將cur的下一個節點的prev指向node cur.next.prev = node # 將cur的next指向node cur.next = node # 9、刪除 def remove(self, item): """刪除元素""" if self.is_empty(): return else: cur = self._head if cur.item == item: # 如果首節點的元素即是要刪除的元素 if cur.next == None: # 如果連結串列只有這一個節點 self._head = None else: # 將第二個節點的prev設定為None cur.next.prev = None # 將_head指向第二個節點 self._head = cur.next return while cur != None: if cur.item == item: # 將cur的前一個節點的next指向cur的後一個節點 cur.prev.next = cur.next # 將cur的後一個節點的prev指向cur的前一個節點 cur.next.prev = cur.prev break cur = cur.next # 驗證 if __name__ == '__main__': double_link = DoubleLinKList() # 頭插 double_link.add(1) # 遍歷 double_link.travel() # 尾插 double_link.append(2) double_link.travel() # 按照索引插入 double_link.insert(3,4) double_link.travel() double_link.insert(3,3) double_link.travel() # 刪除 double_link.remove(3) double_link.travel()
執行結果為:
你要遍歷的連結串列元素有: 1 你要遍歷的連結串列元素有: 1 2 你要遍歷的連結串列元素有: 1 2 4 你要遍歷的連結串列元素有: 1 2 3 4 你要遍歷的連結串列元素有: 1 2 4
四、雙向連結串列的C語言程式碼實現
// main.m // 雙向連結串列 // Created by 侯壘 on 2019/6/28. // Copyright © 2019 可愛的侯老師. All rights reserved. #import <Foundation/Foundation.h> typedef struct N { int element; struct N *next; struct N *prev; }Node; // 建立節點 Node *createNode(int num) { Node *node = (Node *)malloc(sizeof(Node)); node->element = num; node->next = NULL; node->prev = NULL; return node; } // 建立雙向連結串列 Node *createDoubleLinkList(Node *node) { Node *head = node; return head; } // 判斷是否為空 int is_empty(Node *head) { if (head == NULL) { return 1; } else { return 0; } } // 求其長度 int length(Node *head) { Node *current = head; int count = 0; while (current != NULL) { count++; current = current->next; } return count; } // 遍歷 void travel(Node *head) { printf("你要遍歷的資料有:"); Node *current = head; while (current != NULL) { printf("%d ",current->element); current = current->next; } printf("\n"); } // 頭插 Node * add(Node *head,int num) { Node *node = createNode(num); if (is_empty(head)==1) { head = node; } else { node->next = head; head->prev = node; head = node; } return head; } // 尾插 Node* append(Node *head,int num) { Node *node = createNode(num); if (is_empty(head)==1) { head = node; } else { Node *current = head; while (current->next != NULL) { current = current->next; } current->next = node; node->prev = current; } return head; } // 查詢 int search(Node *head,int num) { Node *current = head; for (int i=0; i<length(head); i++) { if (current->element == num) { return i+1; } current = current->next; } return 0; } // 按指定位置插入 Node * insert(Node *head ,int index,int num) { if (index<=0||index>length(head)+1) { printf("你要插入的位置不對,請重新插入"); } else if (index == 1) { head = add(head, num); } else if (index == length(head)+1) { append(head, num); } else { Node *node = createNode(num); Node *current = head; for (int i=1; i<index-1; i++) { current = current->next; } node->prev = current; node->next = current->next; current->next->prev = node; current->next = node; } return head; } // 刪除元素 Node * removeNode(Node *head,int num) { if (is_empty(head)==1) { printf("你要刪除的連結串列為空"); } else { Node *current = head; //處理頭結點就是要刪除的節點 if (current->element == num) { if (current->next == NULL) { // 只有首節點這一個元素 head = NULL; } else { // 要刪除的是首節點,但是後面還有元素 current->next->prev = NULL; head = current->next; } } else { while (current!=NULL) { if (current->element == num) { current->prev->next = current->next; current->next->prev = current->prev; break; } current = current->next; } } } return head; } int main(int argc, const char * argv[]) { // 建立節點 Node *node = createNode(1); // 建立連結串列 Node *head = createDoubleLinkList(node); // 驗證遍歷 travel(head); // 驗證頭插 head = add(head, 0); travel(head); // 驗證尾插 head = append(head, 3); travel(head); // 驗證查詢 int index = search(head, 1); if (index != 0) { printf("你要查詢的資料在%d位置\n",index); } else { printf("沒有找到你要的資料\n"); } //驗證按指定位置插入 head = insert(head, 2, 2); travel(head); //驗證刪除 head = removeNode(head, 0); travel(head); return 0; }
執行結果為:
你要遍歷的資料有:1 你要遍歷的資料有:0 1 你要遍歷的資料有:0 1 3 你要查詢的資料在2位置 你要遍歷的資料有:0 2 1 3 你要遍歷的資料有:2 1 3