链表
链表是非连续的、无序的数据结构,由一系列节点组成。
链表有很多种,今天先说一下单链表
节点: 节点包含两部分, 一部分是存储数据元素的数据域, 一部分是指向下一个节点的指针域。
下图中绿色部分是数据域, 蓝色部分是指针域。首尾节点:链表中第一个节点是首节点,最后一个节点是尾节点。
有、无头链表: 首节点没有数据域的是有头链表;首节点有数据域的是无头链表。
链表有很多种,先介绍单向无头链表。(配图是有头链表)

链表的实现
节点
节点有数据域和指向下一个节点的指针域组成
function Node(data) {
this.data = data
this.next = null
}
链表的方法
- append 添加一个新节点
- insert 向指定位置插入新节点
- remove 删除指定索引节点
- remove_head 删除首节点
- remove_tail 删除尾节点
- indexOf 返回指定节点的索引
- get 返回指定索引的节点
- head 返回首节点
- tail 返回尾节点
- length 返回链表长度
- isEmpty 判断链表是否为空
- clear 清空链表
- print 打印整条链表
insert 方法

思路:
- 要把 new_node 节点 8 插入到 2 的位置, 先找到索引为1 的节点 pre_node
- 通过 pre_node.next 找到原来索引为2 的节点 next_node
- 通过 pre_node.next 连接上 new_node
- 通过new_node.next 连接上next_node
function insert(index, data) {
if(index < 0 || index > length) {
return false
}
let new_node = new Node(data)
if(index === 0) {
new_node.next = head
}
if(index === length){ // 如果插入的位置是尾部
tail.next = new_node // 尾部节点连接上新节点
tail = new_node // tail 指针指向新节点
}else {
let pre_node = get_node(index -1) // 获取 插入位置的前一个节点
new_node.next = pre_node.next // 新节点连接上原来该位置的节点
pre_node.next = new_node // 前一个节点连接上新插入的节点
}
length++
return true
}
remove 方法

思路:
- 先找到上一个索引的节点 pre_node
- 通过 pre_node.next 要删除的节点 del_node
- 通过 pre_node.next.next 找到要删除节点的下一个节点 next_node
- 通过 pre_node.next = next_node 删除 del_node
- 通过 del_node = null 把del_node 清空
function remove(index) {
let del_node = null
if(index < 0 || index > length - 1) {
return false
}
if(index === 0) {
head = head.next
if(!head) {
tail = null
}
}else {
let pre_node = get_node(index - 1)
del_node = pre_node.next
let next_node = pre_node.next.next
pre_node.next = next_node
if(!del_node.next) { // 如果删除的是尾节点
tail = pre_node
}
}
del_node.next = null
length--
return del_node.data
}
其他 链表的方法 如下,或 查看完整链表方法
function LinkList() {
let head = null
let tail = null
let length = 0
this.append = function (data) {
let new_node = new Node(data)
if (!head) {
head = new_node
tail = new_node
} else {
tail.next = new_node
tail = new_node
}
length++
}
this.print = function () {
let curr_node = head
let link_str = ''
while (curr_node) {
link_str += curr_node.data + ' --> '
curr_node = curr_node.next
}
console.log(link_str)
console.log('length:', length)
}
function get_node(index) {
if(index < 0 || index > length - 1) {
return null
}
let curr_node = head
let node_index = index
while (node_index-- > 0) {
curr_node = curr_node.next
}
return curr_node
}
this.insert = function (index, data) {
if(index < 0 || index > length) {
return false
}
if(index === 0) {
let new_node = new Node(data)
new_node.next = head
}
if(index === length){
let new_node = new Node(data)
tail.next = new_node
tail = new_node
}else {
let pre_node = get_node(index -1)
let new_node = new Node(data)
new_node.next = pre_node.next
pre_node.next = new_node
}
length++
return true
}
this.remove = function (index) {
let del_node = null
if(index < 0 || index > length - 1) {
return false
}
if(index === 0) {
head = head.next
if(!head) {
tail = null
}
}else {
let pre_node = get_node(index - 1)
del_node = pre_node.next
let next_node = pre_node.next.next
pre_node.next = next_node
if(!del_node.next) { // 如果删除的是尾节点
tail = pre_node
}
}
del_node.next = null
length--
return del_node.data
}
this.indexOf = function (data) {
let index = 0
let curr_node = head
while (curr_node) {
if(curr_node.data === data) {
return index
}else {
curr_node = curr_node.next
}
index++
}
return -1
}
this.get = function (index) {
const curr_node = get_node(index)
return curr_node ? curr_node.data : null
}
this.clear = function () {
head = null
tail = null
length = 0
}
}