JS数据结构与算法—栈、队列

140 阅读2分钟

1 数组常见操作

let str = ['a', 'b', 'c', 'd', 'e'];
str.push('f');                //在数组最后添加一个元素
str.unshift('g');             //在数组开头添加一个元素
str.pop();                    //删除数组中最后一个元素
str.shift();                  //删除数组中第一个元素
str.splice(2, 0, 'h');        //将'h'添加在数组下标为2 的位置上

2 栈

什么是栈?

  1. 栈(stack)是一种运算受限的线性结构,后进先出(LIFO last in first out)
  • 类似于坐电梯
  1. 其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。
  2. 向一个栈插入新元素会成为新的栈顶元素,从一个栈删除元素是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

使用数组封装栈

 <script>
     function Stack() {
         this.item = [];
         //1.将元素压入栈
         Stack.prototype.push = function (element) {
             this.item.push(element);
         };
         //2.从栈中取出元素
         Stack.prototype.pop = function () {
             return this.item.pop();
         };
         //3.查看一下栈顶元素
         Stack.prototype.peek = function () {
             return this.item[this.item.length - 1];
         };
         //4,判断栈是否为空
         Stack.prototype.isEmpty = function () {
             return this.item.length == 0;
         };
         //5.获取栈中元素的个数
         Stack.prototype.size = function () {
             return this.item.length;
         };
         //6.toString方法
         Stack.prototype.toString = function () {
             let resString = '';
             for (let i = 0; i < this.item.length; i++) {
                 resString += this.item[i] + ' ';
             }
             return resString;
         };
     }
     let stack = new Stack();
     stack.push('a');
     stack.push('b');
     stack.push('c');
     console.log(stack);
     stack.pop();
     console.log(stack);
     console.log(stack.peek());
     console.log(stack.size());
     console.log(stack.isEmpty());
     console.log(stack.toString());
 </script>

利用栈实现十进制转二进制

利用栈后进先出的特点和刚封装的栈实现十进制转二进制

//函数封装
 function dec2bin(num) {
     let stack = new Stack();
     let remainder;
     //将余数压入栈
     while (num > 0) {
         remainder = num % 2;
         num = Math.floor(num / 2);
         stack.push(remainder);
     }
     //将栈中的数据取出
     let result = '';
     while (!stack.isEmpty()) {
         result += stack.pop();
     }
     return result;
 }
 console.log(dec2bin(22));

3 队列

什么是队列?

  1. 队列也是一种运算受限的线性表,先进先出(FIFO first in first out)
  • 类似于排队
  1. 受限之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作

用数组实现队列

class Queue {
    constructor() {
        this.item = [];
    }
    //1.向队尾添加一个或多个项
    addQueue(element) {
        this.item.push(element);
    }
    //2.从队列中删除前端的元素
    removeQueue() {
        return this.item.shift();
    }
    //3.查看前端的元素
    front() {
        return this.item[0];
    }
    //4.查看队列是否为空
    isEmpty() {
        return this.item.length == 0;
    }

    //5.查看队列中的个数u
    size() {
        return this.item.length;
    }
    //6.toString方法
    toString() {
        let resultString = '';
        for (let i = 0; i < this.item.length; i++) {
            resultString += this.item[i] + ' ';
        }
        return resultString;
    }
}
let queue = new Queue();
//测试代码
queue.addQueue('a');
queue.addQueue('b');
queue.addQueue('c');
console.log(queue);
queue.removeQueue();
console.log(queue);
console.log(queue.size());
console.log(queue.isEmpty());
console.log(queue.front());
console.log(queue.toString());

击鼓传花案例

请听题:几个朋友一起玩一个游戏, 围成一圈, 开始数数, 数到某个数字的人自动淘汰. 最后剩下的这个人会获得胜利, 请问最后剩下的是原来在哪一个位置上的人? 思路:

  1. 参数为参赛选手列表和设置的数字
  2. 将参赛选手存入队列
  3. 将所选数字以前的队列元素按顺序,删掉第一个,将之存入最后,然后继续
  4. 将数字以前元素删完后删除数字对应的元素
  5. 将3,4步作为一个循环体,进行循环
  6. 循环至最后队列中只剩一个元素
 function game(nameList, num) {
 //利用前面封装的队列的类(class)
      let queue = new Queue();
      for (let i = 0; i < nameList.length; i++) {
          queue.addQueue(nameList[i]);
      }
      while (queue.size() > 1) {
          for (let i = 0; i < num; i++) {
              queue.addQueue(queue.removeQueue(queue[i]));
              queue;
          }
          queue.removeQueue();
      }
      console.log(queue.size());//查看队列人数
      console.log(nameList.indexOf(queue.front()));//查看此时队列最后人在游戏开始时的下标
      return queue.front();//队列中最后一人是谁
  }
  //调用函数
  let str = ['a', 'b', 'c', 'd'];
  console.log(game(str, 3));

优先队列

元素存入队列中时,不光加入元素本身,还要给元素增加一个优先级,根据优先级的大小,越小越优先排列在队列中。

function PriorityQueue() {
     function QueueElement(element, priority) {
         this.element = element;
         this.priority = priority;
     }
     this.item = [];
     PriorityQueue.prototype.enterQueue = function (element, priority) {
         let queueElement = new QueueElement(element, priority);

         if (this.item.length == 0) {
             this.item.push(queueElement);
         } else {
             let added = false;
             for (let i = 0; i < this.item.length; i++) {
                 if (queueElement.priority < this.item[i].priority) {
                     this.item.splice(i, 0, queueElement);
                     added = true;
                     break;
                 }
             }

             if (!added) {
                 this.item.push(queueElement);
             }
         }
     };
     //删除队列中的元素
     PriorityQueue.prototype.removeQueue = function () {
         return this.item.shift();
     };
     //3.查看一下队列前端元素
     PriorityQueue.prototype.front = function () {
         return this.item[0];
     };
     //4,判断队列是否为空
     PriorityQueue.prototype.isEmpty = function () {
         return this.item.length == 0;
     };
     //5.获取队列中元素的个数
     PriorityQueue.prototype.size = function () {
         return this.item.length;
     };
     //6.toString方法
     PriorityQueue.prototype.toString = function () {
         let resString = '';
         for (let i = 0; i < this.item.length; i++) {
             resString += this.item[i].element + ' ';
         }
         return resString;
     };
 }
 //测试代码
 let priorityQ = new PriorityQueue();
 priorityQ.enterQueue('a', 5);
 priorityQ.enterQueue('b', 2);
 priorityQ.enterQueue('c', 8);
 console.log(priorityQ);
 console.log(priorityQ.size());
 console.log(priorityQ.toString());
 console.log(priorityQ.isEmpty());