Use js to implement those data structures 06 (queues)

  In fact, there are many similarities between queues and stacks, including some of their methods and usage, but the queue uses a completely different principle from the stack. The stack is the last-in, first-out principle, while the queue is First In First Out.

1. Queue

      A queue is a special kind of linear table. The special feature is that it only allows deletion operations at the front of the table and insertion operations at the rear of the table. Like stacks, queues are an operation subject to Linear table of constraints. The end that performs the insert operation is called the tail of the queue, and the end that performs the delete operation is called the head of the queue. When there are no elements in the queue, it is called an empty queue.
  The data elements of the queue are also called queue elements. Inserting a queue element into the queue is called enqueuing, and removing a queue element from the queue is called dequeuing. Because the queue can only be inserted at one end and deleted at the other end, only the elements that enter the queue first can be deleted from the queue first, so the queue is also called a first-in, first-out (FIFO—first in first out) linear table.
  Now that we have a basic understanding of queues, let's take a look at how to implement queues. In fact, it is very similar to the implementation of the stack, but the methods of enqueuing and dequeuing are slightly different, so let's take a look at what methods are required for a complete queue:
    1. enqueue(element(s)), enqueue, add one or more elements to the tail of the queue.
    2. dequeue(), dequeue, remove the first element in the queue, which is the front element of the queue, and return the element.
    3. front(), get the element at the front of the queue, and return the first element in the queue (the element that was added first and also the first element that was removed). The queue does not remove the element.
    4. isEmpty(), to determine whether the queue does not contain any elements.
    5. size(), which returns the total number of elements in the queue.
 // Declare the Queue class 
  function Queue() {
       // Declare and initialize an array for storing queue elements. 
      let items = [];
       // Add queue element 
      this .enqueue = function (element) {
          items.push(element)
      };
      // Remove and return the queue element 
      this .dequeue = function () {
           return items.shift();
      };
      // Get the queue head element 
      this .front = function () {
           return items[0 ];
      };
      // Determine whether the queue element is empty 
      this .isEmpty = function () {
           return items.length == 0 ;
      };

      // Get the number of queue elements 
      this .size = function () {
           return items.length;
      };
      // Print the queue 
      this .print = function () {
          console.log(items.toString())
      };
  }
const queue = new Queue();
console.log(queue.isEmpty()); // outputs true
queue.enqueue('John');
queue.enqueue('Jack');
queue.print(); // John,Jack
queue.enqueue('Camila');
queue.print(); // John,Jack,Camila
console.log(queue.size()); // outputs 3
console.log(queue.isEmpty()); // outputs false
queue.dequeue(); // remove John
queue.dequeue(); // remove Jack
queue.print(); // Camila

  We have already implemented the data structure of the queue above. Similarly, can we make a little modification to make the implementation of the queue look more beautiful.

let Queue = (function () {
      const items = new WeakMap();

      class Queue {
          constructor () { 
        //For emphasis, items here are WeakMap type data, and WeakMap is a key-value pair, with its own set and get methods to get and set the value,
        //So here [] is set for this, that is, with this is the key name and [] is the value, so the queue formed by this method is still an operation on the array items.set(
this ,[]); } enqueue(element) { let q = items.get( this ); //The q here is equivalent to [] q.push(element); } dequeue() { let q = items.get(this); let r = q.shift(); return r; } front() { return items.get(this)[0]; } isEmpty() { return items.get(this).length == 0; } size() { return items.get(this).length; } print() { console.log(items.get(this)); } } return Queue; })()

  In fact, the queue has basically been introduced here, but it feels a bit confusing. So let's finish the rest of the content in this article.

The priority queue
   We're done talking about queues, so let's see what a priority queue is. A normal queue is a first-in, first-out data structure where elements are appended at the end of the queue and removed at the head of the queue. In a priority queue, elements are given priority. When accessing elements, the element with the highest priority is removed first. Priority queues have a first in, largest out behavior. It's like we buy tickets at the window and line up at the airport. Normally, we enter in order from the front of the queue, but there are regulations that give priority to the elderly, children and soldiers, so the elderly (child soldiers) are given priority. The right to jump in line . The priority queue is also to give specific elements the right to jump in the queue (priority). I want to enqueue, not necessarily directly to the tail. Instead the queue is inserted according to the priority I set.
  In fact, the difference in the implementation of the priority queue is the setting of the queue elements and the method of entering the queue (there are actually two implementation methods here, one is to enter the queue according to the priority, the other is to dequeue according to the priority, here we only use the first way). Let's take a look at how to implement a priority queue.
  // Declare Queue class 
  function PriorityQueue() {
       // Declare and initialize an array to store queue elements. 
      let items = [];
       // Create an element class with priority 
      function QueueElement(element,priority) {
           this .element = element;
           this .priority = priority;
      }
      // Add queue element 
      this .enqueue = function (element,priority) {
          let queueElement = new QueueElement(element,priority);
          let added = false ;
           // Traverse the queue elements, 1 has the highest priority, and so on, if the current element's priority is greater than items[i], then put the element in front of items[i]. 
          // If the second parameter of the splice method is 0, then add the third parameter to the front of i. 
          for (let i = 0; i < items.length; i++ ) {
               if (queueElement.priority < items[i].priority) {
                  items.splice(i,0,queueElement);
                  added = true;break;
              }
          }
          / / Determine whether the element can be directly added to the column by added. 
          if (! added) {
              items.push(queueElement);
          }
      };
      // Remove and return the queue element 
      this .dequeue = function () {
           return items.shift();
      };
      // Get the queue head element 
      this .front = function () {
           return items[0 ];
      };
      // Determine whether the queue element is empty 
      this .isEmpty = function () {
           return items.length == 0 ;
      };

      // Get the number of queue elements 
      this .size = function () {
           return items.length;
      };
      // loop to print elements and their priority "``" is an ES6 template string 
      this .print = function () {
           for (let i = 0; i < items.length; i++ ) {
              console.log(`${items[i].element} - ${items[i].priority}`);
          }
      };
  }
const queue = new PriorityQueue();
console.log(queue.isEmpty()); // outputs true

queue.enqueue('zaking',2);
queue.enqueue('linbo',6);
queue.enqueue('queue',5);
queue.enqueue('ada',3);
queue.enqueue('John',1);
queue.enqueue('Jack',2);
queue.enqueue('Camila',3);
queue.enqueue('zak',3);
queue.print();

  The main change lies in the setting of queue elements and the enqueue method. Since the priority needs to be set for each element of the circular queue, the elements of the queue are slightly changed here to have two parameters (the element itself and the priority), Then since the queue needs to be inserted according to different priorities, the enqueue method of the circular queue also needs to loop the entire queue to determine where to insert.

   In fact, the implementation of this priority queue is not very good. For example, if I do not pass the second priority parameter, then the parameter is undefined when the queue is printed, and it should default to the last priority when no parameter is passed. You can try to modify the code to make it look more realistic.
 
3. Circular queue
    In addition to the priority queue, there is also a circular queue. An easily imagined example of a circular queue is the game of drumming and passing flowers. The rules of the game are not mentioned. Everyone played it when they were young. Let's see how to realize the game of drumming and passing flowers.
function hotPotato(nameList, num) {
  const queue = new Queue();
   // List all the lists (nameList) in sequence 
  for (let i = 0; i < nameList.length; i++ ) {
    queue.enqueue(nameList[i]);
  }

  // Declare the name of the currently eliminated personnel 
  let eliminated = '' ;
   // If there is more than one element in the queue, it means there is no final winner, if there is only one left, dequeue the final winner 
  while (queue.size( ) > 1 ) {
       // Loop the current queue num times, and re-enter the "dequeue element" at the head of the queue. 
    for (let i = 0; i < num; i++ ) {
      queue.enqueue(queue.dequeue());
    }
    // After the loop ends, dequeue the elements of the current queue, that is, the knockout. 
    eliminated = queue.dequeue();
    queue.print();
    console.log(eliminated + "eliminated" );
  }

  return queue.dequeue();
}

let names = ["zak","zaking","james","lili","bole","londo","fali"]
console.log(hotPotato(names,7))

  In the above method, each loop will put the head element into the tail in turn, which realizes a circle, and then after the loop ends, the element at the front of the queue is regarded as eliminated, until there is only one element left at the end, that is, A real simulation of the drumming game.

 

  Finally, due to my limited level, my ability is still far from that of the Great God. If there are mistakes or unclear points, I hope everyone will give me some advice and corrections. thank you very much!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324485902&siteId=291194637