一、鏈表 鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。 相比於線性表順序結構,操 ...
一、鏈表
鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。 相比於線性表順序結構,操作複雜。由於不必須按順序存儲,鏈表在插入的時候可以達到O(1)的複雜度,比另一種線性表順序表快得多,但是查找一個節點或者訪問特定編號的節點則需要O(n)的時間,而線性表和順序表相應的時間複雜度分別是O(logn)和O(1)。 使用鏈表結構可以剋服數組鏈表需要預先知道數據大小的缺點,鏈表結構可以充分利用電腦記憶體空間,實現靈活的記憶體動態管理。但是鏈表失去了數組隨機讀取的優點,同時鏈表由於增加了結點的指針域,空間開銷比較大。鏈表最明顯的好處就是,常規數組排列關聯項目的方式可能不同於這些數據項目在記憶體或磁碟上順序,數據的存取往往要在不同的排列順序中轉換。鏈表允許插入和移除表上任意位置上的節點,但是不允許隨機存取。鏈表有很多種不同的類型:單向鏈表,雙向鏈表以及迴圈鏈表。二、單鏈表介紹
單向鏈表(單鏈表)是鏈表的一種,其特點是鏈表的鏈接方向是單向的,對鏈表的訪問要通過順序讀取從頭部開始。單鏈表是一種鏈式存取的數據結構,用一組地址任意的存儲單元存放線性表中的數據元素。鏈表中的數據是以結點來表示的,每個結點的構成:元素(數據元素的映象) + 指針(指示後繼元素存儲位置),元素就是存儲數據的存儲單元,指針就是連接每個結點的地址數據。它的每個節點包含兩個域,一個信息域(元素域)和一個鏈接域。這個鏈接指向鏈表中的下一個節點,而最後一個節點的鏈接域則指向一個空值。
鏈式存儲結構的線性表將採用一組任意的存儲單元存放線性表中的數據元素。由於不需要按順序存儲,鏈表在插入、刪除數據元素時比順序存儲要快,但是在查找一個節點時則要比順序存儲要慢,使用鏈式存儲可以剋服順序線性表需要預先知道數據大小的缺點,鏈表結構可以充分利用記憶體空間,實現靈活的記憶體動態管理。但是鏈式存儲失去了數組隨機存取的特點,同時增加了節點的指針域,空間開銷較大。
三、單鏈表結構
- 表元素域elem用來存放具體的數據。
- 鏈接域next用來存放下一個節點的位置(python中的標識)
- 變數p指向鏈表的頭節點(首節點)的位置,從p出發能找到表中的任意節點。
四、單鏈表的常用操作圖解
1、頭插
2、尾插
3、指定為之插入
4、刪除
五、單鏈表的python代碼實現
# 創建節點 class Node(object): def __init__(self,item): self.element = item self.next = None # 創建單鏈表類 class SingleLinkList(object): def __init__(self): self.header = None self.length = 0 # 1、判斷是否為空 def is_empty(self): if self.header == None: return True else: return False # 2、頭部插入 def add(self,node): if self.is_empty(): self.header = node else: node.next = self.header self.header = node # currentNode = self.header self.length += 1 # 3、尾部插入 def appent(self,node): currentNode = self.header if self.is_empty(): self.add(node) else: while (currentNode.next != None): currentNode = currentNode.next currentNode.next = node self.length += 1 # 4、指定位置插入 def insert(self,node,index): currentNode = self.header if index>self.length+1 or index<=0: print("你要插入的位置不對,請重現選擇位置") if index == 1: self.add(node) elif index == 2: node.next = self.header.next self.header.next = node self.length += 1 else: for i in range(1,index-1): currentNode = currentNode.next node.next = currentNode.next currentNode.next = node self.length += 1 # 5、遍歷 def travel(self): currentNode = self.header if self.length == 0: print("你要遍歷的鏈表沒有數據\n") else: print("你要遍歷的鏈表裡面的元素有:",end=" ") for i in range(self.length): print("%s "%currentNode.element,end=" ") currentNode = currentNode.next print("\n") # 6、排序不用交換節點的位置,只需要交換節點上的數據值 def list_sort(self): for i in range(0,self.length-1): currentNode = self.header for j in range(0,self.length-i-1): if currentNode.element > currentNode.next.element: temp = currentNode.element currentNode.element = currentNode.next.element currentNode.next.element = temp currentNode = currentNode.next # 7、按索引刪除 def remove(self,index): if index<=0 or index>self.length: print("你輸入的下標不對,請重新輸入") return else: if index == 1: self.header = self.header.next currentNode = self.header elif index == 2: currentNode = self.header currentNode.next = currentNode.next.next else: currentNode = self.header for i in range(1,index-1): currentNode = currentNode.next currentNode.next = currentNode.next.next self.length -= 1 # 8、查找是否包含,並返回下標 def isContain(self,num): contain = 0 currentNode = self.header for i in range(self.length): if currentNode.element == num: print("%d在鏈表中%d處\n"%(num,i)) contain = 1 currentNode = currentNode.next if contain == 0: print("%d不在鏈表中\n"%num) # 9、根據下標找節點 def searchNodeByIndex(self,index): currentNode = self.header if index<=0 or index>self.length: print("你輸入的下標不對,請重新輸入\n") return 0 else: for i in range(index-1): currentNode = currentNode.next return currentNode # 10、根據下標修改節點的值 def modifyByIndex(self,index,num): currentNode = self.header if index<=0 or index>self.length: print("你輸入的下標不對,請重新輸入\n") else: for i in range(index-1): currentNode = currentNode.next currentNode.element = num def main(): # 創建一個節點對象 node1 = Node(1) # 創建一個單鏈表對象 single_link_list = SingleLinkList() print("驗證空鏈表的遍歷") single_link_list.travel() print("驗證頭插") single_link_list.add(node1) single_link_list.travel() print("驗證尾插") node2 = Node(2) single_link_list.appent(node2) single_link_list.travel() print("驗證按位置插入") node3 = Node(3) single_link_list.insert(node3,1) single_link_list.travel() print("繼續驗證頭插") node4 = Node(5) single_link_list.add(node4) single_link_list.travel() print("繼續驗證按位置插入") node5 = Node(4) single_link_list.insert(node5,4) single_link_list.travel() print("驗證刪除") single_link_list.remove(3) single_link_list.travel() print("驗證查找一個節點是否在鏈表中") single_link_list.isContain(8) print("驗證按下標查找節點") node = single_link_list.searchNodeByIndex(2) print("第二個節點的值為:%s"%node.element) print("\n驗證排序") single_link_list.list_sort() single_link_list.travel() print("驗證修改") single_link_list.modifyByIndex(2,10) single_link_list.travel() if __name__ == '__main__': main()
運行結果為:
驗證空鏈表的遍歷 你要遍歷的鏈表沒有數據 驗證頭插 你要遍歷的鏈表裡面的元素有: 1 驗證尾插 你要遍歷的鏈表裡面的元素有: 1 2 驗證按位置插入 你要遍歷的鏈表裡面的元素有: 3 1 2 繼續驗證頭插 你要遍歷的鏈表裡面的元素有: 5 3 1 2 繼續驗證按位置插入 你要遍歷的鏈表裡面的元素有: 5 3 1 4 2 驗證刪除 你要遍歷的鏈表裡面的元素有: 5 3 4 2 驗證查找一個節點是否在鏈表中 8不在鏈表中 驗證按下標查找節點 第二個節點的值為:3 驗證排序 你要遍歷的鏈表裡面的元素有: 2 3 4 5 驗證修改 你要遍歷的鏈表裡面的元素有: 2 10 4 5
六、單鏈表的C語言代碼實現
#include <stdio.h> typedef struct N { int element; struct N *next; }Node; // 1、創建節點 Node *createNode(int num) { Node *node; node = (Node *)malloc(sizeof(Node)); node->element = num; node->next = NULL; return node; } // 2、創建鏈表 Node *createSingleLinkList(Node *node) { Node *head = node; return head; } // 3、獲取鏈表長度 int getlength(Node *head) { if (head == NULL) { return 0; } int count = 1; Node *current = head; while (current->next != NULL) { count++; current = current->next; } return count; } // 4、頭部插入 Node * add(Node *head, Node *node) { if(head == NULL) { head = node; return head; } else { node->next = head; head = node; return head; } } // 5、尾部插入 Node * append(Node *head,Node *node) { Node *current = head; if (current->next == NULL) { add(head, node); } else { int len = getlength(head); for (int i = 0; i<len-1; i++) { current = current->next; } current->next = node; } return head; } // 6、按下標插入節點 Node * insert(Node *head,Node *node,int index) { int len = getlength(head); if (index<=0||index>len+1) { printf("你要插入的位置不對,請重現選擇位置"); } Node *current = head; if (index == 1) { head = add(head, node); } else if (index == 2) { node->next = head->next; head->next = node; } else { for (int i = 1; i<index-1; i++) { current = current->next; } node->next = current->next; current->next = node; } return head; } // 7、遍歷 void travel(Node *head) { int len = getlength(head); printf("len = %d\n",len); Node *current = head; if (len == 0) { printf("你要遍歷的鏈表沒有數據\n"); } else { printf("你要遍歷的鏈表裡面的元素有: "); for (int i = 0; i<len; i++) { printf("%d ",current->element); current = current->next; } printf("\n"); } } // 8、根據索引刪除 Node * delect(Node *head,int index) { int len = getlength(head); if (index<=0||index>len) { printf("你輸入的下標不對,請重新輸入"); return head; } else { if (index == 1) { head = head->next; } else if (index == 2) { head->next = head->next->next; } else { Node *current = head; for (int i = 1; i<index-1; i++) { current = current->next; } current->next = current->next->next; } } return head; } // 9、查找是否包含,並返回下標 void isContain(Node *head,int num) { int contain = 0; Node *current = head; int len = getlength(head); for (int i = 0; i<len; i++) { if (current->element == num) { printf("%d在鏈表中的%d處\n",num,i+1); contain = 1; } current = current->next; } if (contain == 0) { printf("%d不在鏈表中\n",num); } } // 10、根據下標找節點 Node *searchByIndex(Node *head , int index) { int len = getlength(head); Node *current = head; if (index<=0||index>len) { printf("你輸入的下標不對,請重新輸入"); return head; } else { for (int i = 0; i<index-1; i++) { current = current->next; } return current; } } // 11、根據下標修改節點的值 void modifyByIndex(Node *head,int index,int num) { int len = getlength(head); Node *current = head; if (index<=0||index>len) { printf("你輸入的下標不對,請重新輸入"); } else { for (int i = 0; i<index-1; i++) { current = current->next; } current->element = num; } } int main(int argc, const char * argv[]) { printf("==========1、創建節點==========\n"); Node * node1 = createNode(1); printf("==========2、創建單鏈表==========\n"); Node * head = createSingleLinkList(node1); travel(head); printf("==========3、驗證頭插==========\n"); Node *node2 = createNode(0); head = add(head, node2); travel(head); Node *node3 = createNode(2); head = add(head, node3); travel(head); printf("==========4、驗證尾插==========\n"); Node *node4 = createNode(4); head = append(head,node4); travel(head); Node *node5 = createNode(5); head = append(head,node5); travel(head); printf("==========5、驗證按下標插入==========\n"); Node *node6 = createNode(6); head = insert(head, node6, 1); travel(head); printf("==========6、驗證按下標刪除==========\n"); head = delect(head, 2); travel(head); printf("==========7、驗證是否包含==========\n"); isContain(head, 8); printf("==========8、驗證根據下標找節點==========\n"); Node *n = searchByIndex(head, 1); printf("第一個節點是%d\n",n->element); printf("==========9、驗證根據下標修改==========\n"); modifyByIndex(head, 3, 9); travel(head); return 0; }
運行結果為:
==========1、創建節點========== ==========2、創建單鏈表========== len = 1 你要遍歷的鏈表裡面的元素有: 1 ==========3、驗證頭插========== len = 2 你要遍歷的鏈表裡面的元素有: 0 1 len = 3 你要遍歷的鏈表裡面的元素有: 2 0 1 ==========4、驗證尾插========== len = 4 你要遍歷的鏈表裡面的元素有: 2 0 1 4 len = 5 你要遍歷的鏈表裡面的元素有: 2 0 1 4 5 ==========5、驗證按下標插入========== len = 6 你要遍歷的鏈表裡面的元素有: 6 2 0 1 4 5 ==========6、驗證按下標刪除========== len = 5 你要遍歷的鏈表裡面的元素有: 6 0 1 4 5 ==========7、驗證是否包含========== 8不在鏈表中 ==========8、驗證根據下標找節點========== 第一個節點是6 ==========9、驗證根據下標修改========== len = 5 你要遍歷的鏈表裡面的元素有: 6 0 9 4 5
寫到此處以吐血,相信你看的也會吐血!!!!