链表
用一组任意存储的单元来存储线性表的数据元素。一个对象存储着本身的值和下一个元素的地址。
- 需要遍历才能查询到元素,查询慢。
- 插入元素只需断开连接重新赋值,插入快。
构造函数
链表的元素都是节点,首先要构建一个节点Node类,每个节点都是Node的实例。
Node类有两个属性,一个是节点的值,一个是对下一个节点的指向(next)。
链表需要一个头节点。
添加方法
尾部添加节点
添加节点非常简单,从头节点开始,用next属性做遍历,当某个节点的next属性为null,则说明到达尾部,将尾部节点的next指向要添加的节点。1234567891011//添加节点append(newVal){let newNode = new Node(newVal);//从头结点开始走let currentNode = this.head;//结点next不为null,可往后走while(currentNode.next!=null){currentNode = currentNode.next}currentNode.next = newNode;}根据节点值查找节点
链表和数组不同,并没有indexOf方法,只能逐个遍历判断。
由于头节点没有值,将从头节点后的第一个节点开始进行。
循环条件:节点不为空且节点值和目标值不等,则循环下一个节点。
循环完毕没找到节点,返回-112345678//根据节点值查找节点findByValue(item){let currentNode = this.head.next;while(currentNode != null && currentNode.element != item){currentNode = currentNode.next;}return currentNode===null? -1 : currentNode}根据索引值获取节点
链表和数组不同,内存地址不连续,无法直接通过索引下标(链表根本不存在下标的概念)查找。
头节点之后的节点是索引0号节点,用pos变量来记录节点的索引,来和传入的index值作比较。
循环条件:节点不为空且pos和索引值不等,则循环下一个节点。
循环完毕没找到节点(index超出节点数),返回-11234567891011//根据index索引查找节点,下标从0开始findByIndex(index){//头节点之后的节点是索引0号节点let currentNode = this.head.next;let pos = 0;while(currentNode != null && pos != index){currentNode = currentNode.next;pos++}return currentNode===null ? -1: currentNode}指定元素向后插入
通过findByValue方法找到要插入的节点位置,在其后方插入新元素。1234567891011//指定元素向后插入insert(newElement, element){let currentNode = this.findByValue(element);if(currentNode === -1){console.log('未找到插入位置')return}let newNode = new Node(newElement)newNode.next = currentNode.next;currentNode.next = newNode;}删除元素
删除链表元素的方法很简单,找到要删除的元素,把它上一个节点的next指向它后一个节点即可。
那么我们需要先写一个方法来找目标节点的前一个节点。1234567891011//查找前一个节点findPrev(item){let currentNode = this.head;while(currentNode.next != null && currentNode.next.element!=item){currentNode = currentNode.next}if(currentNode.next === null){return -1}return currentNode}
之后只要让把prevNode.next指向prevNode.next.next就完成了删除。
完整代码
为了方便测试,需要写一个打印链表元素的方法。非常简单,从头节点后的节点开始遍历,将节点的element打印出来。
完整示例