I was building linked list in javascript.
I dont understand one part.
function Node(element) {
this.element = element;
this.next = null;
this.previous = null;
}
function LList() {
this.head = new Node("head");
this.find = find;
this.findLast = findLast;
this.remove = remove;
this.insert = insert;
this.display = display;
this.dispReverse = dispReverse;
}
function find(item) {
var currNode = this.head;
while(currNode.element != item) {
currNode = currNode.next;
}
return currNode;
}
function display(list) {
var currNode = this.head.next;
while (currNode != null) {
console.log(currNode.element);
currNode = currNode.next;
}
}
function insert(newElement, item) {
var newNode = new Node(newElement);
var current = this.find(item);
newNode.next = current.next;
newNode.previous = current;
current.next = newNode;
// Why I dont need this part?
// Since new node got inserted, on my thoughts,
// the next node of the current node should point the new node as a previous one
// current.next.previous = newNode;
}
function remove(item) {
var currNode = this.find(item);
if (currNode.next != null) {
currNode.previous.next = currNode.next;
currNode.next.previous = currNode.previous;
currNode.next = null;
currNode.previous = null;
}
}
function findLast() {
var currNode = this.head;
while (currNode.next != null) {
currNode = currNode.next;
}
return currNode;
}
function dispReverse() {
var currNode = this.head;
currNode = this.findLast();
while(currNode.previous != null) {
console.log(currNode.element);
currNode = currNode.previous;
}
}
var cities = new LList();
cities.insert("Conway", "head");
cities.insert("Russellville", "Conway");
cities.insert("Carlisle", "Russellville");
cities.insert("Alma", "Carlisle");
cities.display();
cities.remove("Carlisle");
cities.display();
cities.dispReverse();
/*
Output should look like this:
Conway
Russellville
Carlisle
Alma
Conway
Russellville
Alma
Alma
Russellville
Conway
*/
Problem is the insert function!
Let's say if I have A B C node already.
And I want to insert K after B.
Currently, the next and previous of B are C and A for each.
The previous element of C is B.
Once I put K after B,
A B K C
(1) the next element of K will be C
(2) the previous element of K will be B.
(3) The next element of B is K
(4) previous element of C is K.
On the code I wrote in Insert function, each line of the codes below should process the upper statements.
(1) newNode.next = current.next;
(2) newNode.previous = current;
(3) current.next = newNode;
(4) current.next.previous = newNode;
But when I run this whole code including (4), error has occurred.
I don understand why...
Without the (4) line of codes, it works.
Is there anyone who can help me understand this?
You need to do step 4 before step 3:
current.next.previous = newNode
current.next = newNode
As it is, the reference of current.next (C) is being set to newNode (K) before you lookup the "old" current.next's previous property ( current.next.previous when points to B). Your reference to the current node is changed as soon as you assign it a new value. This is why current.next.previous is actually returning newNode.previous instead of the node reference you expect.
Your insert logic seems wrong in the last line :
current.next = newNode;
current.next.previous = newNode;
This actually means
newNode.previous=newNode;
Since you are setting the value of current.next to newNode in the 3rd statement
It should be :
newNode.next.previous = newNode.
Related
I intended to reverse the original LinkedList and compare it with reversed one. If it is identical return true. However, I keep getting the wrong results. Where I did wrong?
var isPalindrome = function(head) {
if(head == null || head.next == null) return true;
let reversedHead = reverse(head)
let count = 0
while (head != null && reversedHead != null) {
if(head.val != reversedHead.val) {
return false
}
head = head.next
reversedHead = reversedHead.next
}
if (head == null && reversedHead == null){
return true
} else {
return false
}
};
var reverse =(head)=> {
let prev = null
let next = new ListNode()
let curr = new ListNode()
curr = head
while(curr){
next = curr.next
curr.next = prev
prev = curr
curr = next
}
return prev
}
After you call:
let reversedHead = reverse(head)
You will have reversed the list, i.e. the head has become the tail, and a tail's next reference is null. Hence your loop will quickly end, as after:
head = head.next
... head will be null.
You need to rethink the algorithm. There are several ways to do it...
Instead of an inplace reversal, you could let reverse return a completely new linked list that will have the reversed order:
function reverse(head) { // Does not modify the given list. Returns a new one.
let node = head;
let reversedHead = null;
while (node) {
reversedHead = new ListNode(node.val, reversedHead);
node = node.next;
}
return reversedHead;
}
I assume here that the ListNode constructor accepts a second argument:
class ListNode {
constructor(val, next=null) {
this.val = val;
this.next = next;
}
}
I am learning the LinkedList data structure with JavaScript. So here is what I tried with the Chrome snippets
(function(){
function LinkedList() {
let Node = function(element) {
this.element = element;
this.next = null;
}
let head = null;
this.append = function(element) {
let node = new Node(element);
let current;
if (head == null) {
head = node;
} else {
current = head;
while(current.next){
current = current.next;
}
current.next = node;
}
}
};
let l1 = new LinkedList();
l1.append(3);
l1.append(4);
l1.append(2);
console.log(l1);
})()
Basically I created a LinkedList function with the append method, then I created a new instance named l1 and append 3 elements to it. At the end of the code, I am expecting to log the instance l1 which maybe something similar to
[
{element: 3, next: 4},
{element: 4, next: 2},
{element: 2, next:null},
]
But what I actually got is the LinkedList function rather than the new instance
LinkedList {append: ƒ}
append: ƒ (element)
So I am not sure what's my misunderstanding in between? and what might be the right way to test a LinkedList in JavaScript? Thanks
You can directly loop over the linked list to create an array.
(function(){
function LinkedList() {
let Node = function(element) {
this.element = element;
this.next = null;
}
let head = null;
this.append = function(element) {
let node = new Node(element);
let current;
if (head == null) {
head = node;
} else {
current = head;
while(current.next){
current = current.next;
}
current.next = node;
}
},
this.toArray = function(){
var arr = [];
for(var curr = head; curr != null; curr = curr.next) arr.push(curr);
return arr;
}
};
let l1 = new LinkedList();
l1.append(3);
l1.append(4);
l1.append(2);
console.log(l1.toArray());
})()
You can try console.log(l1.append(1)) But if you want to see all your data neat and clean you need to define a function in your linked list to console.log the data(or element, in your case) of each node
My LinkedList Class has two properties
this.head
this.size
this.head is used to contain the list of objects. Simple logic says, if I update this.head , its value should be updated. If I, however, assign its value to some other variable and then try to update that variable, then the original this.head shouldn't update.
Eg:
printElements(){
let current = this.head;
while(current){
console.log(current.data)
current = current.next;
}
};
But this piece of code contradicts that situation. I don't know why this.head is getting updated here when it's not directly referenced.
insertAt(data, index){
if(index > 0 && index > this.size)
return
const node = new Node(data);
let current, previous;
current = this.head;
let count = 0;
while(count < index){
previous = current;
count++;
current = current.next;
}
node.next = current;
previous.next = node;
};
The entire piece of code
class Node{
constructor(data, next = null){
this.data = data;
this.next = next;
}
}
class LinkedList{
constructor(){
this.head = null;
this.size = 0;
};
insert(data){
this.head = new Node(data, this.head);
this.size++;
};
insertAt(data, index){
if(index > 0 && index > this.size)
return
const node = new Node(data);
let current, previous;
current = this.head;
let count = 0;
while(count < index){
previous = current;
count++;
current = current.next;
}
node.next = current;
previous.next = node;
};
printElements(){
let current = this.head;
while(current){
console.log(current.data)
current = current.next;
}
};
}
Let's take a stab at minimal examples that show the behaviour you're asking about, keeping it mostly language agnostic, as this is not specific to JS.
Why doesn't this snippet print 20? It prints 10 instead.
b = new Node(20);
a = new Node(10, b);
c = a;
c = c.next;
console.log(a.data);
Why doesn't this snippet print 10? It prints 20 instead.
b = new Node(10);
a = b;
a.data = 20;
console.log(b.data);
Both of these questions arise from conflating variables and objects with each other. The two concepts are related but distinct.
When we say something like b = new Node(20);, we're declaring a variable b, instantiating an object Node(20), and referencing the object from the variable. b holds a reference to Node(20). If we say b.data = 30;, now b holds a reference to Node(30). This was the same Node as before, but its data has changed. So far, the object/variable distinction hasn't revealed itself.
We could also say a = b;, as in the second example. This means we have two variables both referencing the same Node(20) object. If we say a.data = 30;, then the object referenced by variable a's data is set to 30. So since there's only one Node object, b.data and a.data are both 30.
When we say something like c = a; c = c.next;, the Node referenced by a is still there, still referenced by a. a is like an arrow, pointing at Node(10). c is another arrow, also pointing at Node(10). c = c.next; has no impact on a. It's just changing what c is pointing to.
I need to implement the addInPos method inside the LinkedList prototype but I don't know what it is bad in my code...because the test no pass.
Implement the addInPos method inside the LinkedList prototype that must add an element in the indicated position. Both data will be provided as a parameter (pos, value). Where "pos" will be the position in which the "value" value should be added. In the event that the position in which the insertion is to be made is invalid, that is, it exceeds the size of the current list, it must return false.
If the node was added correctly return true.
Note: the zero position corresponds to the head of the LinkedList.
My code:
LinkedList.prototype.addInPos = function(pos, value) {
if(pos > this.size) {
return false;
}
const newNode = new Node(pos, value);
let current = this.head;
let previous;
if(pos === 0) {
newNode.next = current;
current.prev = newNode;
this.head = newNode;
} else {
for(let i = 0; i < pos; i++){
previous = current;
current = current.next;
}
newNode.next = current;
newNode.prev = previous;
current.prev = newNode;
previous.next = newNode;
}
}
Thanks.
With your structure ideally insertAt function would look like:
var insertAt = function(head, item, index) {
var curr = head;
var count = 0;
while (curr !== null) {
if (count === index) {
var newNode = { data: item, next: curr.next, prev: curr };
curr.next = newNode;
break;
}
count++;
curr = curr.next;
}
};
insertAt(head, 2, 3);
Let me know if this works.
Also look at this LinkedList class I have created, insertAt function is currently missing, but from this stack question, I am planning to add it in my class as well.
Class GitHub
NPM package - #dsinjs/linked-list
Complete documentation
I'm learning my way into JS (but not new to programming). So, I'm trying to implement a LinkedList just to play around with JS.
It works okay except that count always returning NaN. I've googled, and thought that the reason was I wasn't initially setting the count to a number, but I did.
Below is my code:
function LinkedList() {
var head = null,
tail = null,
count = 0;
var insert = function add(data)
{
// Create the new node
var node = {
data: data,
next: null
};
// Check if list is empty
if(this.head == null)
{
this.head = node;
this.tail = node;
node.next = null;
}
// If node is not empty
else
{
var current = this.tail;
current.next = node;
this.tail = node;
node.next = null;
}
this.count++;
};
return {
Add: insert,
};
}
var list = new LinkedList();
list.Add("A");
list.Add("B");
The this in this.count refers to to the instance of the LinkedList object.
The part:
var head = null,
tail = null,
count = 0;
These are private variables and not considered a property of the LinkedList object.
What you want to do instead is:
this.head = null;
this.tail = null;
this.count = 0;
And that will make head, tail, count a property of the LinkedList object so that you can do this.count++.
Edit: To keep head, tail, count as private to the LinkedList object, your other code would be something like this:
// Check if list is empty
if(head == null)
{
head = node;
tail = node;
node.next = null;
}
// If node is not empty
else
{
var current = tail;
current.next = node;
tail = node;
node.next = null;
}
count++;
Also keep in mind that objects are pass-by-reference. So that applies to:
var current = tail;
current.next = node;
tail = node;
node.next = null;
More: If you want count to be a public property, then instead of returning:
return {
Add: insert,
};
You need to do this:
this.Add = insert;
return this;
So that the current object context gets returned upon object creation.