variable always NaN - javascript

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.

Related

Create LinkedList with JavaScript but logging the instance is not as expected

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

How does this.head gets directly updated when not updated?

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.

Implement the addInPos method inside the LinkedList prototype in Javascript

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

trouble understanding how reversing a linked list works

I'm reversing a linked list. I know it's a trivial task, but I have an understanding issue.
I'm using a class syntax in JavaScript
class LinkedList {
constructor(value) {
this.head = {
value: value,
next: null
};
this.tail = this.head;
this.length = 1;
}
append(value) {
const newNode = {
value: value,
next: null
}
this.tail.next = newNode;
this.tail = newNode;
this.length++;
return this;
}
reverse() {
if (!this.head.next) {
return this.head;
}
let first = this.head;
this.tail = this.head;
let second = first.next;
let temp = null
while(second) {
temp = second.next;
second.next = first;
first = second;
second = temp;
console.log('first', first)
}
this.head.next = null;
console.log('first after', first)
this.head = first;
return this
}
}
let myLinkedList = new LinkedList(5);
myLinkedList.append(1)
myLinkedList.append(99)
myLinkedList.reverse()
The thing I can't understand is this: after the last iteration of the while loop the first variable should point to this object (it's console.log('first', first)):
{ value: 99,
next: { value: 1, next: { value: 5, next: [Circular] } } }
However, after the loop is over, first starts pointing at
this one, which gives us the right answer (it's console.log('first after', first)):
{ value: 99,
next: { value: 1, next: { value: 5, next: null } } }
I even tried to draw diagrams but still fail to understand why it happens (why first.next.next.next starts pointing at null)
It's because of the line this.head.next = null;.
first.next.next.next and this.head point to the same node: 5.
Below is your code with some extra comments:
reverse() {
// At the start of the invocation, the linked list will be:
// head: 5
// (mid): 1
// tail: 99
if (!this.head.next) {
return this.head;
}
let first = this.head;
this.tail = this.head;
let second = first.next;
let temp = null
while(second) {
temp = second.next;
second.next = first;
first = second;
second = temp;
console.log('first', first)
}
// At this point, the `next` pointer of each node is updated together
// with `this.tail`, but `this.head` still refers to the previous head (now tail).
// `this.head` and `first.next.next.next` reference the same node '5'.
this.head.next = null;
console.log('first after', first)
// Only after this assignment will the head be updated, resulting in the following linked list:
// head: 99
// (mid): 1
// tail: 5
this.head = first;
return this
}

Doubly Linked List in javascript

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.

Categories

Resources