链表(第一周)
链表的基础知识
- 节点
- 数据域
- 链表结构
- 访问链表的时间复杂度
- 查找结点 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 设计链表