Single linked list (JavaScript Implementation)

Keywords: Javascript data structure linked list


To store multiple elements, array is the most commonly used data structure, but array also has many disadvantages:

  • The creation of an array usually requires a continuous memory space, and the size is fixed. Therefore, when the current array cannot meet the capacity requirements, it needs to be expanded (usually apply for a larger array, and then copy the elements in the original array)
  • The cost of inserting data at the beginning or middle of array elements is very high, and a large number of elements need to be displaced.

Therefore, to store multiple elements, another option is the linked list. Unlike the array, the elements in the linked list do not have to be a continuous space in memory. Each element of the linked list has a node that stores the element itself and a reference to the next element.
Compared with arrays, linked lists have some advantages:

  • The memory space does not have to be continuous. It can make full use of the computer memory to realize flexible memory dynamic management.
  • The linked list does not have to be sized at the time of creation, and the size can be extended indefinitely.
  • When inserting and deleting data, the event complexity of linked list can reach O (1), which is much more efficient than array.

Compared with arrays, linked lists have some disadvantages:

  • When a linked list accesses an element at any position, it needs to access it from the beginning. It cannot access the element directly through subscript.

1, What is a single linked list

So what is a single linked list?
It is similar to a train. The locomotive gauge connects a node with passengers, and this node will be connected to the next node, and so on, as follows:


Our linked list structure is:

After understanding the intuitive linked list, let's encapsulate the code of the single linked list.

2, Encapsulation of single linked list

Firstly, we encapsulate a NodeList class to represent the linked list structure. In this class, we encapsulate an internal class Node to encapsulate the information on each Node (data and reference to the next Node), and then save two attributes in the NodeList class, one is the length of the linked list and the other is the head Node in the linked list. As follows:

 function LinkedList(){
            this.length = 0;
            this.head = null;
            //Inner class
            function Node(data){
                this.data = data;
                this.next = null;
            }
        }

3, Common operations of single linked list

Then add common operations of single linked list. It mainly includes:

  • append (element): adds an item to the end of the list
  • insert(position,element): inserts an item into a specific position in the list
  • get(position): get the element of the corresponding position
  • indexOf(element): returns the index of the element in the list. If there is no such element in the list, it returns - 1
  • update(position, ele): modify the element of a certain position
  • removeAt(position): removes an item from the specified position in the list
  • remove(element): removes an item from the list
  • isEmpty(): returns true if the linked list does not contain any elements, and false if the length of the linked list is greater than 0
  • size(): returns the number of elements contained in the linked list, which is related to the length attribute of the array
  • toString(): because the list item uses the Node class, you need to override the default toString method inherited from the JavaScript object to output the value of the element

Next, let's implement it one by one.

1. append(element) method ---- add an item to the end of the list

There are two possible situations for adding data to the tail of the linked list:

  • The linked list itself is empty, and the newly added data is the only node
  • The linked list is not empty. You need to add nodes after other nodes

So we need to make a judgment. If the linked list is empty, directly point the pointer of the head node to the new node.
If the linked list is not empty, create a new temporary node, make it equal to the head node, and judge it. If the pointer field of the node it points to is empty, it is the tail node. Add the newly added node to the end, that is, make the pointer of the tail node point to the newly added node. If the pointer field of the node it points to is not empty, make the pointer field of the temporary node point down A node operates circularly until the pointer field of this node is empty (that is, the tail node). Then, for each node added, make the length of the linked list + 1.

LinkedList.prototype.append = function(data){
                var newNode = new Node(data);
                // Determine whether the linked list is empty
                // 1. Null
                if(this.length === 0){
                    this.head = newNode;
                }else{
                    //Not empty
                    var current = this.head;
                    if(current.next){
                        current = current.next;
                    }
                    current.next = newNode;
                }
                this.length += 1;
            }

2. toString method ---- output the value of the element

This is relatively simple, mainly to obtain each element, because any element of the linked list must start from the first node, so we can start from the node, cycle through each node, take out the element, splice it into a string, and return the character string.

LinkedList.prototype.toString = function(){
                var current = this.head;
                var ListStr = '';
                while(current){
                    ListStr += current.data + ' ';
                    current = current.next;
                }
                return ListStr;
            }

Verify: create several new nodes and print them

 var list = new LinkedList();
        list.append('a');
        list.append('b');
        list.append('c');
        list.append('d');
        list.append('e');
        alert(list);

The print result is:

3. insert method ---- inserts an item into a specific location in the list

To implement the method of inserting data at any position, first judge whether the inserted position is out of bounds, and then divide it into two cases without exceeding the bounds. If you insert it into the first position, it means that the newly added node is the head. You need to take the original head node as the next of the new node, and then let the head point to the new node. If you insert it into other positions, you need to find the section first through a loop Point the position and save the previous node and the next node during the cycle. After finding the correct position, point the next node of the new node to the next node and point the next node of the previous node to the new node. The code is as follows:

 LinkedList.prototype.insert = function(position,data){
                if(position<0 || position >this.length){
                   return false;
               }
                var newNode = new Node(data);
                var index = 0;
              if(position == 0){
                newNode.next = this.head;
                this.head = newNode;

              }else{
                    while(index++ < position){
                        var current = this.head;
                        var previous = null;
                        previous = current;
                        current = current.next;
                    }
                    newNode.next = current;
                    previous.next = newNode;
                }
                this.length += 1;
                return true;
                }

Verification: insert xl in position 1 and wh in position 2

list.insert(1,'xl')
       list.insert(2,'wh')
        alert(list)

4. Get method ---- get the element of the corresponding position

This method is relatively simple. First, judge whether the position is out of bounds, and then traverse the linked list through the temporary node to the target location to obtain the elements of the location.

LinkedList.prototype.get = function(position,data){

                var current = this.head;
                var index = 0;
                if(position < 0 || position >= this.length){
                    return null;
                }else{
                    while(index<position){
                        current = current.next;
                        index++;
                    }
                    return current.data;
                }
            }

Validation: get the element at the third location:

alert( list.get(3));

5. indexOf() method ----- returns the index of the element in the list

First, judge whether the location of the searched element exists. If it does not exist, return - 1. If it exists, there are two cases. If the returned element is in the first position, directly return the index of the first position. If the returned element is in other positions, you need to find the node location first through the loop. In this process, the index needs to be added automatically with the number of traversals When the position of the element is correct, the print index is the target position.

LinkedList.prototype.indexOf = function(data){
                var index = 0;
                var current = this.head;
                while(current){
                    if(current.data == data){
                        return index;
                    }
                    else{
                        current = current.next;
                    index++;
                    }
                }
                return -1;
            }
        }

Verify: get c's index:

alert(list.indexOf('c'));

6. update method ---- modify the element at a certain location

This method is similar to the get method. It traverses backward. When the value of index is equal to position, it means that the target location is found and the date is changed to the target value:

LinkedList.prototype.update = function(position,ele){
                if(position<0 || position>=this.length){
                    return false;
                }else{
                    var index = 0;
                    var current = this.head;
                    while(index++ <position){
                        current = current.next;
                    }
                    current.data = ele;
                    return true;
                }
            }

Verification: the element of the 0th position is: bear

 list.update(0,'bear')
      alert(list)

7. removeAt method ---- removes an item from the specified position in the list

First, judge whether the position of the deleted item is out of bounds. Then, if it is not out of bounds, give two temporary nodes previous and current. Previous is used to save the value of the previous current, traverse from the node until the index position is equal to the target position, let the temporary node current traverse to the target position, and let the previous next of the temporary node point to the next.

LinkedList.prototype.removeAt = function(position,data){
                var current = this.head;
                var previous = null;
                var index = 0;
                if(position<0 || position>=this.length){
                    return false;
                }else{
                    while(index++ <position){
                        previous = currrent;
                        current = current.next;
                    }
                    previous.next = current.next;
                    this.length -= 1;
                    return true;
                }
            }
        }

Verify: remove element in third position:

list.removeAt(3)
      alert(list)

8. remove method ---- removes an item from the list

First judge whether the element to be deleted is in the linked list. If not, return false. Otherwise, build a temporary node to traverse the linked list. If the data value of the temporary node is equal to the element to be deleted, stop the traversal and let the previous next of the temporary node point to the next. Here, you can build a temporary node to store the value of the previous current.

LinkedList.prototype.remove = function(ele){
                var current = this.head;
                var previous = null;
                var index = 0;
                while(current.data !== ele){
                    previous = current;
                    current = current.next;
                    index++;
                }
                previous.next = current.next;
            }

Validation: delete element with value xl:

 list.remove('xl')
      alert(list)

9. isEmpty method ---- judge whether the linked list is empty

According to the length, if the linked list does not contain any elements, it returns true. If the length of the linked list is greater than 0, it returns false

LinkedList.prototype.isEmpty = function(){
                    return this.length == 0;
                }

verification:

 alert(list.isEmpty())

9. size method ----- returns the number of elements contained in the linked list

Directly return the length of the element, which is its number.

LinkedList.prototype.size = function(){
                    return this.length;
                }

verification:

   alert(list.size())

Posted by redtux on Sat, 04 Dec 2021 19:39:12 -0800