单向链表
- 链表存储有序得到元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。
- 每个元素是由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针的或链接)组成。
注意:
- 相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。
- 然而,链表需要使用指针,因此实现链表时需要额外注意。
- 在数组中,我们可以直接访问任何位置的任何元素,而要想访问链表中间的一个元素,则需要从起点(表头)开始迭代链表直到找到所需的元素
举个简单的例子:
- 寻宝游戏:你有一条线索,这条线索就是指向寻找下一条线索的地点的指针,顺着这条链接去下一个地点,得到另一条指向在下一处的线索,得到链表中间的线索的唯一办法,就是从起点(第一条线索)顺着链表寻找
- 火车:一列火车是由一系列车厢组成,每节车厢都互相连接。你很容易分离一节车厢,改变它的位置,添加或移除它。每节车厢都是链表的元素,车厢间的连接就是指针。
链表类方法
- push(element)/append(element):向链表尾部添加一个新元素
- insert(position,element):向链表特殊位置插入一个新的元素
- get(position):获取对应位置的元素
- indexOf(element):返回元素在列表中的索引。如果列表中没有该元素则返回
- update(positon,element):修改某个位置的元素
- removeAt(position):从列表的特定位置移除一项
- remove(element):从列表中移除一项
- isEmpty():如果链表中不包括任何元素,会犯true,如果链表长度大于则返回false
- size():返回链表包含的元素个数。与数组length类似
实现链表:
class Node {
constructor(element) {
// 保存元素
this.element = element
// 指向下一个节点
this.next = null
}
}
class LinkedList {
constructor() {
this.head = null
this.length = 0
}
append(element):向链表尾部追加数据
append(element) { const newNode = new Node(element); // 追加到最后 if (!this.head) { this.head = newNode } else { let current = this.head; while (current.next) { current = current.next } current.next = newNode } this.length++ }
insert(position,element):向链表特殊位置插入一个新的项
insert(position, element) { //判断越界问题 if (position < 0 || position > this.length) return false // 创建新的节点 const newNode = new Node(element) // 插入元素 if (position === 0) { newNode.next = this.head this.head = newNode } else { let index = 0 let current = this.head let previous = null while (index++ < position) { previous = current current = current.next } previous.next = newNode newNode.next = current } this.length++ return true }
get(position):获取对应位置的元素
get(position) { if (position < 0 || position > this.length - 1) return null // 查找该位置的元素 let index = 0 let current = this.head while (index++ < position) { current = current.next } return current.element }
indexOf(element):返回元素在列表中的索引。如果列表中没有该元素则返回-1
indexOf(element) { // 獲取第一個元素 let current = this.head let index = 0 // 開始查找 while (current) { if (current.element === element) { return index } index++ current = current.next } return -1 }
update(positon,element):修改某个位置的元素
update(positon, element) { // 刪除position位置的元素,直接调用我们封装好的就好 const result = this.removeAt(positon) // 插入position,直接调用我们封装好的就好 this.insert(positon, element) return result }
removeAt(position):从列表的特定位置移除一项
removeAt(position) { if (position < 0 || position > this.length - 1) return null // 刪除元素 let current = this.head let previous = null let index = 0 // if (position === 0) { this.head = current.next } else { while (index++ < position) { previous = current current = current.next } previous.next = current.next } this.length-- return current.element }
remove(element):从列表中移除一项
remove(element) { // 獲取位置 const index = this.indexOf(element) if (index === -1) return // 刪除該位置的元素 this.removeAt(index) }
isEmpty():如果链表中不包括任何元素,会犯true,如果链表长度大于则返回false
isEmpty() { return this.length === 0 }
size():返回链表包含的元素个数。与数组length类似
size() { return this.length } }
测试方法是否成功
- 测试append
const linkedList = new LinkedList()
linkedList.append('aaa')
linkedList.append('bbb')
linkedList.append('ccc')
linkedList.append('ddd')
console.log(linkedList)//输出length 为4的链表,每个node有各自对应的值
- 测试insert
linkedList.insert(1, 'abc')
linkedList.insert(3, 'cba')
console.log(linkedList)//输出length 为6的链表,每个node有各自对应的值
- 測試position
console.log(linkedList.get(1))//输出abc
console.log(linkedList.get(3))//输出cba
- 測試indexof
console.log(linkedList.indexOf('abc'))//输出1
console.log(linkedList.indexOf('cba'))//输出3
console.log(linkedList.indexOf('asdsd'))//输出-1(定义查不到返回-1)
- 測試removeAt
console.log(linkedList.removeAt(3))//输出cba
console.log(linkedList.removeAt(1))//输出abc
console.log(linkedList)//此时链表length 为4 因为调用删除
- 測試update
console.log(linkedList.update(1, 'npc'))//输出bbb(注意:在这里不设置返回值,会输出undefined,但无伤大雅,已经设置)
console.log(linkedList)//此时将bbb更新为npc,链表length为4
- 測試remove
linkedList.remove('aaa')
console.log(linkedList)//此时链表length为3
- 測試isEmpty
console.log(linkedList.isEmpty())//输出false
- 測試size
console.log(linkedList.size())//输出3
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。