TDD 实现队列以及优先级队列[幼儿园版]

107 阅读1分钟

队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

github 手写,tdd 测试通过

import { Queue, passGame } from "./Queue";

import { expect, assert, describe, it, test } from 'vitest';


const queue = new Queue();

describe('Queue', () => {
  it('new', () => {
    expect(queue.size()).toBe(0)
  })
  it('enqueue', () => {
    queue.enqueue('top')
    expect(queue.size()).toBe(1)
  })
  it('front', () => {
    expect(queue.front()).toBe('top')
  })
  it('iSEmpty', () => {
    expect(queue.isEmpty()).toBe(false)
    queue.dequeue()
    expect(queue.isEmpty()).toBe(true)
  })
  it('size', () => {
    queue.enqueue('1')
    queue.enqueue('2')
    expect(queue.size()).toBe(2)
  })
  it('toString', () => {
    expect(queue.toString()).toBe('1 2')
  })
})
describe('击鼓传花', () => {
  it('passGame', () => {
    expect(passGame(['ldq', 'link', 'nb'], 5)).toBe(0)
  })
})
export class Queue {
  queue: any[] = [];
  static enqueue: Function;
  static dequeue: Function;
  static front: Function;
  static size: Function;
  static isEmpty: Function;
  static toString: Function;
  enqueue(value: any) {
    this.queue.push(value)
  }
  dequeue() {
    return this.queue.shift()
  }
  front() {
    if (this.isEmpty()) {
      return undefined
    } else {
      return this.queue[0]
    }
  }
  size() {
    return this.queue.length
  }
  isEmpty() {
    return this.queue.length == 0
  }
  toString() {
    return this.queue.join(' ')
  }
}
// 击鼓传花
export function passGame(nameList: any[], num: number) {
  // 创建一个队列
  const queue = new Queue()
  // 将所有的人加入队列
  for (let i = 0; i < nameList.length; i++) {
    queue.enqueue(nameList[i])
  }
  // 开始数数字
  while (queue.size() == 1) {
    for (let i = 0; i < num; i--) {
      queue.enqueue(queue.dequeue())
    }
    queue.dequeue()
  }
  return nameList.indexOf(queue.front())
}

优先级对列

优先级对列和普通队列的区别 就是在push 的时候有一些区别,会去判断元素的优先级,然后在合适的地方插入

export class PriorityQueue extends Queue {
  constructor(
    // 处理判断优先级
    private hanlder: Function,
    // 处理元素
    private getElement: Function,
    // 处理输出hanlder
    public toStrHanlder: Function
  ) {
    super();
  }

  enqueue(element: QueueEl): void {
    const el = this.getElement(element)

    if (this.isEmpty()) {
      this.queue.push(el)
    } else {
      var added = false
      for (let i = 0; i < this.queue.length; i++) {
        if (this.hanlder(el, this.queue[i])) {
          this.queue.splice(i, 0, el)
          added = true
          break;
        }
      }
      if (!added) {
        this.queue.push(el)
      }
    }
  }
  toString(): string {
    return this.queue.map((m: QueueEl) => this.toStrHanlder(m)).join(' ')
  }
}
describe('优先级队列', () => {
  it('PriorityQueue', () => {

    interface QueueEl {
      value: any,
      priority: number
    }

    // 比较函数
    const hanlder = function (el: any, el2: any): boolean {
      return el.priority < el2.priority
    }
    // 处理元素
    const getElement = function (el: QueueEl): QueueEl {
      return {
        value: el.value,
        priority: el.priority / 10
      }
    }
    // 处理输出hanlder
    const toStrHanlder = function (element: QueueEl): string {
      return element.value + '-' + element.priority
    }
    const pq = new PriorityQueue(hanlder, getElement, toStrHanlder)

    pq.enqueue({ value: 'link', priority: 50 })
    pq.enqueue({ value: 'ldq', priority: 100 })
    pq.enqueue({ value: 'nb', priority: 10 })

    expect(pq.toString()).toBe('nb-1 link-5 ldq-10')
  })
})