数据结构-链表

# 链表

通常由一连串节点组成, 每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接("links").

wikipedia: https://zh.wikipedia.org/wiki/%E9%93%BE%E8%A1%A8 (opens new window)

点击查看代码
/**
 * 链表
 */
class Node {
  constructor(name) {
    this.name = name
    this.next = null
  }
}

class LinkedList {
  constructor() {
    this.head = new Node('head')
  }

  // 添加节点
  append(name) {
    const newNode = new Node(name)
    let currentNode = this.head
    while(currentNode.next) {
      currentNode = currentNode.next
    }

    currentNode.next = newNode
  }

  // 插入节点
  insert(name, node) {
    if (!node || node === -1) {
      return false
    }

    const newNode = new Node(name)
    newNode.next = node.next
    node.next = newNode
  }

  // 删除节点
  remove(node) {
    const prevNode = this.findPrev(node)

    if (prevNode === -1) {
      return false
    }

    prevNode.next = prevNode.next.next
  }

  // 查找前一个节点
  findPrev(node) {
    let currentNode = this.head.next
    while (currentNode && currentNode.next !== node) {
      currentNode = currentNode.next
    }

    return currentNode === null ? -1 : currentNode
  }

  // 通过 name 查找节点
  findByName(name) {
    let currentNode = this.head.next
    while(currentNode !== null && currentNode.name !== name) {
      currentNode = currentNode.next
    }

    return currentNode === null ? -1 : currentNode
  }

  // 通过 index 查找节点
  findByIndex(index) {
    let currentNode = this.head.next
    let pos = 0

    while(currentNode !== null && pos !== index) {
      currentNode = currentNode.next
      pos++
    }

    return currentNode
  }

  // 查找中间节点
  findMidNode() {
    let fast = this.head,
      slow = this.head
    while(
      fast.next !== null && fast.next.next !== null
    ) {
      fast = fast.next.next
      slow = slow.next
    }

    return slow
  }

  // 反转链表
  reverse() {
    let root = new Node('head'),
      currentNode = this.head.next

    while(currentNode !== null) {
      const next = currentNode.next
      currentNode.next = root.next

      // 后移
      root.next = currentNode
      currentNode = next
    }

    this.head = root
  }
}

// ---------- Test ---------
let list = new LinkedList()
list.append('append1')
list.append('append2')

const findNode = list.findByName('append2')

list.insert('append3', findNode)
list.append('append4')
list.remove(list.findByName('append4'))

console.log(list)
// LinkedList {
//   head: Node {
//     name: "head",
//     next: Node {
//       name: "append1",
//       next: Node {
//         name: "append2",
//         next: Node {
//           name: "append3",
//           next: null
//         }
//       }
//     }
//   }
// }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140