反转单向链表
题目
定义一个函数,输入一个单向链表的头节点,反转该链表,并输出反转之后的头节点
链表
链表是一种物理结构(非逻辑结构),是数组的补充。
数组需要一段连续的内存空间,而链表不需要。
数据结构
- 单向链表
{ value, next } - 双向链表
{ value, prev, next }
两者对比
- 链表:查询慢,新增和删除较快
- 数组:查询快,新增和删除较慢
export function createLinkList(arr) {
const length = arr.length
if (length === 0) throw new Error('arr is empty')
let curNode = {
value: arr[length - 1]
}
if (length === 1) return curNode
for (let i = length - 2; i >= 0; i--) {
curNode = {
value: arr[i],
next: curNode
}
}
return curNode
}
export function reverseLinkList(listNode) {
// 定义三个指针
let prevNode = undefined;
let curNode = undefined;
let nextNode = listNode;
/**
* 第一次
* prev = undefined
* cur = undefined
* next = {value:100,next:{value:200, next: {value: 300, next: {value: 400}}}}
*
* 第二次
* prev = undefined
* cur = {value:100}
* next = {value:200, next: {value: 300, next: {value: 400}}}
*
* 第三次
* prev = {value:100}
* cur = {value:200, next: {value:100}}
* next = {value: 300, next: {value: 400}}
*
* 第四次
* prev = {value:200, next: {value:100}}
* cur = {value: 300, next: {value:200, next: {value:100}}}
* next = {value: 400}
*
* 第五次
* prev = {value: 300, next: {value:200, next: {value:100}}}
* cur = {value: 400, next: {value: 300, next: {value:200, next: {value:100}}}}
* next = undefined
*/
// 以 nextNode 为主,遍历链表
while(nextNode) {
// 第一个元素,删掉 next ,防止循环引用
if (curNode && !prevNode) {
delete curNode.next
}
// 反转指针
if (curNode && prevNode) {
curNode.next = prevNode
}
// 整体向后移动指针
prevNode = curNode
curNode = nextNode
nextNode = nextNode?.next
}
// 最后一个的补充:当 nextNode 空时,此时 curNode 尚未设置 next
curNode.next = prevNode
return curNode
}
const arr = [100, 200, 300, 400]
const list = createLinkList(arr)
const list1 = reverseLinkList(list)
console.log('list1:', list1)
扩展
思考:用数组和链表实现队列,哪个性能更好?
- 链表
- 链表和数组的不同
- 内存占用
- 查询、新增、删除的效率
- 如何保证 nextNode 不丢失
class MyQueue1 {
head = null;
tail = null;
len = 0;
add(n) {
const newNode = { value: n, next: null };
// 处理head
if (this.head == null) {
this.head = newNode;
}
// 处理tail
const tailNode = this.tail;
if (tailNode) {
tailNode.next = newNode;
}
this.tail = newNode;
this.len++;
}
delete() {
const headNode = this.head;
if (headNode == null) return null;
if (this.len <= 0) return null;
// 取值
const value = headNode.value;
// 处理head
this.head = headNode.next;
// 记录长度
this.len--;
return value;
}
get length() {
return this.len;
}
}
// 功能测试
const q = new MyQueue1();
q.add(100);
q.add(200);
q.add(300);
console.info("length1", q.length);
console.log(q.delete());