0

伙计们,

在熟悉 TypeScript 的过程中,我遇到了让一个简单的 LinkedList 实现正常工作的严重问题。

这是源代码 - 我将在下面详细描述问题。

class LinkedList<ListType> {

     firstElement:ListItem<ListType> = null;

     /**
      * add Element in Front of List
      */
     addElementFirst(element: ListType) {
         var newItem:ListItem<ListType> = new ListItem<ListType>();

         newItem.setElement(element);
         newItem.setNextItem(this.firstElement);

         this.firstElement = newItem;
     }

    /**
     * add Element at End of List;
     */
    addElementLast(element: ListType) {

         var newItem:ListItem<ListType> = new ListItem<ListType>();
         newItem.setNextItem(null);
         newItem.setElement(element);

         //find last Element;
         var li:ListItem<ListType> = this.firstElement; //THIS IS
         while (li!=null) li=li.getNextItem(); //WHERE IT
         li = newItem; //BREAKS!
    }


    dumpListContents() {

         var li:ListItem<ListType> = this.firstElement;
        var i:number = 0; 
        while (li!=null) {
            console.log(i+". "+li.getElement());
            li=li.getNextItem(); 
            i++
        }

    }


}

class ListItem<ListType> {
    private element:ListType;
    private nextItem: ListItem<ListType>;

    setElement(element:ListType) {

        this.element=element;

    }

    getElement():ListType {

        return this.element;

    }


    setNextItem(nextItem:ListItem<ListType>) {

        this.nextItem=nextItem;


    }

    getNextItem():ListItem<ListType> {

        return this.nextItem;    

    }

}


var foo:LinkedList<string> = new LinkedList<string>();
var bar:LinkedList<string> = new LinkedList<string>();

console.log("Playing with foo");
foo.addElementFirst("first");
foo.addElementFirst("second");
foo.addElementFirst("third");

foo.dumpListContents();

console.log("Playing with bar");
bar.addElementLast("first");
bar.addElementLast("second");
bar.addElementLast("third");

bar.dumpListContents();

上面的代码使用泛型实现了一个简单的类型化 LinkedList,就像在其他 OO 语言中所做的那样。问题是 addElementFirst 完美地工作,但 addElementLast 惨败。

为什么会这样?我的强烈假设是作业

  var li:ListItem<ListType> = this.firstElement; //THIS IS
  while (li!=null) li=li.getNextItem(); //WHERE IT
  li = newItem; //BREAKS!

为局部变量赋值(而不是传递引用!),因此,随后对 addElementLast 中的数据结构所做的所有更改都是局部的,并且不对原始数据结构进行操作。生成的 JS 代码如下所示,并证实了这一假设:

 LinkedList.prototype.addElementLast = function (element) {
        var newItem = new ListItem();
        newItem.nextItem = null;
        newItem.element = element;
        //find last Element;
        var li = this.firstElement;
        while (li != null)
            li = li.nextItem;
        li = newItem;
    };

从理论上讲,我担心我认为赋值语义与这里的 Java 有很大不同,在 Java 中模拟代码可以工作,因为所有赋值都只能使用引用进行。

有没有解决这个问题的简单概念方法?我可以强制底层 JavaScript 严格使用引用吗?

最好的问候, 埃利亚斯

4

1 回答 1

2

您所做的就是将 分配newItem给局部变量li

//find last Element;
var li:ListItem<ListType> = this.firstElement;
while (li!=null) li=li.getNextItem();
//At this point, li is null.  All you're doing is assigning the newItem to your variable
li = newItem;

您需要做的是setNextItem在循环到最后一个元素后使用您的方法:

//find last Element;
var li:ListItem<ListType> = this.firstElement;
while (li.getNextItem()!=null) li=li.getNextItem();
//At this point, li is the last element
li.setNextItem(newItem);

请注意,当它为空时,我们不会分配li给下一项,因此它仍然指向列表中的最后一项。最后,如果列表没有任何元素,我们需要处理:

//find last Element;
if (this.firstElement == null) {
    this.firstElement = newItem;
} else {
    var li:ListItem<ListType> = this.firstElement;
    while (li.getNextItem()!=null) li=li.getNextItem();
    //At this point, li is the last element
    li.setNextItem(newItem);
}
于 2014-11-20T14:03:00.310 回答