我试图在linkedlist
中递归转发Javascript
。我试过自己并在网上搜索它。但没有成功。以下是我尝试的代码:
var Node = (function(){
function Node(val){
this.elem = val;
this.next = null;
}
return Node;
})();
var SLinkedlist = (function(){
function SLinkedlist(){
this.head = new Node("head");
}
return SLinkedlist;
})();
SLinkedlist.prototype.find = function(val){
var current = this.head;
while(current !== null && current.elem !== val){
current = current.next;
}
return current;
}
SLinkedlist.prototype.insert = function(newVal, val){
var current = this.find(val);
var newNode = new Node(newVal);
newNode.next = current.next;
current.next = newNode;
}
function reverseLinkedList(list, previous){
//We need to use the the current setting of
//list.next before we change it. We could save it in a temp variable,
//or, we could call reverseLinkedList recursively
console.log(list);
if(list !== null && list.next !==null){
reverseLinkedList(list.next, list);
}
console.log("after recursion!")
console.log(list);
//Everything after 'list' is now reversed, so we don't need list.next anymore.
//We passed previous in as an argument, so we can go ahead and set next to that.
list.next = previous;
}
reverseLinkedList(list.head, null);
任何人都可以帮助我吗?
答案 0 :(得分:2)
这是我面向对象的递归解决方案。
function Node(value) {
this.value = value;
this.next = null;
}
function SLinkedList(node) {
if (node) {
this.head = node;
} else {
this.head = null;
}
}
SLinkedList.prototype.prepend = function(node) {
node.next = this.head;
this.head = node;
}
SLinkedList.prototype.print = function() {
var arr = [];
var current = this.head;
while (current !== null) {
arr.push(current.value);
current = current.next;
}
alert(arr.join(' '));
}
SLinkedList.prototype.reverse = function() {
if (this.head === null || this.head.next === null) {
return;
}
var first = this.head;
var rest = new SLinkedList(this.head.next);
rest.reverse();
first.next.next = first;
first.next = null;
this.head = rest.head;
}
var list = new SLinkedList();
list.prepend(new Node(4));
list.prepend(new Node(3));
list.prepend(new Node(2));
list.prepend(new Node(1));
list.print();
list.reverse();
list.print();
JSFiddle:http://jsfiddle.net/5c9gtstk/1/
您的代码的一些提示,不是100%错误但我认为会有所帮助,主要是为了刷新链接列表:
next
。console.log(list)
行不会过多地讲述发生了什么,因为数据结构只包含elem
和next
,这就是为什么我写了一个打印功能。这可以帮助您调试。http://www.thatjsdude.com/interview/linkedList.html#singlyLinkedList简明扼要地解释了如何做到这一点。
至于你的反向算法,你几乎有正确的想法。我在这里给出的主要提示是绘制递归调用中发生的事情!慢慢地手动逐步执行代码。它需要几秒钟,但让所有东西都100%清晰。
具体来说,在翻转列表的其余部分后,您需要做的是list.next = previous;
吗?还有一些其他指示你需要改变。
其他人,包括这里的答案,给出了比我能给出的更好的解释。再次,图表是关键。 http://www.geeksforgeeks.org/write-a-function-to-reverse-the-nodes-of-a-linked-list/有一个很好的简短解释 - 跳过关于递归方法的部分。
我上面的2个链接各有1个浏览器页面。我鼓励你去看看。
答案 1 :(得分:1)
假设您的列表与此类似:
var list =
{
name: "1",
next: {
name: "2",
next: {
name: "3",
next: {
name: "4"
}
}
}
};
console.log("Original list");
var head = list;
while (head != undefined) {
console.log(head.name);
head = head.next;
}
呈现
Original list
1
2
3
4
您可以使用递归函数对其进行反转:
head = reverse(list, undefined);
console.log("Reverse list");
while (head != undefined) {
console.log(head.name);
head = head.next;
}
function reverse(list, prev) {
// if this is the last node, switch it with previous and return
if (list.next == undefined) {
list.next = prev;
return list;
}
// otherwise, switch it with the reverse of what is next
var ret = reverse(list.next, list);
list.next = prev;
return ret;
}
呈现
Reverse list
4
3
2
1
它是如何工作的?它基于以下原则:
Reverse([1 2 3 4]) ==
[ Reverse([2 3 4]) 1 ] ==
[ Reverse([3 4]) 2 1 ] ==
[ 4 3 2 1 ]
答案 2 :(得分:0)
这两个现有的答案为这个问题提供了很好的解决方案,但我认为知道你的代码为什么不起作用可能会有所帮助。在javascript中,当执行递归调用时,会创建一个具有自己范围的新闭包。所以在最后的电话会议中," tail"如果找到它,引用它的list
变量实际上是一个已覆盖环境中现有list
的局部变量。因此,当函数退出时,如果未返回,则对此本地list
的引用将丢失。
其他两个答案的作用是返回该值并将其存储在临时变量中(代码中的注释实际上没有用处......你需要在某处存储尾部,否则你将失去它!)
如您所知,如果所有这些都在您的反向函数中处理,则不会污染全局范围。
同样@bbill绝对正确地手动执行代码,一步一步就像Chrome devtools。这确实可以让您深入了解发生的事情。
希望这有帮助。
答案 3 :(得分:0)
要反转链表,我们可以使用简单的递归方法。将链表头部传递给下面的方法。
reverse( head ) {
if( head ) {
reverse( head.next );
console.log( head.data );
}
}
完整的工作解决方案here
答案 4 :(得分:0)
要添加到上述答案中,以下是ES6 / JavaScript中的LIFO(后进先出)链接列表实现,该函数具有递归和就地替换 列表的功能(无创建一个新列表):
class Element {
constructor(value) {
this.value = value;
this.next = null;
}
}
class List {
constructor(arr) {
this.head = null;
if (arr) {
arr.forEach(el => this.add(new Element(el)));
}
}
get length() {
return this.head ? this.countElements(1, this.head) : 0;
}
add(el) {
const element = el;
element.next = this.head;
this.head = element;
}
countElements(count, element) {
return element.next ? this.countElements(count + 1, element.next) : count;
}
toArray(arr = [], element = this.head) {
arr.push(element.value);
return element && element.next ? this.toArray(arr, element.next) : arr;
}
reverse(prev = null) {
if (this.head.next) {
const current = this.head;
this.head = this.head.next;
current.next = prev;
return this.reverse(current);
}
this.head.next = prev;
return this;
}
}
const list = new List([1, 2, 3, 4, 5, 6, 7 , 8 ,9 , 10]);
console.log(list.toArray().toString()); // returns LIFO list as array (last list el = first array el)
console.log(list.reverse().toArray().toString()); // returns LIFO list reversed as array(first first)
答案 5 :(得分:0)
您可以尝试以下方法: 我从这里参考:https://www.youtube.com/watch?v=KYH83T4q6Vs 基本上,一旦我们递归到达最后一个节点,就可以将指针从最后一个节点更改为指向上一个节点。
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
reverseLLRec(node) {
if (!node.next) {
this.head = node;
return;
}
this.reverseLLRec(node.next);
const curr = node.next;
curr.next = node;
node.next = null;
}
}
class Node {
constructor(val) {
this.val = val;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
reverseLLRec(node) {
if (!node.next) {
this.head = node;
return;
}
this.reverseLLRec(node.next);
const curr = node.next;
curr.next = node;
node.next = null;
}
insertAtLast(data) {
const node = new Node(data);
if (this.head === null) {
this.head = node;
} else {
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = node;
}
}
printList() {
let curr = this.head;
let list = [];
while (curr) {
list.push(curr.val);
curr = curr.next;
}
console.log(list);
}
}
const ll = new LinkedList();
ll.insertAtLast(1);
ll.insertAtLast(2);
ll.insertAtLast(3);
ll.insertAtLast(4);
ll.insertAtLast(5);
console.log('Before reverse:');
ll.printList();
ll.reverseLLRec(ll.head);
console.log('After reverse:');
ll.printList();