JavaScript implements Queue structure (Queue)

Keywords: Javascript ECMAScript

JavaScript implements Queue structure (Queue)

1, Queue introduction

Queue is a restricted linear table, which is characterized by first in first out (FIFO).

  • The limitation is that it only allows deletion at the front of the table;
  • Insert at the back end of the table;

It is equivalent to queuing up to buy tickets. Those who come first buy tickets first and those who come later buy tickets later.

Application of queue:

  • Print queue: when the computer prints multiple files, it needs to queue up for printing;
  • Thread queue: when multithreading is enabled, when the resources required by the newly opened thread are insufficient, it will be put into the thread queue first and wait for CPU processing;

Implementation of queue class:

The implementation of queue is the same as that of stack. There are two schemes:

  • Array based implementation;
  • Based on linked list;

Common actions for queues:

  • enqueue (element): add one (or more) new items to the end of the queue;
  • dequeue(): removes the first (i.e. the first) item in the queue and returns the removed element;
  • front (): returns the first element in the queue - the first element added and will be the first element removed. No changes are made to the queue (no elements are removed, only element information is returned, which is very similar to the peek method of Stack class);
  • isEmpty(): returns true if the queue does not contain any elements; otherwise, returns false;
  • size (): returns the number of elements contained in the queue, similar to the length attribute of the array;
  • toString(): convert the contents in the queue into string form;

2, Encapsulate queue class

2.1. Code implementation

    // Encapsulating queue class based on array
    function Queue() {
    // attribute
      this.items = []
      
    // method
    // 1.enqueue(): add elements to the queue
    Queue.prototype.enqueue = element => {
      this.items.push(element)
    }

    // 2.dequeue(): deletes the front-end element from the queue
    Queue.prototype.dequeue = () => {
      return this.items.shift()
        //This wave needs the main distinguishing method
        //push: store the element from the end, pop up the end element
        //shift: pop up header element unshift: add header element
    }

    // 3.front(): view the front-end elements
    Queue.prototype.front = () => {
      return this.items[0]
    }

    // 4.isEmpty: check whether the queue is empty
    Queue.prototype.isEmpty = () => {
      return this.items.length == 0;
    }

    // 5.size(): view the number of elements in the queue
    Queue.prototype.size = () => {
      return this.items.length
    }

    // 6.toString(): output the elements in the queue as strings
    Queue.prototype.toString = () => {
      let resultString = ''
        for (let i of this.items){
          resultString += i + ' '
        }
        return resultString
      }
    }

Test code:

 	// Create queue
    let queue = new  Queue()

    // Add element to queue
    queue.enqueue('a')
    queue.enqueue('b')
    queue.enqueue('c')
    queue.enqueue('d')
    console.log(queue);												//58

    // Delete element from queue
    queue.dequeue()
    console.log(queue);												//62
    queue.dequeue()
    console.log(queue);												//64

    //front
    console.log(queue.front());								 		//67
    
    // Verify other methods
    console.log(queue.isEmpty());								 	//70
    console.log(queue.size());								 		//71
    console.log(queue.toString());								 	//72

Test results:

2.2. Queue application

Use the queue to realize the small game: beat the drum to pass flowers, pass in a set of data and the set number num, and cycle through the elements in the array. When the traversed elements are the specified number num, delete the elements until there is one element left in the array.

Modified rules of the game:
Several friends play a game together, form a circle and start counting. Those who count to a certain number will be eliminated automatically.
The last person left will win. Where is the last person left?

Idea: store the array in the queue. All the numbers before that number are put in that number, and then delete that number. When there is only one number left, the loop jumps out. The loop ends. There is only one number in the array, which is the winner, and then put it in the original array, which is the original position

Code implementation:

    // Queue application: interview question: beating drums and passing flowers
    let passGame = (nameList, num) => {
      //1. Create queue structure
      let queue = new Queue()

      //2. Add everyone to the queue in turn
      // This is the for loop writing method of ES6. I is equivalent to nameList[i]
      for(let i of nameList){
        queue.enqueue(i)
      }
      // 3. Start counting
     while(queue.size() > 1){//Stop counting when there is only one person left in the queue
      // If it is not num, rejoin the end of the queue
      // When it is num, delete it from the queue
      // 3.1. Put the person before num number back to the end of the queue (add the deleted in front of the queue to the end of the queue)
      for(let i = 0; i< num-1; i++ ){
        queue.enqueue(queue.dequeue())
      }
      // 3.2.num corresponds to this person and is directly deleted from the queue
      /*
        The idea is like this. Since the queue does not have the same subscript value as the array and cannot directly get to an element, the num-1 element in front of num is deleted first and then added to the end of the queue. In this way, the num element is at the top of the queue and can be deleted directly by using the dequeue method
      */
      queue.dequeue()
     }

      //4. Get the rest of the person
      console.log(queue.size());									//104
      let endName = queue.front()
      console.log('Finally, the rest:' + endName);						   //106	
      
      return nameList.indexOf(endName);
    }

    //5. Test drum beating and flower transmission
    let names = ['lily', 'lucy', 'Tom', 'Lilei', 'Tony']
    console.log(passGame(names, 3));								//113

Test results:

3, Priority queue

The main considerations of priority queue are:

  • Each element is no longer just a data, but also contains the priority of the data;
  • In the process of adding data, it is placed in the correct position according to the priority;

3.1. Implementation of priority queue

Code implementation:

    // Encapsulate priority queue
    function PriorityQueue() {

      //Inner class: encapsulate another class in the class; Represents data with priority
      function QueueElement(element, priority) {
        this.element = element;
        this.priority = priority;
      } 

      // Encapsulation properties
      this.items = []

      // 1. Implement the priority insertion method
      PriorityQueue.prototype.enqueue = (element, priority) => {
        // 1.1. Create QueueElement object
        let queueElement = new QueueElement(element, priority)

        // 1.2. Judge whether the queue is empty
        if(this.items.length == 0){
          this.items.push(queueElement)
        }else{
          // Defines whether a variable record successfully adds a new element
          let added = false
          for(let i of this.items){
            // Compare the priority of the newly inserted element with the original element (the smaller the priority, the higher the priority)
            if(queueElement.priority < i.priority){
              this.items.splice(i, 0, queueElement)
              added = true
              // The new element has found the insertion position. You can use break to stop the loop
              break
            }
          }
          // If the new element is not successfully inserted, it is placed at the top of the queue
          if(!added){
            this.items.push(queueElement)
          }
        }
      }

      // 2.dequeue(): deletes the front-end element from the queue
      PriorityQueue.prototype.dequeue = () => {
        return this.items.shift()
      }

      // 3.front(): view the front-end elements
      PriorityQueue.prototype.front = () => {
        return this.items[0]
      }

      // 4.isEmpty(): check whether the queue is empty
      PriorityQueue.prototype.isEmpty = () => {
        return this.items.length == 0;
      }

      // 5.size(): view the number of elements in the queue
      PriorityQueue.prototype.size = () => {
        return this.items.length
      }

      // 6.toString(): output the elements in the queue as a string
      PriorityQueue.prototype.toString = () => {
        let resultString = ''
          for (let i of this.items){
            resultString += i.element + '-' + i.priority + ' '
          }
          return resultString
        }
    }

Test code:

    // Test code
    let pq = new PriorityQueue();
    pq.enqueue('Tom',111);
    pq.enqueue('Hellen',200);
    pq.enqueue('Mary',30);
    pq.enqueue('Gogo',27);
    // Print modified priority queue objects
    console.log(pq);

Test results:

3.2. Precautions

About the usage of array method splice:

  • splice (1, 0, 'Tom'): insert the element 'Tom' before the element with index 1 (it can also be understood as deleting the element with index 1, deleting 0 elements, and then adding the element 'Tom' before the element with index 1);

  • Split (1, 1, 'Tom'): it means to delete from the element with index 1 (including the element with index 1). A total of 1 element is deleted and the element 'Tom' is added. That is, replace the element with index 1 with the element 'Tom'.

    var fruits = ["Banana", "Orange", "Apple", "Mango"];
    fruits.splice(2,0,"Lemon","Kiwi");
    //Banana,Orange,Lemon,Kiwi,Apple,Mango
    
    var fruits = ["Banana", "Orange", "Apple", "Mango"];
    fruits.splice(2,2,"Lemon","Kiwi");
    //Banana,Orange,Lemon,Kiwi
    
    var fruits = ["Banana", "Orange", "Apple", "Mango"];
    fruits.splice(2,1,"Lemon","Kiwi")
    //Banana,Orange,Lemon,Kiwi,Mango
     If only one element is deleted, an array of one element is returned. If no element is deleted, an empty array is returned.
    
    var fruits = ["Banana", "Orange", "Apple", "Mango"];
    fruits.splice(2,2);
    //Banana and orange delete the two elements after the array from the third position:
    //If the following 2 is not set, the following 2 is deleted
    

The form of array push method in array, stack and queue:

  • Array: pop(3) in the array [0, 1, 2], and the result is [0, 1, 2, 3];
  • Stack: execute pop(0), pop(1), pop(2) and pop(3). The elements from the bottom of the stack to the top of the stack are 0, 1, 2 and 3 respectively; If it is regarded as an array, it can be written as [0, 1, 2, 3], but the element 3 with index 3 is actually the top element of the stack; Therefore, the push method of the stack is to add elements to the top of the stack (but from the perspective of the array, to add elements to the end of the array);
  • Queue: enqueue method can be implemented by the push method of array. It is the same as array, which is equivalent to adding elements at the end of array.

Think of it this way: the stack structure is an array structure with a head down (the index value increases from bottom to top).

reference material: JavaScript data structure and algorithm

Posted by longtone on Wed, 10 Nov 2021 18:12:56 -0800