前端資料結構--線性結構-連結串列

風吹De麥浪發表於2021-04-19

連結串列

  標準陣列是一塊連續的記憶體地址,所以在做插入、刪除時會對資料進行大量的移動,如果資料量很大那麼效率會比較低。如果我們把每一個元素都記錄著下一個元素的地址,那我們在做插入、刪除時是不是隻需要改變下一個元素的地址即可, 如

 從儲存結構來看連結串列不需要一塊連續的記憶體空間,它通過“指標”將一組零散的記憶體塊串聯起來使用 

 常見的連結串列結構有單連結串列、雙向連結串列、迴圈連結串列、雙向迴圈連結串列。

單連結串列

  連結串列中的每一個節點都具備兩個功能:一個功能是儲存資料,另外一個功能是記錄下一個節點的地址。當結點只記錄下一個結點的地址且最後一個結點指向null,這種連結串列叫單連結串列。

迴圈連結串列

  迴圈連結串列是一種特殊的單連結串列。它跟單連結串列的區別就在尾結點。單連結串列的尾結點指標指向null 空地址,表示這是最後的結點,而迴圈連結串列的尾結點指標是指向連結串列的頭結點 如

雙向連結串列

  單連結串列只有一個方向,結點只有一個指向後面結點的指標,雙向連結串列支援兩個方向,一個是前面,一個是後面 如

雙向迴圈連結串列

  把迴圈連結串列、雙向連結串列組合就是雙向迴圈連結串列,結點可以指向前面、後面結點的指標,同時尾結點還指向了頭結點 如

 陣列與連結串列

陣列與連結串列是兩種不同的記憶體組織方式,陣列的特點是隨機訪問、記憶體地址連續,插入、刪除操作不需要移動元素。連結串列結點要儲存上一個結點、下一個結點的資訊(對記憶體的消耗比較大),對於插入、刪除操作只需要改變引用的指標即可。

 js 實現單連結串列

 1 /*
 2   資料是1:1的關係
 3   單向連結串列:只有指向一個方向
 4   迴圈連結串列:末尾節點指向頭部節點(跟節點) 
 5   雙向連結串列:節點存在指向上、下節點的引用
 6   雙向迴圈連結串列:把迴圈連結串列、雙向連結串列組合而成
 7 */
 8 
 9 class Node {
10   constructor (data) {
11     this.data = data
12     this.next = null
13   }
14 }
15 
16 class linkedList  {
17   constructor () {
18     this.header = null
19     this.size = 0
20   }
21   // 插入末尾
22   append (data) {
23     const addNode = new Node(data)
24     if (!this.header) {
25       this.header = addNode
26     } else {
27       const currNode = this.find()
28       currNode.next = addNode
29     }
30     this.size++
31   }
32   // 插入到x位置,其中是x索引從0開始
33   insertAt (index, data) {
34     if (index < 0 || index > this.size) {
35       throw new Error('插入的位置不正確')
36     }
37     const node = new Node(data)
38     if (index === 0) {
39       node.next = this.header
40       this.header = node
41     } else {
42       let pre = this.getNode(index - 1)
43       node.next = pre.next
44       pre.next = node
45     }
46     this.size++
47   }
48   // 刪除
49   remove (index) {
50     if (index < 0 || index >= this.size) {
51       throw new Error('超出連結串列索引')
52     }
53     
54     if (index === 0) {
55       this.header = this.header.next
56     } else {
57       const pre = this.getNode(index - 1)
58       const delNode = pre.next
59       pre.next = delNode.next
60     }
61     this.size--
62   }
63   // 通過索引獲取
64   getNode (index) {
65     if (index < 0 || index >= this.size) {
66       throw new Error('超出連結串列索引')
67     }
68     let currentNode = this.header
69     for (let i = 0; i < index; i++) {
70       currentNode = currentNode.next
71     }
72     return currentNode
73   }
74   // 獲取末尾節點
75   find () {
76     let currentNode = this.header
77     while (currentNode.next) {
78       currentNode = currentNode.next
79    }
80    return currentNode
81   }
82 }
83 
84 const linkList = new linkedList()
85 linkList.append('header')
86 linkList.append(1)
87 linkList.append(2)
88 linkList.append(3)
89 linkList.insertAt(4, 4)
90 linkList.insertAt(3, '3-before') // 插入到3的前面
91 
92 linkList.remove(4)
93 console.log(linkList)

對連結串列的插入、刪除操作,在插入第一個結點和刪除最後一個結點的情況,需要進行特殊處理,即空鏈。

預覽 codepen

 

相關文章