Home > database >  Is this pop() method for linked list in JavaScript correct? It works but I'm curious that if I
Is this pop() method for linked list in JavaScript correct? It works but I'm curious that if I

Time:08-29

pop(){
    if(this.head == null){
        return undefined;
    }
    else if(this.head == this.tail){
        this.head = null;
        this.tail = null;
        this.length--
    }
    else{
        let temp = this.head;
        let pre = this.head;
        while(temp.next){
            pre = temp;
            temp = temp.next;
        }
        this.tail = pre;
        this.tail.next = null;
        this.length--
    }

I'm more concerned about the condition in which there's only one item inside the linked list.

CodePudding user response:

The code is fine.

Here is a program that will test the implementation. Of course, the class needs to be completed with some other methods. The return undefined can be simplified to just return.

class Node {
    constructor(value, next=null) {
        this.value = value;
        this.next = next;
    }
}

class LinkedList {
    constructor(...values) {
        this.head = this.tail = null;
        this.length = 0;
        for (value of values) {
            this.push(value);
        }
    }
    push(value) {
        if (this.tail) {
            this.tail = this.tail.next = new Node(value);
        } else {
            this.head = this.tail = new Node(value);
        }
        this.length  ;
    }
    pop(){
        if (this.head == null){
            return;
        }
        else if (this.head == this.tail){
            this.head = null;
            this.tail = null;
            this.length--
        }
        else {
            let temp = this.head;
            let pre = this.head;
            while(temp.next){
                pre = temp;
                temp = temp.next;
            }
            this.tail = pre;
            this.tail.next = null;
            this.length--
        }
    }
    *[Symbol.iterator]() {
        for (let node = this.head; node; node = node.next) {
            yield node.value;
        }
    }
    consistent() {
        if (this.length != [...this].length) throw "length is inconsistent";
        if (this?.tail?.next) throw "tail is inconsistent";
    }
}

// Perform tests by doing the same operations on a native array simultaneously and comparing the result
let list = new LinkedList;
let arr = [];
for (let i = 0; i < 10000; i  ) {
    let choice = Math.random() > 0.5 && list.length < 10;
    let value = Math.floor(Math.random() * 100);
    if (choice) {
        list.push(value);
        arr.push(value);
    } else {
        list.pop();
        arr.pop();
    }
    list.consistent();
    if (JSON.stringify(arr) !== JSON.stringify([...list])) throw "Difference detected";
}
console.log("Tests done: all OK");

In JavaScript it is customary for pop() to return the value that was popped (this is not the case in every language, e.g. C ), as this is how the native array prototype defines pop. So you might want to consider to apply the same principle on your pop method.

Here is a version of the above code that includes that feature (and tests it):

class Node {
    constructor(value, next=null) {
        this.value = value;
        this.next = next;
    }
}

class LinkedList {
    constructor(...values) {
        this.head = this.tail = null;
        this.length = 0;
        for (value of values) {
            this.push(value);
        }
    }
    push(value) {
        if (this.tail) {
            this.tail = this.tail.next = new Node(value);
        } else {
            this.head = this.tail = new Node(value);
        }
        this.length  ;
    }
    pop() {
        if (this.head == null){
            return;
        }
        const value = this.tail.value;
        if (this.head == this.tail){
            this.head = null;
            this.tail = null;
        } else {
            let temp = this.head;
            let pre = this.head;
            while(temp.next){
                pre = temp;
                temp = temp.next;
            }
            this.tail = pre;
            this.tail.next = null;
        }
        this.length--;
        return value;
    }
    *[Symbol.iterator]() {
        for (let node = this.head; node; node = node.next) {
            yield node.value;
        }
    }
    consistent() {
        if (this.length != [...this].length) throw "length is inconsistent";
        if (this?.tail?.next) throw "tail is inconsistent";
    }
}

let list = new LinkedList;
let arr = [];
for (let i = 0; i < 10000; i  ) {
    let choice = Math.random() > 0.5 && list.length < 10;
    let value = Math.floor(Math.random() * 100);
    if (choice) {
        list.push(value);
        arr.push(value);
    } else {
        if (list.pop() !== arr.pop()) throw "Inconsistent pop return value";
    }
    list.consistent();
    if (JSON.stringify(arr) !== JSON.stringify([...list])) throw "JSON is different";
}
console.log("tests done");

CodePudding user response:

In the case when there is only one item in the list, this might not work.

This piece of code will not run:

        while(temp.next){
            pre = temp;
            temp = temp.next;
        }

The length will be reduced. But i guess you will have to point both this.head and this.tail to null, in the case length is 1.

  • Related