2017-03-03 6 views
0

Ich lerne derzeit Datenstrukturen und ich habe mehrere Probleme beim Versuch, LinkedList in TS zu implementieren. Ich habe mehrere Methoden hinzugefügt, aber obwohl es zu funktionieren scheint, ist die Ausgabe wirklich seltsam.LinkedList Implementierung in Typescript

Meine Fragen sind in Kommentaren.

Mein Code:

function LinkedList() {  //why doesn't fat arrow syntax work?? 
          //ie. let LinkedList =() => {...this.append =() => {}...} 
          // prints out TypeError: t.append is not a function 

let Node = (elem) => { 
    this.elem = elem; 
    this.next = null; 
} 

this.head = null; 
this.len = 0; 

this.append = (elem) => { 

    let node = new Node(elem); 
    let current; 

    if(this.head === null){ 
     this.head = node; 
    } else { 
     current = this.head; 
     while(current.next){ 
      current = current.next; 
     } 
     current.next = node; 
    } 
    this.len++; 
} 

this.removeAt = (pos) => { 
    if(pos > -1 && pos < this.len){ 
     let current = this.head; 
     let previous; 
     let index = 0; 

     if(pos === 0){ 
      this.head = current.next; 
     } else { 
      while(index++ < pos){ 
       previous = current; 
       current = current.next; 
      } 
      previous.next = current.next; 
     } 
     this.len--; 
     return current.elem; 
    } else { 
     return null; 
    } 
} 


this.insert = (elem, pos) => { 
    if(pos > -1 && pos < this.len){ 
     let current = this.head; 
     let index = 0; 
     let previous; 
     let node = new Node(elem); 

     if(pos === 0){ 
      node.next = current; 
      this.head = node; 
     } else { 
      while(index++ < pos){ 
       previous = current; 
       current = current.next; 
      } 
      node.next = current; 
      previous.next = node; 
     } 
     this.len++; 
     return true; 
    } else { 
     return false; 
    } 
} 

this.toString =() => { 
    var current = this.head; 
    var str = ''; 
    while(current){ 
     str += current.elem; //output is undefinedundefinedundefined 
       // str += JSON.stringify(current); 
       // prints out {"next":{"next":{}}}{"next":{}}{} 
     current = current.next; 
    } 
    return str; 
} 

} 

let t = new LinkedList(); 
t.append('asd'); //Doesn't work with fat arrow function declaration 
t.append(1); 
t.append(0); 
console.log(t); 
let tt = t.removeAt(1); 
console.log(t,'tt', tt); 
t.insert('asd',2); 
let ttt = t.insert('a', 1) 
console.log(ttt); 
console.log(t); 
console.log(t.toString()); 
+3

Gibt es einen Grund, warum Sie nicht Klassen verwenden Sie? –

Antwort

2

Es scheint mir, dass du das Mischen ES5-ähnliche Syntax (wo die Menschen Funktionen verwenden JavaScript Pseudo-Klassen erstellen) mit Typoskript. Das musst du nicht tun. Schreiben Sie stattdessen das korrekte Typoskript, sonst gibt es keinen Grund, TypeScript überhaupt zu verwenden.

Seien Sie auch vorsichtig mit Fett Pfeil Funktionssyntax. Der Grund, warum sie existieren, ist nicht, Funktionen zu ersetzen. In Ihrem Fall gibt es keinen wirklichen Grund, warum Sie es verwenden müssten. In der Tat, das ist, was wahrscheinlich Ihren Code zu brechen ist: Sie verwenden Ihren ursprünglichen (globalen?) Bereich als den Bereich der this innerhalb der Funktionen, nicht die LinkedList-Instanz selbst.

Eine richtige idiomatische Umsetzung das, was Sie versuchen, etwas zu tun wie dies aussehen:

class Node { 
    private elem; 
    private next; 

    constructor(elem) { 
     this.elem = elem; 
     this.next = null; 
    } 
} 

class LinkedList { 
    private head = null; 
    private len = 0; 

    public append(elem) { 
     let node = new Node(elem); 
     let current; 

     if (this.head === null) { 
      this.head = node; 
     } else { 
      current = this.head; 
      while (current.next) { 
       current = current.next; 
      } 
      current.next = node; 
     } 
     this.len++; 
    } 

    public removeAt(pos) { 
     if (pos > -1 && pos < this.len) { 
      let current = this.head; 
      let previous; 
      let index = 0; 

      if (pos === 0) { 
       this.head = current.next; 
      } else { 
       while (index++ < pos) { 
        previous = current; 
        current = current.next; 
       } 
       previous.next = current.next; 
      } 
      this.len--; 
      return current.elem; 
     } else { 
      return null; 
     } 
    } 


    public insert(elem, pos) { 
     if (pos > -1 && pos < this.len) { 
      let current = this.head; 
      let index = 0; 
      let previous; 
      let node = new Node(elem); 

      if (pos === 0) { 
       node.next = current; 
       this.head = node; 
      } else { 
       while (index++ < pos) { 
        previous = current; 
        current = current.next; 
       } 
       node.next = current; 
       previous.next = node; 
      } 
      this.len++; 
      return true; 
     } else { 
      return false; 
     } 
    } 

    public toString() { 
     var current = this.head; 
     var str = ''; 
     while (current) { 
      str += current.elem; //output is undefinedundefinedundefined 
      // str += JSON.stringify(current); 
      // prints out {"next":{"next":{}}}{"next":{}}{} 
      current = current.next; 
     } 
     return str; 
    } 
} 

let t = new LinkedList(); 
t.append('asd'); // Works fine 
t.append(1); 
t.append(0); 
console.log(t); // LinkedList 
let tt = t.removeAt(1); 
console.log(t, 'tt', tt); // LinkedList, 'tt', 1 
t.insert('asd', 2); 
let ttt = t.insert('a', 1) 
console.log(ttt); // true 
console.log(t); // LinkedList 
console.log(t.toString()); //asda0 

Aber da es keine Typanmerkung überall dient es wenig Zweck. Zumindest muss Knoten mit Anmerkungen versehen werden, damit Sie stabileren Code haben können.

Als Bonus: console.log() wird Ihre LinkedList-Instanz nicht in eine Zeichenfolge konvertieren, da sie Objekte ordnungsgemäß anzeigen kann. Stattdessen wird toString() nur automatisch verwendet, wenn JavaScript in Zeichenfolge konvertiert werden muss. So würde diese Arbeit:

console.log(t + ""); //asda0 
+0

Vielen Dank für die ausführliche Antwort. Kannst du genauer über Annotationen (Knoten) sein? – kazanDipi

+0

Ihr Code ist in TypeScript, aber er erzwingt nicht [Typen] (https://www.typescriptlang.org/docs/handbook/basic-types.html) irgendeiner Art. Sie werden Autovervollständigung erhalten, aber es ist immer noch zu dynamisch; Sie werden es keine Regeln für Sie erzwingen. Zum Beispiel wäre es für eine LinkedList sinnvoll, sie zu verwenden [generics] (https://www.typescriptlang.org/docs/handbook/generics.html), so dass Sie nur Objekte eines bestimmten hinzufügen können Geben Sie die Liste ein. Die Effizienz typengerechter Sprachen ergibt sich aus der Verwendung dieser Art von Konstrukten. – zeh

0
class Link{ 
    value: number; 
    nextNode: Link; 

    constructor(nodeValue, nodeReference){ 
     this.value = nodeValue; 
     this.nextNode = nodeReference; 
    } 
} 

class LinkedList{ 
    list: Link; 
    _length: number = 0; 
    insertLink(i: number): boolean { 
     if(this.list == null){ 
      this.list = new Link(i, null); 
      this._length++; 
      return true 
     }else{ 
      let temp = this.list; 
      while(temp.nextNode != null){ 
       temp = temp.nextNode 
      } 
      temp.nextNode = new Link(i, null); 
      this._length++; 
      return false 
     } 
    } 

    printLinkList(): void { 
     let temp = this.list; 
     if (this.list == null){ 
      console.log('empty linked list') 
     }else{ 
      while(temp.nextNode != null){ 
       console.log(temp.value); 
       temp = temp.nextNode; 
      } 
      //to show last element 
      console.log(temp.value) 
     } 
    } 

    //last occurrence of a given number 
    searchNodeByValue(i:number): number{ 
     let temp = this.list; 
     let counter = 1; 
     let position = null; 
     if(temp == null){ 
      console.log('empty list'); 
     }else{ 
      while(temp.nextNode != null){ 
       if(temp.value === i){ 
        position = counter; 
       } 
       counter++; 
       temp = temp.nextNode 
      } 
      //check if the last element of the node 
      if (temp.value === i){ 
       position = counter; 
      } 
     } 
     //console.log(position); 
     if(position == null){ 
      return 0; 
     }else{ 
      return position; 
     } 
    } 
    removeListItemByValue(i:number): boolean { 
     if(this.list == null){ 
      return true 
     }else{ 
      let itemPosition = this.searchNodeByValue(i); 
      if(itemPosition == 0){ 
       return true 
      }else{ 
       let temp = this.list; 

       //if its the first element in the stack 
       if(itemPosition == 1){ 
        this.list = this.list.nextNode; 
        return true 
       } 
       //if the element is not first or last 
       while(temp.nextNode.value != i){ 
        console.log('in here'); 
        temp = temp.nextNode; 
       } 
       temp.nextNode = temp.nextNode.nextNode 
      } 
      return true 
     } 
    } 
    removeListItemByPos(i:number): boolean { 
     let temp = this.list; 
     let counter:number = 1; 

     if(i > this._length) return false 

     if(i == 1){ 
      this.list = this.list.nextNode; 
      return true 
     } 

     while(counter != (i-1)){ 
      temp = temp.nextNode; 
      counter ++; 
     } 
     temp.nextNode = temp.nextNode.nextNode; 
    } 

    toString(): String{ 
     let current = this.list; 
     let str = ''; 
     while (current) { 
      str += current.value; //output is undefinedundefinedundefined 
      // str += JSON.stringify(current); 
      // prints out {"next":{"next":{}}}{"next":{}}{} 
      current = current.nextNode; 
     } 
     return str; 
    } 
} 

let obj = new LinkedList(); 
obj.insertLink(1); 
obj.insertLink(2); 
obj.insertLink(3); 
obj.insertLink(4); 

obj.removeListItemByPos(4); 
obj.insertLink(5); 
console.log(obj.toString())