Srujan R
Srujan R

Reputation: 19

LinkedList push() method in JavaScript with a this.tail , unable to understand the reference by value

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

class SLL {
  constructor() {
    this.head = null;
    this.tail = null;
    this.length = 0;
  }

  push(val) {
    let newNode = new Node(val)
    if (!this.head) {
      this.head = newNode;
      this.tail = this.head;
    } else {
      console.log(this.tail);
      console.log(this.tail.next);
      debugger
      this.tail.next = newNode;
      this.tail = newNode;
    }
    this.length++;
  }
}

let x = new SLL();
x.push('Hi');
x.push('Hello');
x.push('How');
x.push('Are');
x.push('You');
x.push('Man');

Doubt: After the 2nd push('Hello'), the tail is assigned with the newNode "this.tail = newNode" under else part. But in the 3rd push "push('How')" how the this.tail is still referencing the this.head.

I have done console.log of both "this.tail" and "this.tail.next".The output shows fresh node. Am not able to understand how this still reference to the this.head.

enter image description here

enter image description here

Thanks for the answers!

Usecase 1:

let l = { a : 1}
let o;
let p;

o = l;
p = o;

p.a = 2;

console.log("l",l);
console.log("o",o);
console.log("p",p);

p = { a:10};


console.log("l",l);
console.log("o",o);
console.log("p",p);

when p = {a:10} a new memory space is created right?

Now the link is broken form "p" to "o" right?

enter image description here

Upvotes: 1

Views: 180

Answers (3)

Ezekiel Muema
Ezekiel Muema

Reputation: 1

Inputs: A1, A0 ┌──────────────┐ A1 ─────────► MAND (A1, A1, 0) ───► S2 └──────────────┘

              ┌──────────────┐
 A0 ─────────► MAND (A0, A0, 0) ───► S0
              └──────────────┘

              ┌──────────────┐
 A0 ─────────► MAND (A0, 0, 0) ───► A0'
              └──────────────┘

              ┌──────────────────────┐
 A1, A0' ───► MAND (A1, A0', 0) ───► S1
              └──────────────────────┘

              ┌──────────────┐
 A1, A0 ────► MAND (A1, A0, 0) ───► S3
              └──────────────┘

Upvotes: 0

trincot
trincot

Reputation: 350781

The head references the first node in the list, but that first node will get its next property updated when a second node is added to the list. We can "see" the tail node from the head node by following the next chain.

It may help to visualise this:

When x = new SLL() has executed, we can picture it as follows:

 x
 ↓
┌─────SLL────┐
│ head: null │
│ tail: null │
│ length: 0  │
└────────────┘

When x.push('Hi'); is executed, newNode is created:

                    newNode
                     ↓
 x                 ┌─────Node────┐
 ↓                 │ val: 'Hi'   │
┌─────SLL────┐     │ next: null  │
│ head: null │     └─────────────┘
│ tail: null │
│ length: 0  │
└────────────┘

Then the if block is entered, where both this.head and this.tail are made to reference that new node, and finally the list's length property is updated:

                    newNode
                     ↓
 x                 ┌─────Node────┐
 ↓             ┌──►│ val: 'Hi'   │
┌─────SLL────┐ │ ┌►│ next: null  │
│ head: ───────┘ │ └─────────────┘
│ tail: ─────────┘
│ length: 1  │
└────────────┘

Now to the main program again, where x.push('Hello'); is executed. Again a new node is created:

                                        newNode
                                         ↓
 x                 ┌─────Node────┐     ┌─────Node────┐
 ↓             ┌──►│ val: 'Hi'   │     │ val: 'Hello'│
┌─────SLL────┐ │ ┌►│ next: null  │     │ next: null  │
│ head: ───────┘ │ └─────────────┘     └─────────────┘
│ tail: ─────────┘
│ length: 1  │
└────────────┘

This time the else block is entered, where this.tail.next = newNode; is executed. It updates the next property of the node that this.tail references:

                                        newNode
                                         ↓
 x                 ┌─────Node────┐     ┌─────Node────┐
 ↓             ┌──►│ val: 'Hi'   │ ┌──►│ val: 'Hello'│
┌─────SLL────┐ │ ┌►│ next: ────────┘   │ next: null  │
│ head: ───────┘ │ └─────────────┘     └─────────────┘
│ tail: ─────────┘
│ length: 1  │
└────────────┘

This was an important step: the linked list was extended by mutating a next property, which is happening at a node that also the head property references, and explains why you can "see" that extended list by looking at head.

In that else block the next statement, this.tail = newNode; updates the tail property of the linked list instance, and finally the length property is updated:

                                        newNode
                                         ↓
 x                 ┌─────Node────┐     ┌─────Node────┐
 ↓             ┌──►│ val: 'Hi'   │ ┌──►│ val: 'Hello'│
┌─────SLL────┐ │   │ next: ────────┘ ┌►│ next: null  │
│ head: ───────┘   └─────────────┘   │ └─────────────┘
│ tail: ─────────────────────────────┘
│ length: 2  │
└────────────┘

This process continues with the addition of the next word. Every push will mutate the next property of the tail node and make it reference a new node.

I hope this clarifies why head can "see" the changes that are made to the list as you push new elements at its end.

Upvotes: 2

Aniket Raj
Aniket Raj

Reputation: 2141

Linked list implementation with Tail address pointer

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

class SinglyLinkedList {
  constructor() {
    this.root = null;
    this.tail;
  }

  insert(value) {
    // create object of node class
    let newNode = new Node();

    if (!this.root) {
      newNode.value = value;
      this.root = newNode;
      this.tail = this.root;
      return;
    }

    let current = this.tail;
    //assign value to newNode
    newNode.value = value;

    current.next = newNode;
    //update the tail to newly inserted Node address
    this.tail = current.next;
  }

  //   To print all nodes
  printAllNodes() {
    let current = this.root;
    while (current != null) {
      console.log(current.value);
      current = current.next;
    }
  }
}

let list = new SinglyLinkedList();

list.insert(5);
list.insert(10);
list.insert(15);
list.insert(20);
list.insert(25);

list.printAllNodes();

// console.log(list.root);

Upvotes: 0

Related Questions