链表(第一周)
链表的基础知识
- 节点
- 数据域
- 链表结构
- 访问链表的时间复杂度
- 查找结点 O(n)
- 插入节点 O(1)
- 删除节点 O(1)
- 几种链表的经典实现方式
链表和数组的区别
类型 |
访问 |
添加 |
删除 |
链表 |
慢 O(n) |
快 O(1) |
快 O(1) |
数组 |
快 O(1) |
慢 O(n) |
慢 O(n) |
链表的应用场景
- 操作系统内的动态内存分配
- LRU 淘汰缓存算法
- 缓存算法是一种高速的数据结构
- 设备间存在速度差异,可以通过较多的数据存放在高速区域,而将较少的内存区域放在相对低速的区域方式,来对系统进行优化
单向链表的实现
// 单向链表
let LinkedList = function () {
// 链表元素
let Node = function (element) {
this.element = element;
this.next = null;
};
let length = 0; // 链表长度
let head = null; // 链表头节点
// 链表末尾添加元素
this.append = function (element) {
let node = new Node(element);
let cur = undefined;
if (head === null) {
head = node;
} else {
cur = head;
while (cur.next) {
cur = cur.next;
}
cur.next = node;
}
length += 1;
};
// 链表中插入元素
this.insert = function (element, index) {
let cur = head;
let node = new Node(element);
// 向链表头部添加
if (index <= 0) {
node.next = cur;
head = node;
}
// 链表尾部添加
if (index >= length) {
this.append(element);
}
// 链表中间添加
while (index-- > 1) {
cur = cur.next;
}
node.next = cur.next;
cur.next = node;
length += 1;
};
// 移出链表中指定的项
this.removeAt = function (index) {
let cur = head;
if (index >= 0 && index <= length) {
if (index === 0) head = head.next;
while (index-- > 1) {
cur = cur.next;
}
cur.next = cur.next.next;
length -= 1;
} else {
return false;
}
};
// 移出值为element的项
this.remove = function (element) {
this.removeAt(this.indexof(element));
};
// 返回 元素在链表中的索引,没有则返回-1
this.indexof = function (element) {
let cur = head;
let len = 0;
while (cur) {
if (cur.element == element) {
return len;
}
cur = cur.next;
len += 1;
}
return -1;
};
// 判断链表是否为空
this.isEmpty = function () {
return len === 0;
};
// 链表的长度
this.size = function () {
let len = 0;
let cur = head;
while (cur) {
cur = cur.next;
len += 1;
}
return length || len;
};
// 清空链表
this.clear = function () {
let cur = head;
for (let i = 0; i < length; i++) {
this.removeAt(i);
}
head = null;
length = 0;
};
// 输出整个链表
this.print = function () {
return head;
};
};
let linkedList = new LinkedList();
linkedList.append(0);
linkedList.append(1);
linkedList.append(2);
linkedList.append(4);
linkedList.insert(3, 3);
linkedList.remove(1);
// linkedList.clear()
console.log(linkedList.print(), "print");
console.log(linkedList.size(), "size");
console.log(linkedList.indexof(3), "indexof");
双向链表的实现
经典面试题
- 141 环形链表
- 142 环形链表 ||
- 202 快乐数
- 206 反转链表
- 92 反转链表 II
- 25 K 个一组翻转链表 *
- 61 旋转链表
- 24 两两交换链表中的节点
- 19 删除链表的倒数第 N 个结点
- 83 删除排序链表中的重复元素
- 82 删除排序链表中的重复元素 II
- 707 设计链表