数据结构——队列、相关练习代码

182 阅读2分钟

队列:受限的线性结构

定义:是一种运算受限的线性表

规则:

队列遵循先进先出

先进先出First in first out FIFO

队列的详解:

1.当队列中没有元素,或者只有一个元素时,队首与队尾指向的都是同一个元素:

image.png

2.当元素1,元素2依次入队,队首指向元素1,而队尾指向元素2

image.png

封装队列(es6):

 class Queue{
// 封装队列结构
constructor(){
    this.item=[]
}
// 1.入队
enqueue(ele){
    this.item.push(ele)
}
// 2.出队
dequeue(){
    return this.item.shift()
}
// 3.查看队首元素
front(){
    return this.item[0]
}
// 4.查看队列是否为空
isEmpty(){
    return this.item.length==0
}
// 5.查看队列中元素的个数
size(){
    return this.item.length
}
}

优先级队列:

为什么要封装优先级队列:

  • 因为每个线程处理的任务重要性不同, 我们可以通过优先级的大小, 来决定该线程在队列中被处理的次序.

优先级思想:

  • 我们知道, 普通的队列插入一个元素, 数据会被放在后端. 并且需要前面所有的元素都处理完成后才会处理前面的数据.
  • 但是优先级队列, 在插入一个元素的时候会考虑该数据的优先级.(和其他数据优先级进行比较)
  • 比较完成后, 可以得出这个元素正确的队列中的位置. 其他处理方式, 和队列的处理方式一样.
  • 也就是说, 如果我们要实现优先级队列, 最主要是要修改添加方法. (当然, 还需要以某种方式来保存元素的优先级)

封装优先级队列(es6):

代码分析:

在插入新的元素时, 有如下情况下考虑:

  • 根据新的元素先创建一个新的Node对象.

  • 如果元素是第一个被加进来的, 那么不需要考虑太多, 直接加入数组中即可.

  • 如果是后面加进来的元素, 需要和前面加进来的元素依次对比优先级.

  • 一旦优先级, 大于某个元素, 就将该元素插入到元素这个元素的位置. 其他元素会依次向后移动.

  • 如果遍历了所有的元素, 没有找到某个元素被这个新元素的优先级低, 直接放在最后即可.

      <script>
      // 封装一个构造函数,用于保存元素和元素的优先级
      class Node {
      
          constructor(ele,priority) {
              this.ele = ele
              this.priority =priority
          }
      }
      
      class PriorityQueue {
    
          constructor() {
              this.item = []
          }
          // 添加元素的方法
          enqueue(ele, priority) {
              // 创建新节点  或者let  newnode={data:ele,priority:priority}
              let newnode = new Node(ele, priority)
              if (this.item.length == 0) {
                  // 队列是一个空队列,就不用比较优先级,元素直接入队
                  this.item.push(newnode)
              } else {
                  // 非空队列
                  // 元素是否被添加到队列中
                  let isAdd = false;
                  for (let i = 0; i < this.item.length; i++) {
                      // 依次比较优先级
                      if (newnode.priority < this.item[i].priority) {
                          // 注意:我们这里数字越小,优先级越高
                          // 新节点的优先级高于队列中元素的优先级
                          // 将新节点插入队列中
                          // 插入到它优先级高于的那个元素的前面
                          // splice(start,length)方法: 删除元素,并向数组添加新元素。
                          this.item.splice(i, 0, newnode);
                          isAdd = true
                          break;
                      }
                  }
                  // 循环遍历结束都没有优先级比新节点要小的元素时,直接添加到队列的最后
                  if (!isAdd) {
                      this.item.push(newnode)
                  }
    
              }
          }
          // 出队
          dequeue(){
              return this.item.shift()
          }
          // 获取前端的元素
          front(){
              return this.item[0]
          }
          // 查看元素是否为空
          isEmpty(){
              return this.item.length=00
          }
          // 获取元素的个数
          size(){
              return this.item.length
          }
      }
    

相关设计代码:

1.击鼓传花:

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

图解: 1.

image.png

image.png 3.

image.png 4.

image.png 5.

image.png 6.

image.png 7.

image.png

image.png 9.

image.png 10.所以到最后队列中只剩下了鲨鱼辣椒

image.png

正确代码:

    <script src="Queue.js"></script>
<script>
    function jigu(ele,num){
        // 创建一个队列
        var queue=new Queue()
        // 将数组中所有元素入队
        ele.forEach((el,index) => {
            queue.enqueue(el)
        });
        let index=1
        // 找最后一个人
        while(queue.size()>1){
            // for(var i=0;i<num;i++){
            //     // 将所有不等于3的数出队,又入队
            //     queue.enqueue( queue.dequeue())
            // }
            // // 数数等于3,出队,不重新入队
            // queue.dequeue()
            // 上面这个代码是错误的,当i>num时,会在一次循环中移出两次元素
            // 因为queue.dequeue()重复了两次
            if (index >= num) {
                // 将index=num的元素移出队列
                queue.dequeue()
           // 再让index继续从1开始数数
              index = 1
            }
          queue.enqueue(queue.dequeue())      
          index++
        }
        // 最后一个人
        var endname=queue.front()
        console.log(endname);
        // 在队列中的位置
        return ele.indexOf(endname)
    }
    var arr=["鲨鱼辣椒","蜻蜓队长","蟑螂恶霸","金龟次郎","蝎子莱莱","铁甲小宝"]
    jigu(arr,3)
</script>

image.png

错误代码:

while循环中,当i>num时,会在一次循环中移出两次元素,因为queue.dequeue()重复了两次

    <script src="Queue.js"></script>
    <script>
    function jigu(ele,num){
        var queue=new Queue()
        // 将数组中所有入队
        ele.forEach((el,index) => {
            queue.enqueue(el)
        });
        // 找最后一个人
        while(queue.size()>1){
            for(var i=0;i<num;i++){
                // 将所有不等于3的数出队,又入队
                queue.enqueue(queue.dequeue())
            }
            // 数数等于3,出队,不重新入队
            queue.dequeue()
        }
        // 最后一个人
        var endname=queue.front()
        console.log(endname);
        // 在队列中的位置
        return ele.indexOf(endname)
         


    }
    var arr=["鲨鱼辣椒","蜻蜓队长","蟑螂恶霸","金龟次郎","蝎子莱莱","铁甲小宝"]
    jigu(arr,3)
    </script>
    
    

image.png