Detailed explanation of JavaScript single linked list (add, delete, change, check and reverse order)

Posted by stew on Thu, 09 Dec 2021 16:13:19 +0100

1,addNode(val): Add elements at the end of the linked list( val Is the value of the node.

2,Length(): The length of the linked list.

3,display(): Print the linked list.

4,ModifyValue(val1,val2): Replaces the specified value.

5,findValue(val): Finds the specified value,Return to its location.

6,DeleteValue(val): Deletes the specified node.

7,ModifyLc(location,val): Modify the value of the specified location.

8,insert(location,val): Adds an element to the specified location.

9,ReverseOrder():In reverse order.

Single linked list and node.

A linked list is a series of cells storing data elements connected in series by pointers, so each cell has at least two fields,
One field is used for the storage of data elements, and the other field is a pointer to other units.
Here, a storage unit with one data field and multiple pointer fields is usually called a node

The simplest node structure is shown in the figure. It is the basic node structure of a single linked list. In the node, the data field is used to store data elements,
The pointer field is used to point to the next node with the same structure.

characteristic

An important feature of a single linked list is that it can only find subsequent nodes through the precursor nodes, but can not find the precursor nodes from the subsequent nodes.

Advantages and disadvantages

advantage:

1. Linked list is a dynamic data structure, so it can grow and shrink by allocating and deallocating memory at run time. Therefore, there is no need to give the initial size of the linked list.

2. The insertion and deletion of nodes is really easy. Unlike arrays, we don't have to move elements after they are inserted or deleted. In the linked list, we only need to update the address existing in the next pointer of the node.

3. Since the size of the linked list can be increased or decreased at run time, memory will not be wasted. In the case of arrays, a lot of memory will be wasted. For example, if we declare an array with a size of 10 and store only 6 elements in it, we will waste 4 elements of space. There is no such problem in the linked list because memory is allocated only when needed.

Disadvantages:

1. Storing elements in a linked list requires more memory than arrays. Because in the linked list, each node contains a pointer, and it itself needs additional memory.

2. It is difficult to traverse elements or nodes in a linked list. We can't randomly access any elements like in an array by index. For example, if we want to access a node at location n, we must traverse all nodes before it. Therefore, it takes a lot of time to access the node.

3. In a linked list, reverse traversal is really difficult. In the case of double linked list, it is easier, but the backward pointer requires additional memory, so it wastes memory.

1,addNode(val)

1. When inserting an element at the end, if the head is empty (length=0), that is, the linked list is empty, we only need to point the head node to the newly created node.

2. If the linked list is not empty, we just need to find the last node and point its next to the newly created node.

//Add an element at the end of the linked list (val is the value of the node)
 ListNode.prototype.addNode = function(val){
     //Create nodes to add
     let newNode = new Node(val);
    //Judge whether the linked list is empty. If it is not empty, add an element after the linked list, otherwise it is the head node
    if(this.length==0){
        this.head=newNode;
    }else{
        let head1 = this.head;
        while(head1.next!==null){//Find the tail of the linked list
        head1 = head1.next;
    }
    head1.next = newNode;//Add a node to the end of the linked list
    }
    this.length++;//The corresponding length increases after adding nodes
 }

2,Length()

The length of the linked list. Since the length attribute in the linked list will be updated when we add and delete nodes, the value of length is the length of the linked list.

ListNode.prototype.Length = function(){
     return this.length;//Return its length, which is the length of the linked list
 }

3,display()

We build an array to save the traversal results of the linked list. If the current pointer is not empty, we store its value in the array, and then move the pointer to the next position. Until it is empty, you can traverse all the values in the linked list.

 //Print linked list
 ListNode.prototype.display = function(){
    let head1 = this.head;
    let res  = [];//Save the values in the traversed linked list with an array
    let i = 0;
    while(head1!==null){//Traverse the linked list in turn and store the values in the array
        res[i] = head1.val;
        head1 = head1.next;
        i++;
    }
    return res;
 }

4,ModifyValue(val1,val2)

When replacing a value, we first find the location of the value, and then modify its value.

//Replace specified value
 ListNode.prototype.ModifyValue = function(val1,val2){//Replace val1 with val2
     let location = this.findValue(val1);//Find the location of val1
     if(location==false){//If it is not found, false is returned
         return false;
     }
     let head1 = this.head;//If found, find the node and replace the value
     while(head1!==null&&location>1){
         head1 = head1.next;
         location--;
     }
     head1.val = val2;
 }

5,findValue(val)

When finding the specified value, we search the position of the specified value by traversing all the values in the linked list in turn, and return its relative position by calculating several traversed values.

//Finds the specified value and returns its location
 ListNode.prototype.findValue = function(val){
    let head1 = this.head;
    let count = 0;
    while(head1!==null){//Traverse the linked list in turn
        if(head1.val==val){//If found, return to its location
            count++;
            return count;
        }else{//If you don't find it, keep looking down;
            head1 = head1.next;
            count++;
        }
    }
    return false;//After traversal, false is returned if it is not found
 }

6,DeleteValue(val)

We'd better find the location of the specified value first. If we don't find it, it means that there is no value in the linked list.

If you find a header node, you only need to point its header pointer to its next node:

Otherwise, find the previous node and the next node to delete:

Then point the previous node to the next node to delete:

//Delete specified node
 ListNode.prototype.DeleteValue = function(val){
    let location = this.findValue(val);//Find the location of val
    if(location==false){//If it is not found, it returns false
        return false;
    }
    let head1 = this.head;
    let head2 = null;
    if(location==1){//If you need to delete the head node, you can directly point the head node to the next node
        this.head=this.head.next;
        this.length--;
    }else{
        while(location>2&&head1.next!==null){//Otherwise, find its previous node
            head1 = head1.next;
            location--;
        }
        head2 = head1.next.next;//Find his next node
        head1.next = head2;//Connect its previous and next nodes together
        this.length--;
    }
    
}

7,ModifyLc(location,val)

Directly find the location to be modified, and then modify its value to val.

//Modify the value at the specified location
 ListNode.prototype.ModifyLc = function(location,val){
     location = location-1;//The starting position starts from 0, while the normal position starts from 1
    if(this.length<location||location<0){ //Judge whether it is out of bounds
        return false;
    }
    if(location==0){//Change the value of the header node
        this.head.val = val
    }else{//Change the following value
        let count = 0;
        let head1 = this.head;
        while(count<location&&head1!==null){//Find the location that needs to be modified
        head1 = head1.next;
        count++;
    }
    head1.val=val;//Modify the value after finding the specified location
    }
 }

8,insert(location,val)

If inserted in the head:

Insert in the middle or tail:

Before insertion:

After insertion:

//Adds an element to the specified location
 ListNode.prototype.insert = function(location,val){
     location = location-1//The starting position starts from 0, while the normal position starts from 1
     //Judge the length and position of the linked list. If the position to be inserted is greater than the length of the linked list or less than 0, return false
     if(this.length<location||location<0){
        return false;
     }
     let newNode = new Node(val);//Create the node to insert
     if(location==0){//If inserted in the head
        newNode.next = this.head;//Point the next of the node to the head
        this.head = newNode;//head points to the first node
     }else{//Otherwise, find the position to insert
         let count = 0;
         let head1 = this.head;
         let head2 = null
         while(count<location&&head1!==null){
             head2 = head1;//Find the previous node to insert
             head1 = head1.next;//Find the next node to insert
             count++;
         }
         head2.next = newNode;//Point the next of the previous node to the inserted node
         newNode.next = head1;//Point the next inserted node to the next node
     }
     this.length++;
 }

9,ReverseOrder()

If the linked list has only one node or is empty, reverse order is not required.

otherwise

The first step of the reverse process is shown as follows:



After finishing the above steps:

//Reverse order
 ListNode.prototype.ReverseOrder = function(){
     let l1 = this.head;
    if(l1===null||(l1!==null&&l1.next==null)){//Judge whether the linked list is empty or there is only one node, and return directly
    return l1;
    }else{//There are two or more nodes in the linked list
    let head2 = l1.next;//Let the head point to the next node of l1
    let head1 = l1;//head1 points to the first node
    while(head2.next!==null){
        l1.next = head2.next;//Disconnect the second pointer and connect the first node to the third node
        head2.next = head1;//Turn the first node ☞ to the head node
        head1 = head2;//head1 is updated to the head node
        head2=l1.next;//head re points to the second node of l1
    }
    if(head2!==null&&head2.next==null){//Point the last node to the head node
        l1.next = null;
        head2.next = head1;
    }   
    this.head = head2
    }
}

Complete linked list creation and common methods.

//Establishment and basic operation of single linked list
class Node{//Create a node class
    constructor(val, next){
        this.val = (val===undefined ? 0 : val)
        this.next = (next===undefined ? null : next)
    }
 }

 function ListNode(){//Linked list class  
        this.length = 0;
        this.head = null;
 }

//Add an element at the end of the linked list (val is the value of the node)
 ListNode.prototype.addNode = function(val){
     //Create nodes to add
     let newNode = new Node(val);
    //Judge whether the linked list is empty. If it is not empty, add an element after the linked list, otherwise it is the head node
    if(this.length==0){
        this.head=newNode;
    }else{
        let head1 = this.head;
        while(head1.next!==null){//Find the tail of the linked list
        head1 = head1.next;
    }
    head1.next = newNode;//Add a node to the end of the linked list
    }
    this.length++;//The corresponding length increases after adding nodes
 }

 ListNode.prototype.Length = function(){
     return this.length;//Return its length, which is the length of the linked list
 }

 //Print linked list
 ListNode.prototype.display = function(){
    let head1 = this.head;
    let res  = [];//Save the values in the traversed linked list with an array
    let i = 0;
    while(head1!==null){//Traverse the linked list in turn and store the values in the array
        res[i] = head1.val;
        head1 = head1.next;
        i++;
    }
    return res;
 }

 //Replace specified value
 ListNode.prototype.ModifyValue = function(val1,val2){//Replace val1 with val2
     let location = this.findValue(val1);//Find the location of val1
     if(location==false){//If it is not found, false is returned
         return false;
     }
     let head1 = this.head;//If found, find the node and replace the value
     while(head1!==null&&location>1){
         head1 = head1.next;
         location--;
     }
     head1.val = val2;
 }


 
 //Finds the specified value and returns its location
 ListNode.prototype.findValue = function(val){
    let head1 = this.head;
    let count = 0;
    while(head1!==null){//Traverse the linked list in turn
        if(head1.val==val){//If found, return to its location
            count++;
            return count;
        }else{//If you don't find it, keep looking down;
            head1 = head1.next;
            count++;
        }
    }
    return false;//After traversal, false is returned if it is not found
 }

 //Delete specified node
 ListNode.prototype.DeleteValue = function(val){
    let location = this.findValue(val);//Find the location of val
    if(location==false){//If it is not found, it returns false
        return false;
    }
    let head1 = this.head;
    let head2 = null;
    if(location==1){//If you need to delete the head node, you can directly point the head node to the next node
        this.head=this.head.next;
        this.length--;
    }else{
        while(location>2&&head1.next!==null){//Otherwise, find its previous node
            head1 = head1.next;
            location--;
        }
        head2 = head1.next.next;//Find his next node
        head1.next = head2;//Connect its previous and next nodes together
        this.length--;
    }
    
}


 //Modify the value at the specified location
 ListNode.prototype.ModifyLc = function(location,val){
     location = location-1;//The starting position starts from 0, while the normal position starts from 1
    if(this.length<location||location<0){ //Judge whether it is out of bounds
        return false;
    }
    if(location==0){//Change the value of the header node
        this.head.val = val
    }else{//Change the following value
        let count = 0;
        let head1 = this.head;
        while(count<location&&head1!==null){//Find the location that needs to be modified
        head1 = head1.next;
        count++;
    }
    head1.val=val;//Modify the value after finding the specified location
    }
    

 }

 //Adds an element to the specified location
 ListNode.prototype.insert = function(location,val){
     location = location-1//The starting position starts from 0, while the normal position starts from 1
     //Judge the length and position of the linked list. If the position to be inserted is greater than the length of the linked list or less than 0, return false
     if(this.length<location||location<0){
        return false;
     }
     let newNode = new Node(val);//Create the node to insert
     if(location==0){//If inserted in the head
        newNode.next = this.head;//Point the next of the node to the head
        this.head = newNode;//head points to the first node
     }else{//Otherwise, find the position to insert
         let count = 0;
         let head1 = this.head;
         let head2 = null
         while(count<location&&head1!==null){
             head2 = head1;//Find the previous node to insert
             head1 = head1.next;//Find the next node to insert
             count++;
         }
         head2.next = newNode;//Point the next of the previous node to the inserted node
         newNode.next = head1;//Point the next inserted node to the next node
     }
     this.length++;
 }
 //Reverse order
 ListNode.prototype.ReverseOrder = function(){
     let l1 = this.head;
    if(l1===null||(l1!==null&&l1.next==null)){//Judge whether the linked list is empty or there is only one node, and return directly
    return l1;
    }else{//There are two or more nodes in the linked list
    let head = l1.next;//Let the head point to the next node of l1
    let head1 = l1;//head1 points to the first node
    while(head.next!==null){
        l1.next = head.next;//Disconnect the second pointer and connect the first node to the third node
        head.next = head1;//Turn the first node ☞ to the head node
        head1 = head;//head1 is updated to the head node
        head=l1.next;//head re points to the second node of l1
    }
    if(head!==null&&head.next==null){//Point the last node to the head node
        l1.next = null;
        head.next = head1;
    }   
    this.head = head
    }
}

 let list = new ListNode();
 list.addNode(1);
 list.addNode(2);
 list.addNode(3)
 list.insert(4,5)
 list.ModifyLc(4,9)
 console.log("Found location:",list.findValue(9))
 console.log("Length of linked list",list.Length());
 console.log("Traversal of linked list:",list.display());
 list.DeleteValue(9)
 console.log("Length of linked list after node deletion",list.Length());
 console.log("Traversal of linked list after node deletion:",list.display());
 list.ModifyValue(3,7)
 console.log("Replaced linked list",list.display())
//  let list1 = list.head;
 list.ReverseOrder();
 console.log("Linked list in reverse order",list.display())

Topics: Javascript data structure linked list