JS 算法 之 链表逆置
一、什么是链表逆置?
链表逆置是最常规的链表操作,也是有关链表的最基本的算法。顾名思义,就是将链表的顺序颠倒,用一张图片来说明:
二、算法实现
1. 关于实现的思考
从后往前修改,将链表最后一个节点的next指向它的前一个节点,将倒数第二个节点的next指向它的前一个节点,以此类推…
代码如下(示例):
function reverse(node){
// 找到最后一个节点,并将最后一个节点的next指向它前面的一个节点
// 这里使用了倒数第二个节点
// 如果直接找最后一个节点,那么不知道它的前一个节点是谁,也就无法赋值,直接找倒数第二个节点,可以将它的下一个节点(最后一个节点)指向自己
if(node.next.next === null){
node.next.next = node;
return node.next;
} else {
const result = reverse(node.next);
// 如果不是最后一个节点,将它后一个节点的next指向自己
node.next.next = node;
// 将自己的next置为null,避免形成循环链表
node.next = null;
return result;
}
}
因为该方法是根据倒数第二个节点进行查找的,实际测试中会有两个问题:
- 当链表只有一个元素的时候, node.next为null,此时调用 node.next.next会报错
- 当链表只有两个元素的时候,第一个节点也就是倒数第二个节点,所以上面的代码只会进入到if中,无法修改第一个节点的next,会形成循环链遍
2.算法修正
代码如下:
function reverse(node){
if(!node) return null;
if(node.next === null) return node; // 最后一个节点逆置后必然是头节点
else {
const result = reverse(node.next);
node.next.next = node;
node.next = null;
return result;
}
}
总结
完整的测试代码
// 链表创建
function Node(value) {
this.value = value;
this.next = null;
}
Node.prototype.print = function () {
let n = this;
let str = '';
while (n) {
str += n.value;
n.next && (str += '->');
n = n.next;
}
console.log(str);
}
// 链表逆置
function reverse(node) {
if (!node) return;
if (node.next === null) return node;
else {
const result = reverse(node.next);
node.next.next = node;
node.next = null;
return result;
}
}
function createLinkedList(...arr) {
if (arr.length === 0) return;
var root = new Node(arr[0]);
let node = root;
for (let i = 1; i < arr.length; i++) {
node.next = new Node(arr[i]);
node = node.next;
}
return root;
}
// 测试
const link = createLinkedList(1, 2, 3, 4, 5);
link.print(); // 1->2->3->4->5
const newLink = reverse(link);
newLink.print(); // 5->4->3->2->1