How to design an object-based linked list?

Time:2021-12-1

preface

As we all know more or less, the most used data structure as a front end is array; In the writing business, it must be inseparable from the array, because it is not only convenient for storage, but also convenient for operation. Regardless of efficiency, storing data arrays is a personal choice. But there is another thing called “linked list” in the data structure. The “linked list” may be used less in the front end. Anyway, as a bottom staff, I have worked for more than two years and haven’t used the “linked list”. I usually use arrays. Although I may not use it, I might as well learn from it. Compared with the addition and deletion of the array, the “linked list” still has advantages, although the query is more “hip pulling”. The ancients said, “choose the good and follow it.”.

Linked list

Unidirectional linked list is the most common linked list structure. It is a data structure similar to chaining composed of multiple nodes. It looks like the following:

How to design an object-based linked list?

The linked list will have a special node called “head”, which stores the first node. Each node will contain an element and a “next” pointer to the next element; The next of the last node will point to “null, undefind”.

In JS, although there is the concept of “linked list”, it does not provide a built-in constructor to create “linked list”, unlike some back-end languages. In JS, if you want to use the “linked list” to store data, you can only manually implement some constructors and methods.

Design a linked list that should include the following:

  • Linked list constructor
  • Node constructor
  • Push method (add a node to the end of the linked list)
  • Insert method (add an element to the specified location)
  • Removeat method (deletes a node at a specified location)
  • Removeitem method (deletes the node of a specified element)
  • Getelementat method (get a node at a specified location)
  • Indexof method (get the node position of an element)
  • Show method (display all linked list data)
  • Size method (number of linked list nodes)
  • Gethead method (get header node)
  • Isempty method (judge whether the list is empty)
  • There may be others. I didn’t expect them for the time being

After understanding the requirements, we will implement a linked list structure step by step. (for ease of understanding, the code will not be encapsulated, although there are many similar codes)

Node constructor

An ordinary node only needs an element and a pointer (next), and there is no need for other superfluous things.

class Node {
  constructor(elememt){
    this.elememt = elememt
    this.next = undefined
  }
}

Linked list constructor

The linked list constructor requires oneHead nodeAnd save the number of nodescountandThe above methods


class LinkedList {
  constructor(){
    this.count = 0
    this.head = new Node('head')
  }
}

After creating the structure, you can implement the method of operating the linked list. Now the linked list looks as follows:

How to design an object-based linked list?

Push method

Before implementing this method, first understand its addition logic through a diagram.

How to design an object-based linked list?

Push methodIs to add a node at the end of the linked list. Suppose we want to add a “Zhang San”, then we have to passNode constructorCreate a node called “Zhang San”, then find the last node in the linked list, disconnect its link to undefined next, and point it to a new node (as shown in the figure above).

If the logic is clear, it will be easy to implement.

push(ele){
  //Create a new node
  let newEle = new Node(ele)
  let current = this.head
  //Find the last node
  while(current.next !== undefined){
    current = current.next
  }
  //Change the pointer of the last node
  current.next = newEle
  //Number of nodes plus 1
  this.count++
}

Insert method

How to design an object-based linked list?

Suppose we want to add a node called “Li Si” at the first (index = 0), then we need to findPrevious node of index, as shown in the figure above, the previous node of index ishead, we need to find it and put itNext pointerpointNew node, andPointer to the new elementpointIndex node

insert(ele, index){
    //Superscript processing
    if(index>=0 && index <= this.count){
      //Create new element
      let node = new Node(ele)
      let current=this.head , pre
      
      for (let i = 0; i <= index; i++) {
          //Save the previous node of index
        pre = current
        //Target node of index
        current =current.next
      }
      //The pointer to the previous node of index points to the new node
      pre.next = node
      //The new node pointer points to the target node of index
      node.next = current
      //Node plus 1
      this.count++
    }else{
      Console. Error ('superscript ')
    }
  }

Removeat method

How to design an object-based linked list?

Suppose we want to delete the first item(index === 0), then find it(index=0)And point its pointer toindex=0The next node, that is, its next, finally resets the deleted node pointer toundefined

removeAt(index){
     //Superscript processing
    if(index >= 0 && index < this.count){
      let current=this.head , pre
      for (let i = 0; i <= index; i++) {
          //Index previous
        pre = current
        //Index item
        current =current.next
      }
      //Change the pointer of the previous item of index to skip the index item and point to the next item of index
      pre.next = current.next
      current.next = undefined
      //Node minus one
      this.count--
    }else{
      Console. Error ('delete failed, superscript exceeded ')
    }
  }

Removeitem method

This method is through element deletion. The logic is similar to that above, so it is not shown in the figure above.

removeItem(ele){
  let current = this.head,pre
  try {
    while(current.elememt !== ele){
      pre = current
      current = current.next
    }
  } catch (error) {
    Console. Error ('deletion failed, there is no such element ')
  }
  pre.next = current.next
  this.count--
}

Getelementat method

This method is mainly throughindexIf the corresponding node is found, the node will be returned. If not, the node will be returnedundefined


 getElement(index){
    if(index >= 0 && index < this.count){
      let node = this.head
      for (let i = 0; i <= index; i++) {
        node = node.next        
      }
      return node
    }
    return undefined
  }

Indexof method

This method is mainly throughelementfindsubscript, return when foundsubscript, return if not found-1


indexOf(ele){
  let current = this.head
  for (let i = 0; i < this.count; i++) {
    if(ele === current.elememt){
      return i
    }
    current = current.next
  }
  return -1
}

Size, gethead, isempty, show methods

The size method obtains the number of nodes, the gethead method obtains the head node of the linked list, the isempty method determines whether the linked list is empty, and the show method displays the linked list elements.

size(){
    return this.count
  }

  getHead(){
    return this.head
  }

  isEmpty(){
    return this.count === 0
  }

  show(){
    if(this.count > 0){
      let current = this.head
      while(current.next !== undefined){
          //This is just a print display
        console.log(current.next.elememt)
        current = current.next
      }
    }
  }

test

let personLink = new LinkedList()
  
  Personlink.push ('zhang San ')
  
  Personlink.push ('li Si ')
  
  Personlink. Insert ('wang Wu ', 1)
  
  personLink.removeAt(1)
  
  console.log(personLink.getHead())
  
  personLink.show()
  
  personLink.removeAt(1)
  
  Console.log (personlink.indexof ('wang Wu '))

Complete code

class Node {
  constructor(elememt){
    this.elememt = elememt
    this.next = undefined
  }
}

class LinkedList {
  constructor(){
    this.count = 0
    this.head = new Node('head')
  }

  push(ele){
    let newEle = new Node(ele)
    let current = this.head
    while(current.next !== undefined){
      current = current.next
    }
    current.next = newEle
    this.count++
  }
 
  size(){
    return this.count
  }

  getHead(){
    return this.head
  }

  isEmpty(){
    return this.count === 0
  }

  show(){
    if(this.count > 0){
      let current = this.head
      while(current.next !== undefined){
        console.log(current.next.elememt)
        current = current.next
      }
    }
  }

  removeAt(index){
    if(index >= 0 && index < this.count){
      let current=this.head , pre
      for (let i = 0; i <= index; i++) {
        pre = current
        current =current.next
      }
      pre.next = current.next
      current.next = undefined
      this.count--
    }else{
      Console. Error ('delete failed, superscript exceeded ')
    }
  }

  removeItem(ele){
    let current = this.head,pre
    try {
      while(current.elememt !== ele){
        pre = current
        current = current.next
      }
    } catch (error) {
      Console. Error ('deletion failed, there is no such element ')
    }
    pre.next = current.next
    this.count--
  }

  getElement(index){
    if(index >= 0 && index < this.count){
      let node = this.head
      for (let i = 0; i <= index; i++) {
        node = node.next        
      }
      return node
    }
    return undefined
  }

  insert(ele, index){
    if(index>=0 && index <= this.count){
      let node = new Node(ele)
      let current=this.head , pre
      for (let i = 0; i <= index; i++) {
        pre = current
        current =current.next
      }
      pre.next = node
      node.next = current
      this.count++
    }else{
      Console. Error ('superscript ')
    }
  }

  indexOf(ele){
    let current = this.head
    for (let i = 0; i < this.count; i++) {
      if(ele === current.elememt){
        return i
      }
      current = current.next
    }
    return -1
  }

}

let personLink = new LinkedList()
Personlink.push ('zhang San ')
Personlink.push ('li Si ')
Personlink. Insert ('wang Wu ', 1)
personLink.removeAt(1)
console.log(personLink.getHead())
personLink.show()
personLink.removeAt(1)
Console.log (personlink.indexof ('wang Wu '))