2014-02-15 103 views
1

我在做链接列表数据结构。原型包括一个方法,从列表中弹出(删除)最后一项,我试图通过查找最后一个对象来完成,然后将其设置为null。它似乎没有工作。工作是将前一个对象中的引用('指针')设置为null。我仍然是一个相对JS OOP新手,不能让我的大脑理解为什么。代码:Javascript:链接列表:无法删除对象引用

function LinkedList() { 
    this._rootNode = null; 
    this._length = 0;          
} 

LinkedList.prototype = { 

    push: function(data) { 
     var newNode = { 
      data: data,          
      nextNode: null 
     }; 
     // initialize this._rootNode or subsequent .nextNode with newNode 
     this._length++; 
    }, 

    pop: function() { 
     var selectedNode, perviousNode; 

     if (this._rootNode) { 
      if (this._length > 1) { 
       selectedNode = this._rootNode; 
       while (selectedNode.nextNode) { 
        previousNode = selectedNode; // <-- shouldn't need this? 
        selectedNode = selectedNode.nextNode; 
       } 
       selectedNode = null;    // <-- doesn't delete it 
       // previousNode.nextNode = null; // <-- works (but feels unnecessary?) 
      } else { 
       this._rootNode = null; 
      } 
      this._length--; 
     } 
    }, 

    // more methods.. 
}; 


/* --- Main Prorgam --- */ 

var list = new LinkedList(); 

list.push('AAA'); 
list.push('BBB'); 
list.pop(); 
console.log(list._rootNode.nextNode.data); <-- 'BBB' still there 

希望有一些见解,以及任何其他改进功能的提示。谢谢!

回答

3

我想你知道你的push方法不起作用,但你还没有问过那个。

如果你正在做某种需要你写这样的链表的学校项目,那么一定要继续。你的问题是selectedNode并不是真正的“节点本身”,它是对它的引用,你只是将该引用设置为null,而前一个项目的指针仍然指向它,所以你实际上并没有将它从你的清单。实际上,您可以通过取消注释将指针设置为null的行设置来实现这一点,这意味着您还必须保存对前一个节点的引用。

previousNode.nextNode = null; 

你其实不想与pop()完全删除节点,你想退货。一旦删除了对调用函数中弹出节点的引用,它将成为最后一个引用,并且该对象将用于垃圾回收。这是(据我所知)所有传统的OOP语言如何处理基本级别的链表。

这使我想到下一点,即现在大多数使用的OOP语言实际上并不要求您在基本级别上工作。他们中的大多数都有库为你和Javascript实现链表,特别是在它的数组语法中实现了链表式的数据结构。 ([1,2,3,4]).pop()评估为4,([1,2,3,4]).push(5)评估为[1,2,3,4,5]。如果你真的需要在一个真实的项目中使用一个链表,不要。

+1

啊,总觉得!是的,这是一个数据结构和算法的编程练习,只是为了好玩而尝试。谢谢! – pete

+0

从列表的前面“push”和“pop”实际上会更快。为您节省了遍历它的需求。只需保存对'rootNode'的引用,将'rootNode'引用设置为'nextNode',将原始节点的'nextNode'引用设置为null并将其返回。推送相同。你需要遍历列表的唯一原因是如果你想强制执行队列而不是堆栈行为。 – citizenslave