Linked List - find Nth element at index - javascript

I'm having an issue with my code for finding an element at a specific index for a Linked List.
findElement(index) {
let currentNode = this.head;
let count = 0;
while (currentNode != null) {
if (count === index) {
return currentNode;
count++;
currentNode = currentNode.next;
}
return -1;
}
}
When I do this, I'm getting the entire linked list instead of one specific node. So if I console.log(list.findElement(0)), I get the entire linked list. But if I console log console.log(list.findElement(1)), I get -1. But what I want there is the second node. Below is the rest of my code. Not entirely sure what's wrong with my findElement function.
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
//Length
this.length = 0;
}
//Push-front
pushFront(value) {
let node = new Node(value);
node.next = this.head;
this.head = node;
this.length++;
}
//Pop-front
popFront() {
if (this.head != null) {
this.head = this.head.next;
}
this.length--;
}
//Push-back
pushBack(value) {
let node = new Node(value);
if (this.head === null) {
this.head = node;
} else {
let currentNode = this.head;
while (currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
this.length++;
}

There are a few issues with the logic in your findElement function. The primary issue is that count never changes from 0, so the function only works if the head is the sought element (e.g. index === 0) and returns -1 on any other input (this "fail" return should be moved outside of the while loop entirely).
Here's a version with count++ and currentNode = currentNode.next moved outside of the if into an implicit else:
findElement(index) {
let currentNode = this.head;
let count = 0;
while (currentNode) {
if (count === index) { // found the element
return currentNode;
}
count++; // increment counter
currentNode = currentNode.next; // move to next node
}
return -1;
}
Another issue is your popFront will decrease the length of the list to -1 if called on an empty list. The decrement should be conditional as well as the removal. This could cause harm in future implementations, but since you never use the list length, you can remove it entirely.
Putting it all together, here's a test program:
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.length = 0;
}
findElement(index) {
let currentNode = this.head;
let count = 0;
while (currentNode) {
if (count === index) {
return currentNode;
}
count++;
currentNode = currentNode.next;
}
return -1;
}
pushFront(value) {
const node = new Node(value);
node.next = this.head;
this.head = node;
this.length++;
}
popFront() {
if (this.head != null) {
this.head = this.head.next;
this.length--;
}
}
pushBack(value) {
const node = new Node(value);
if (this.head === null) {
this.head = node;
}
else {
let currentNode = this.head;
while (currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
this.length++;
}
}
const ll = new LinkedList();
ll.pushBack(1);
ll.pushBack(2);
ll.pushBack(3);
console.log(ll);
console.log(`First node: ${ll.findElement(0).value}`);
console.log(`Second node: ${ll.findElement(1).value}`);
console.log(`Third node: ${ll.findElement(2).value}`);
console.log(`Invalid index: ${ll.findElement(22).value}`);

You have a return statement as the first line of your if (count === index) conditional, which prevents further code from executing (meaning currentNode = currentNode.next will never get reached).
You're looking to move return currentNode down two lines, so that the subsequent node is referenced before the function returns.
findElement(index) {
let currentNode = this.head;
let count = 0;
while (currentNode != null) {
if (count === index) {
count++;
currentNode = currentNode.next;
return currentNode;
}
return -1;
}
}

Related

Working on my first linked list and can't get the return function to work correctly

Here is the code I have gathered and worked on so far. I can't seem to get my remove function to work correctly. It keeps saying "Cannot read properties of undefined (reading 'value') when I try to execute it on the last two lines. Any tips or help would be appreciated, thank you!
function LinkedList() {
this.head = null;
this.tail = null;
this.length = 0;
}
function Node(value) {
this.value = value;
this.next = null;
}
// adds a node to the specified index
// if index is specified, accepts parameter (value, index)
// if no index is specified then add element to the end of list
LinkedList.prototype.add = function(...value) {
if (!this.head) {
this.head = this.tail = new Node(...value);
this.length++;
return;
}
while (value.length) {
let curr = value.pop();
this.tail.next = new Node(curr);
this.tail = this.tail.next;
this.length++;
}
}
// retrieves the node at the specified index
LinkedList.prototype.get = function(index) {
if (index >= this.length) {
return -1;
}
if (index === 0) {
return this.head;
}
let previousNode = null;
let currentNode = this.head;
for (let i = 0; i < index; i++) {
if (!currentNode.next) {
break;
}
previousNode = currentNode;
currentNode = currentNode.next;
}
previousNode.next = currentNode.next;
this.length--;
return currentNode;
}
// retrieves and removes the node at the specified index
// if no index is specified, removes the last node (tail)
LinkedList.prototype.remove = function(index) {
if (this.length === 0) {
return undefined;
}
if (this.head.value === index) {
this.removeFromHead();
return this;
}
let previousNode = this.head;
let thisNode = previousNode.next;
while (thisNode) {
if (thisNode.value === index) {
break;
}
previousNode = thisNode;
thisNode = thisNode.next;
}
if (thisNode === null) {
return undefined;
}
previousNode.next = thisNode.next;
this.length--;
return this;
}
LinkedList.prototype.removeFromHead = function() {
if (this.length === 0) {
return undefined;
}
const value = this.head.value;
this.head = this.head.next;
this.length--;
return value;
}
let linkedList = new LinkedList()
linkedList.add(0);
linkedList.add(1, 0);
linkedList
console.log(linkedList.remove().value) //should return 1
console.log(linkedList.remove().value) //should return 2
I'm not all cuteseed up

LinkedList recursion problem using Javascript

Looking for help solving this recursion problem: Given a linked list of indeterminate length, composed of nodes that store a reference to the next node....how can you return the list in reverse?
For example, node A --> B --> C --> D should return D-->C-->B-->A. The function is given any node and should return that list in reverse.
A node would consist of a couple values; an integer (i) and a next property which is the pointer to the next node.
const traverseList = (node) => {
if(node.next !== null) traverseList(node);
else return;
}
I'm trying this code but it's not working. Just looking for the missing pieces, please. Thanks for any help.
you are on the right path, just print it when you are returning from each node.
const traverseList = (node) => {
if (!node) return;
traverseList(node.next);
console.log(node.value); // or whatever you want to output
}
1) Store a reference to current(initially head), next(initially null), previous(initially null) node
2) Set tail to head, if your using a tail pointer
3) Traverse this list setting next to current.next, current.next to previous, previous to current, and finally current to next
4) Depending on how you do it after the loop, you must set current.next to previous and head to current
I have included both iterative and recursive solutions below.
class Node {
constructor(value, next){
this.value = value;
this.next = next;
}
}
class LinkedList {
constructor(){
this.size = 0;
this.head = null;
this.tail = null;
}
add(value){
const node = new Node(value, null);
if(this.head === null){
this.head = node;
this.tail = node;
} else {
this.tail.next = node;
this.tail = node;
}
this.size++;
}
traverse(){
let current = this.head;
while(current != null){
console.log(current.value);
current = current.next;
}
}
reverse(){
let current = this.head;
let previous = null;
let next = null;
this.tail = current;
while(current != null && current.next != null){
next = current.next;
current.next = previous;
previous = current;
current = next;
}
current.next = previous;
this.head = current;
}
_reverseRecursively(node){
if(node == null){
return null;
}
if(node.next == null){
this.head = node;
return node;
}
let nextNode = this._reverseRecursively(node.next);
nextNode.next = node;
node.next = null;
return node;
}
reverseRecursively(){
this.tail = this.head;
this._reverseRecursively(this.head);
}
}
const list = new LinkedList();
list.add(10);
list.add(12);
list.add(14);
console.log("Original List");
list.traverse();
list.reverse();
console.log("Reversed List - using loop");
list.traverse();
list.reverseRecursively();
console.log("Reversed List - using recursion");
list.traverse();

LinkedList - Creating function that takes a value, creates a node, and add it to end of list

This is the pseudocode we have to build the LL from:
FUNCTION push(element)
CREATE node
SET node.value TO element
SET node.next TO null
IF the head node does not exist
THEN SET head to node
ELSE
SET current to head
SET current.next to node
END IF
END FUNCTION
The pseudocode itself has an error in it as well.
Below is my attempt to follow that, but right now it's pointing
to the { right after value in the push function.
let head = null,
last,
node,
current,
value = element;
const linkedList = () => {
let node = new Node(value);
push(value) {
if(head === null) {
head = last = node;
} else {
last.next = node;
last = node;
}
}
}
Error : push(value) { <----- This curly bracket is throwing the error. Unexpected token.
Beside the syntax error, you have a logical error as well. You need to treat the head node different from any other node and set the head property to node if not set, but if set, then assign to the last node the next node.
If you no head node, you can not set the last node, because there is actually no one.
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.last = null;
}
push(value) {
var node = new Node(value);
if (!this.head) {
this.head = node;
} else {
this.last.next = node;
}
this.last = node;
}
}
var ll = new LinkedList;
ll.push(10);
console.log(ll);
ll.push(11);
console.log(ll);
ll.push(12);
console.log(ll);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With check for an already inserted value.
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.last = null;
}
push(value) {
var node = new Node(value),
temp = this.head;
while (temp) {
if (temp.value === value) return;
temp = temp.next;
}
if (!this.head) {
this.head = node;
} else {
this.last.next = node;
}
this.last = node;
}
}
var ll = new LinkedList;
ll.push(10);
console.log(ll);
ll.push(11);
console.log(ll);
ll.push(12);
console.log(ll);
ll.push(11);
console.log(ll);
.as-console-wrapper { max-height: 100% !important; top: 0; }
And since we are at it.
Here is a version where you can insert append and remove nodes in ES6. No last node thougth since that would ruin the beauty of it. :)
class Node {
constructor(value) {
this.prev = null;
this.next = null;
this.value = value === undefined? null : value;
this.list = null;
}
remove() {
let prev = this.prev;
let next = this.next;
if (prev) {
prev.next = next;
}
if (next) {
next.prev = prev;
}
return this;
}
insert(node) {
let prev = this.prev;
if (prev) {
prev.next = node;
node.prev = prev;
}
this.prev = node;
node.next = this;
}
append(node) {
let next = this.next;
if (next) {
next.prev = node;
node.next = next;
}
this.next = node;
node.prev = this;
}
}
class LinkedList {
constructor() {
this.head = null;
}
get last() {
return this.list.length > 0 ? this.list[this.list.length] : null;
}
get values() {
let node = this.head;
let values = [];
while(node) {
values.push(node.value);
node = node.next;
};
return values;
}
push(node) {
node.prev = null;
node.next = null;
if (this.head) {
this.head.prev = node;
node.next = this.head;
}
this.head = node;
}
find(v) {
let node = this.head;
let fn = v;
if (!(v instanceof Function)) fn = (el) => el.value === v;
while(node && !fn(node)) {node = node.next;};
return node;
}
forEach(fn) {
let node = this.head;
while(node) {fn(node); node = node.next;};
}
}
Usable like so:
let ll = new LinkedList();
let n1= new Node(1);
let n2= new Node(2);
let n3= new Node(3);
ll.push(n1);
ll.push(n2);
ll.find(1).append(n3);
console.log(ll.values);
ll.find(3).remove();
console.log(ll.values);
ll.find(2).append(n3);
console.log(ll.values);

How to implement methods add(value, index) and remove(index) for the SinglyLinkedList

I need to implement methods for removing and adding items by index. I was able to implement only at the beginning and end of the list. I understand that I have to break an array by index, add a new element to the end of the first list. and then add another part to it? Please help
class Node{
constructor(value, next, prev){
this.value = value;
this.next = next;
this.prev = prev;
}
}
class SinglyLinkedList{
constructor(){
this.head = null;
this.tail = null;
}
addFirst(value){
let node = new Node(value, this.head, null);
if (this.head){
this.head.prev = node;
}
else {
this.tail = node;
}
this.head = node;
}
removeFirst(){
if (!this.head){
return null;
}
let value = this.head.value;
this.head = this.head.next;
if (this.head) {
this.head.prev = null;
}
else {
this.tail = null;
}
return value;
}
toString(){
let str = "";
let current = this.head;
while (current){
str += current.value + " ";
current = current.next;
}
console.log(str.trim());
}
}
The add(value, index) will look like this -
add(value, index){
let node = new Node(value, null, null);
if(!this.head){
this.head = node;
} else if(index == 0) {
node.next = this.head;
this.head = node;
} else {
let current = this.head;
let d = 1;
while(current !== NULL){
if(d === index){
node.next = current.next;
current.next = node;
break;
}
current = current.next;
d++;
}
}
return head;
}
Notice here the algorithm:
Create a new node with given value.
if the this.head is currently NULL then set the new node to this.head
if the given index is 0 then also set the node to this.head
else loop over the linked list and find the right position and set the node there
The remove(index) method will look like this:
remove(index) {
if(!this.head){
return;
}
let temp = this.head;
if(index === 0){
this.head = temp.next;
return;
}
for(let i=0;temp!==null && i<index - 1;i++){
temp = temp.next;
if(temp === null || temp->next === null){
return;
}
let next = temp.next.next;
temp.next = next;
}
}
Notice here the algorithm for remove(index) is also very similar:
if the this.head is not defined yet then return
if the node to be removed is the head then assign new head and return
else loop over the linked list until the position is found then change the next properties to remove the node at the desired position
You can implement removeAtIndex() in the following way :
removeAtIndex(index){
if (!this.head){
return null;
}
var i = 1;
var temp = this.head;
var save;
console.log(temp);
while(i < index && temp){
save = temp;
temp = temp.next;
i++;
}
if(temp){
save.next = temp.next;
} else{
save.next = undefined;
}
return temp.value;
}
Basically just iterate to that index and maintain reference to the node before it and the reference to the node after the index of node which you want to delete. And simply save the reference of next node node which you want to delete in the next of the previous node of the node which you want to delete.
You an implement add in the similar way.
In the snippet removeAtIndex() functionality is demonstrated you can make addAtIndex in the same way.
class Node{
constructor(value, next, prev){
this.value = value;
this.next = next;
this.prev = prev;
}
}
class SinglyLinkedList{
constructor(){
this.head = null;
this.tail = null;
}
addFirst(value){
let node = new Node(value, this.head, null);
if (this.head){
this.head.prev = node;
}
else {
this.tail = node;
}
this.head = node;
}
removeFirst(){
if (!this.head){
return null;
}
let value = this.head.value;
this.head = this.head.next;
if (this.head) {
this.head.prev = null;
}
else {
this.tail = null;
}
return value;
}
removeAtIndex(index){
if (!this.head){
return null;
}
var i = 1;
var temp = this.head;
var save;
while(i < index && temp){
save = temp;
temp = temp.next;
i++;
}
if(temp){
save.next = temp.next;
} else{
save.next = undefined;
}
return temp.value;
}
toString(){
let str = "";
let current = this.head;
while (current){
str += current.value + " ";
current = current.next;
}
console.log(str.trim());
}
}
list = new SinglyLinkedList();
list.addFirst(1);
list.addFirst(2);
list.addFirst(3);
list.removeAtIndex(2);
console.log(list.toString());

Why does the method of inserting a node by index not work?

I want to insert a node by index using the add () method but it does not work help fix it.
This is how the call should look like:
list.add ('2', 1); // At the list: '1', '2', '3'
But when I make a call an error is triggered:
throw new Error("Position Node Doesnt Exist!")
All my code:
class Node {
constructor(value) {
this.value = value; // value in the node
this.next = null; // link to the next node
}
}
class SinglyLinkedList {
constructor() {
/*pointer to the knot-head
(first element) of the list*/
this.head = null;
/*pointer to the node-tail
(last item) of the list*/
this.tail = null;
this.length = 0;
}
//insert to the beginning (returns the inserted value)
addFirst(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.head) {
newNode.next = this.head;
//this.head = newNode;
} else {//Linked list is empty
this.tail = newNode;
//this.head = newNode
}
//set the head to the new node
this.head = newNode;
//increment count
this.length++;
}
//insert to the end(returns the inserted value)
addLast(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.tail) {
this.tail.next = newNode;
//this.tail = newNode;
} else {
this.head = newNode;
//this.tail = newNode
}
this.tail = newNode;
//increment count
this.length++;
}
findIndex(item) {
let currentNode = this.head;
while (currentNode) {
if (currentNode.value === item) {
return currentNode;
}
currentNode = currentNode.next;
}
return null;
}
add(value, index) {
//create the new node based on the name passed
let newNode = new Node(value);
//find the position or item node we want to insert after.
let positionNode = this.findIndex(index);
if (positionNode != null) {
//first set the next pointer of new node to be that of position nodes next
newNode.next = positionNode.next;
//finally update the positionNode's next to be the new node
positionNode.next = newNode;
this.length++;
} else {
//position not found, return error
throw new Error("Position Node Doesnt Exist!")
}
}
}
let list = new SinglyLinkedList();
list.addFirst('1');
list.addLast('3');
list.add('2', 1);
console.log(list);
You are trying to compare strings with numbers in the findIndex method at:
if (currentNode.value === item) {
To allow auto type coercion, you can use the double equal operator. Or you could convert both values to the same type(number or string)
if (currentNode.value == item) {
Please find the edited working snippet below.
class Node {
constructor(value) {
this.value = value; // value in the node
this.next = null; // link to the next node
}
}
class SinglyLinkedList {
constructor() {
/*pointer to the knot-head
(first element) of the list*/
this.head = null;
/*pointer to the node-tail
(last item) of the list*/
this.tail = null;
this.length = 0;
}
//insert to the beginning (returns the inserted value)
addFirst(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.head) {
newNode.next = this.head;
//this.head = newNode;
} else {//Linked list is empty
this.tail = newNode;
//this.head = newNode
}
//set the head to the new node
this.head = newNode;
//increment count
this.length++;
}
//insert to the end(returns the inserted value)
addLast(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.tail) {
this.tail.next = newNode;
//this.tail = newNode;
} else {
this.head = newNode;
//this.tail = newNode
}
this.tail = newNode;
//increment count
this.length++;
}
findIndex(item) {
let currentNode = this.head;
while (currentNode) {
if (currentNode.value == item) {
return currentNode;
}
currentNode = currentNode.next;
}
return null;
}
add(value, index) {
//create the new node based on the name passed
let newNode = new Node(value);
//find the position or item node we want to insert after.
debugger;
let positionNode = this.findIndex(index);
if (positionNode != null) {
//first set the next pointer of new node to be that of position nodes next
newNode.next = positionNode.next;
//finally update the positionNode's next to be the new node
positionNode.next = newNode;
this.length++;
} else {
//position not found, return error
throw new Error("Position Node Doesnt Exist!")
}
}
}
let list = new SinglyLinkedList();
list.addFirst('1');
list.addLast('3');
list.add('2', 1);
console.log(list);
You could track which index you're on within findIndex instead of comparing values.
class Node {
constructor(value) {
this.value = value; // value in the node
this.next = null; // link to the next node
}
}
class SinglyLinkedList {
constructor() {
/*pointer to the knot-head
(first element) of the list*/
this.head = null;
/*pointer to the node-tail
(last item) of the list*/
this.tail = null;
this.length = 0;
}
//insert to the beginning (returns the inserted value)
addFirst(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.head) {
newNode.next = this.head;
//this.head = newNode;
} else {//Linked list is empty
this.tail = newNode;
//this.head = newNode
}
//set the head to the new node
this.head = newNode;
//increment count
this.length++;
}
//insert to the end(returns the inserted value)
addLast(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.tail) {
this.tail.next = newNode;
//this.tail = newNode;
} else {
this.head = newNode;
//this.tail = newNode
}
this.tail = newNode;
//increment count
this.length++;
}
findIndex(item) {
let currentNode = this.head;
let index = 0;
while (currentNode) {
if (index === item - 1) {
return currentNode;
}
index++;
currentNode = currentNode.next;
}
return null;
}
add(value, index) {
//create the new node based on the name passed
let newNode = new Node(value);
//find the position or item node we want to insert after.
let positionNode = this.findIndex(index);
if (positionNode != null) {
//first set the next pointer of new node to be that of position nodes next
newNode.next = positionNode.next;
//finally update the positionNode's next to be the new node
positionNode.next = newNode;
this.length++;
} else {
//position not found, return error
throw new Error("Position Node Doesnt Exist!")
}
}
}
let list = new SinglyLinkedList();
list.addFirst('1');
list.addLast('3');
list.add('2', 1);
console.log(list);
Your logics seems wrong.
The findindex function finds the item with the some value.
You call it with an index as a parameter... That is wrong.
You need a findItem method with index as parameter
if(index<0||index>length) {return null or head or tail...}
let currentNode = this.head;
let currentIndex=0;
while (currentIndex<index) {
currentNode = currentNode.next;
CurrentIndex++;
}
return currentNode;

Categories

Resources