第88题 实现队列功能

请用两个栈,实现一个队列功能

功能 add/delete/length

  • 数组实现队列,队列特点:先进先出
  • 队列是逻辑结构,抽象模型,简单的可以用数组、链表来实现

    /**
     * @description 两个栈实现 - 一个队列功能
     */
    
    class MyQueue {
        stack1 = []
        stack2 = []
    
        /**
         * 入队
         * @param n n
         */
        add(n) {
          this.stack1.push(n)
        }
    
        /**
         * 出队
         */
        delete() {
          let res
    
          const stack1 = this.stack1
          const stack2 = this.stack2
    
          // 第一步:将 stack1 所有元素移动到 stack2 中
          while(stack1.length) {
              const n = stack1.pop()
              if (n != null) {
                  stack2.push(n)
              }
          }
    
          // 第二步:stack2 pop 出栈
          res = stack2.pop()
    
          // 第三步:将 stack2 所有元素“还给”stack1
          while(stack2.length) {
              const n = stack2.pop()
              if (n != null) {
                  stack1.push(n)
              }
          }
    
          return res || null
        }
    
        // 通过属性.length方式调用
        get length() {
          return this.stack1.length
        }
    }
    // 功能测试
    const q = new MyQueue()
    q.add(100)
    q.add(200)
    q.add(300)
    console.info(q.length)
    console.info(q.delete())
    console.info(q.length)
    console.info(q.delete())
    console.info(q.length)

性能分析:时间复杂度:add O(1)delate O(n) 空间复杂度整体是O(n)

使用链表实现队列

可能追问:链表和数组,哪个实现队列更快?

  • 数组是连续存储,push很快,shift很慢
  • 链表:查询慢(把链表全部遍历一遍查询)时间复杂度:O(n),新增和删除快(修改指针指向)时间复杂度:O(1)
  • 数组:查询快(根据下标)时间复杂度:O(1),新增和删除慢(移动元素)时间复杂度:O(n)
  • 结论:链表实现队列更快

思路分析

  • 使用单项链表,但要同时记录headtail
  • 要从tail入队,从head出队,否则出队时tail不好定位
  • length要实时记录单独存储,不可遍历链表获取length(否则遍历时间复杂度是O(n)
    // 用链表实现队列
    
    // 节点数据结构
    interface IListNode {
      value: number
      next: IListNode | null
    }
    
    class MyQueue {
      head = null // 头节点,从head出队
      tail = null // 尾节点,从tail入队
      len = 0 // 链表长度
    
      /**
       * 入队,在 tail 位置入队
       * @param n number
       */
      add(n) {
        const newNode = {
          value: n,
          next: null,
        }
    
        // 处理 head,当前队列还是空的
        if (this.head == null) {
          this.head = newNode
        }
    
        // 处理 tail,把tail指向新的节点
        const tailNode = this.tail // 当前最后一个节点
        if (tailNode) {
          tailNode.next = newNode // 当前最后一个节点的next指向新的节点
        }
        // ![](https://s.poetries.work/uploads/2023/01/843c681c06e65a9c.png)
        // 把当前最后一个节点断开,指向新的节点
        this.tail = newNode 
    
        // 记录长度
        this.len++
      }
    
      /**
       * 出队,在 head 位置出队
       */
      delete() {
        const headNode = this.head
        if (headNode == null) return null
        if (this.len <= 0) return null
    
        // 取值
        const value = headNode.value
    
        // 处理 head指向下一个节点
        // ![](https://s.poetries.work/uploads/2023/01/3d2d72a7370b826a.png)
        this.head = headNode.next
    
        // 记录长度
        this.len--
    
        return value
      }
    
      get length() {
        // length 要单独存储,不能遍历链表来获取(否则时间复杂度太高 O(n))
        return this.len
      }
    }
    // 功能测试
    
    const q = new MyQueue()
    q.add(100)
    q.add(200)
    q.add(300)
    
    console.info('length1', q.length)
    console.log(q.delete())
    console.info('length2', q.length)
    console.log(q.delete())
    console.info('length3', q.length)
    console.log(q.delete())
    console.info('length4', q.length)
    console.log(q.delete())
    console.info('length5', q.length)
    // 性能测试
    
    var q1 = new MyQueue()
    console.time('queue with list')
    for (let i = 0; i < 10 * 10000; i++) {
      q1.add(i)
    }
    for (let i = 0; i < 10 * 10000; i++) {
      q1.delete()
    }
    console.timeEnd('queue with list') // 12ms
    
    // 数组模拟入队出队
    var q2 = []
    console.time('queue with array')
    for (let i = 0; i < 10 * 10000; i++) {
      q2.push(i) // 入队
    }
    for (let i = 0; i < 10 * 10000; i++) {
      q2.shift() // 出队
    }
    console.timeEnd('queue with array') // 425ms
    
    // 结论:同样的计算量,用数组和链表实现相差很多,数据量越大相差越多
Last Updated:
Contributors: leeguooooo