Реализация операций с помощью JavaScript
В двусвязном списке можно перемещаться вперед и назад при обходе списка.
Если вам интересно узнать об основах связанного списка, посетите мой блог.
Вот изображение того, как выглядит двусвязный список:
Создание класса узла
// By creating this node class, you avoid repeating the same steps //You just have call this class when you want to create or add a node class Node { constructor(value){ this.value = value this.next = null this.previous = null } }
Создание нового связанного списка
class DoublyLinkedList { constructor(value) { // create new Node using the Node class // point the head and tail to the new Node // keep track of the length const newNode = new Node(value) this.head = newNode this.tail = this.head this.length = 1 } }
Добавление узла в конец списка
//PROCESS //takes in 1 argument: the value of the new Node //use the Node Class to create a new Node //if list is empty: //point the head and tail to the New Node //else: //have the current last Node point to the New Node //connect the new Node back to what had been the last Node in the list //set the tail to equal the new Node //increase length by 1 //return the entire linked list push(value){ const newNode = new Node(value) if(!this.head){ this.head = newNode this.tail = newNode }else { this.tail.next = newNode newNode.previous = this.tail this.tail = newNode } this.length++ return this }
Удаление узла в конце списка
//PROCESS: //if list is empty: //return undefined //create variable and set it equal to the tail //if list only has 1 item //set the head and tails equal to null //else //change the tail to point to the second to last Node //this will set it as the new last Node //remove the connection between the new last Node and the old last Node //set the tail.next to equal null //set the oldlastNode.previous equal null //reduce length by 1 //return the Node that has been removed pop() { if(this.length === 0) return undefined let temp = this.tail if(this.length === 1){ this.head = null this.tail = null }else { this.tail = this.tail.previous this.tail.next = null temp.previous = null } this.length-- return temp }
Добавление узла в начало списка
//PROCESS: //takes in 1 argument: the value of the new Node //create new node using the Node class //if list is empty //set the head and tail equal to the new Node //else // set the new Node to point to the first Node in list //set the first Node to point back to the new Node //set the new Node as the first Node in list //increase length by 1 //return entire list unshift(value){ const newNode = new Node(value) if(this.length === 0){ this.head = newNode this.tail = newNode }else { newNode.next = this.head this.head.previous = newNode this.head = newNode } this.length++ return this }
Удаление первого узла из списка
//PROCESS: //if list is empty: //return undefined //create variable and set it equal to the head //this will be used to point to the node that you want to delete //if list has one item //set the head and tail equal to null //else //set the head equal to the 2nd Node in list //set the new first Node to point back to null //set the previous first Node to point to null //reduce length by 1 //return the deleted Node shift() { if(this.length === 0) return undefined let temp = this.head if(this.length === 1){ this.head = null this.tail = null } else { this.head = this.head.next this.head.previous = null temp.next = null } this.length-- return temp }
Получение узла из определенного индекса
//PROCESS: //takes in 1 argument: the specific index //if index is outside range //return undefined //create a new variable and set it equal to head //if the index is less than half of the length of list //traverse list from the head //else //traverse list from the tail //return the Node for the specific index get(index){ if(index < 0 || index >= this.length){ return undefined } let temp = this.head if(index < this.length / 2){ for(let i = 0; i < index; i++){ temp = temp.next } } else { temp = this.tail for(let i = this.length - 1; i > index ; i--){ temp = temp.previous } } return temp }
Изменение значения определенного индекса
//PROCESS: //takes in 2 arguments: //the specific index, and the new value of that Node //use the GET method to find the specific Node //instead of typing the code again //if Node exists in the list: //set its value equal to the new value //return true //else //return false set(index, value){ let temp = this.get(index) if(temp){ temp.value = value return true } return false }
Вставка нового узла в определенный индекс
//PROCESS: //takes two arguments: specific index and new value //if index === 0 //use the UNSHIFT method //if index === length of list //use the PUSH method //if index is outside range //return undefined //else //create new Node using the Node Class //create two variables //one is used to point to the previous Node in list //use the GET METHOD to find this Node //the other is used to point to the next Node in list // change the previous Node to point to the new Node //set the new Node to point back to the previous Node //set the new Node to point to the next Node //change the next Node to point back to the new Node //increase length by 1 //return true insert(index, value){ if(index === 0) return this.unshift(value) if(index === this.length) return this.push(value) if(index < 0 || index >= this.length){ return undefined } const newNode = new Node(value) const before = this.get(index - 1) const after = before.next before.next = newNode newNode.previous = before newNode.next = after after.previous = newNode this.length++ return true }
Удаление узла по определенному индексу
//PROCESS: //takes in 1 argument: the specified index //if specified index === 0: //use the SHIFT method //if specified index is the last Node in list: //use the POP method //if specified index outside the range of list //return undefined //else //find the specific Node using the GET method //connect the previous Node to the Node that's after the specified Node //remove the specified node from list //reduce length by 1 //return the deleted node remove(index){ if(index === 0) return this.shift() if(index === this.length -1) return this.pop() if(index < 0 || index >= this.length){ return undefined } const temp = this.get(index) temp.previous.next = temp.next temp.next.previous = temp.previous temp.next = null temp.previous = null this.length-- return temp }
Вот как это выглядит вместе:
//USED TO CREATE NEW NODE class Node { constructor(value) { this.value = value this.next = null this.previous = null } } class DoublyLinkedList { //USED TO CREATE NEW LIST constructor(value) { const newNode = new Node(value) this.head = newNode this.tail = this.head this.length = 1 } //ADDING NEW NODE TO END OF LIST push(value){ const newNode = new Node(value) if(!this.head){ this.head = newNode this.tail = newNode } else { this.tail.next = newNode newNode.previous = this.tail this.tail = newNode } this.length++ return this } //REMOVING NODE FROM THE END OF LIST pop() { if(this.length === 0) return undefined let temp = this.tail if(this.length === 1){ this.head = null this.tail = null } else { this.tail = this.tail.previous this.tail.next = null temp.previous = null } this.length-- return temp } //ADDING NODE AT THE BEGINNING OF LIST unshift(value){ const newNode = new Node(value) if(this.length === 0){ this.head = newNode this.tail = newNode }else { newNode.next = this.head this.head.previous = newNode this.head = newNode } this.length++ return this } //DELETING FIRST NODE FROM LIST shift() { if(this.length === 0) return undefined let temp = this.head if(this.length === 1){ this.head = null this.tail = null } else { this.head = this.head.next this.head.previous = null temp.next = null } this.length-- return temp } //GETTING NODE FROM A PARTICULAR INDEX get(index){ if(index < 0 || index >= this.length){ return undefined } let temp = this.head if(index < this.length / 2){ for(let i = 0; i < index; i++){ temp = temp.next } }else { temp = this.tail for(let i = this.length - 1; i > index ; i--){ temp = temp.previous } } return temp } //CHANGING VALUE AT A PARTICULAR INDEX set(index, value){ let temp = this.get(index) if(temp){ temp.value = value return true } return false } //INSERTING NEW NODE AT A PARTICULAR INDEX insert(index, value){ if(index === 0) return this.unshift(value) if(index === this.length) return this.push(value) if(index < 0 || index >= this.length){ return undefined } const newNode = new Node(value) const before = this.get(index - 1) const after = before.next before.next = newNode newNode.previous = before newNode.next = after after.previous = newNode this.length++ return true } //REMOVING NODE AT A PARTICULAR INDEX remove(index){ if(index === 0) return this.shift() if(index === this.length -1) return this.pop() if(index < 0 || index >= this.length){ return undefined } const temp = this.get(index) temp.previous.next = temp.next temp.next.previous = temp.previous temp.next = null temp.previous = null this.length-- return temp } } // creates new instance of the linked list const newDoublyList = new DoublyLinkedList(1) // adds new Node to the 'newDoublyList' instance newDoublyList.push(2)
Цитирование