Reputation: 19
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.
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?
Upvotes: 1
Views: 180
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
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
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