定义
单向链表是一种链式存取的数据结构,链表中的数据是以结点来表示,每个结点上包含两个部分: 数据域
与 指针域
数据域(data):保存数据
指针域(next):指向下一个结点的引用
用图来表示就是:
实现
这里一般有两种:一种是含头结点,另一种是不含头结点。下边以含头结点为例来实现单向链表。
-
结点类的构造
class Node { // 数据域 data = null; // 指针域 next = null; constructor(cdata, cnext) { this.data = cdata ? cdata : null; this.next = cnext ? cnext : null; } }
-
单向链表类(实现部分方法)
class SingleList { // 链表长度 len = 0; // 头结点 head = null; /** * 添加结点 * @param {Node} node */ add(node) { // 如果链表长度为0,则将该结点作为头结点 if (this.len == 0) { this.head = node; } else { // 否则从头结点开始遍历查找下一结点为空的结点,也就是next=null let temp = this.head; while (temp.next != null) { temp = temp.next; } // 找到并赋值 temp.next = node; } // 链表长度加1 this.len++; } /** * 插入新结点:将插入位置的上一个结点指向新结点,然后将新结点指向插入位置的下一个结点 * @param {Number} index 插入位置 * @param {Node} node */ insert(index, node) { if (index == 0) { // 在头结点处插入,将新结点作为头结点,然后再指回原头结点 let temp = this.head; this.head = node; node.next = temp; this.len++; } else if (index >= this.len) { // 超出原链表长度,调用add方法将新结点添加到末尾 this.add(node); } else { // 在其他位置插入时,先找到目标位置的结点和目标结点的上一结点 let cnode = this.forNext(index); let pnode = this.forNext(index - 1); // 将上一结点指向新结点,然后新结点指向目标位置的结点 pnode.next = node; node.next = cnode; this.len++; } } /** * 获取索引位置结点 * @param {number} index */ get(index) { // 索引合法性判断 this.checkIndex(index); return this.forNext(index); } /** * 删除索引位置结点 * @param {number} index */ delete(index) { // 索引合法性判断 this.checkIndex(index); if (index == 0) { // 如果删除头结点,将下一结点设置为头结点 this.head = this.head.next; } else { // 否则就是将目标位置的上一结点,指向目标位置结点的下一结点 let cnode = this.forNext(index - 1); cnode.next = cnode.next.next; } } /** * 循环找到对应结点 * @param {number} index */ forNext(index) { let temp = this.head; for (let i = 0; i < index; i++) { temp = temp.next; } return temp; } /** * 检查索引合法性 * @param {number} index */ checkIndex(index) { if (index < 0 || index >= this.len) { throw new Error('illegal index.'); } } }
-
部分方法图示
-
插入(insert):
(1)头部插入
(2)中间插入
-
删除(delete):
(1)删除头结点:
(2)删除中间结点:
-