算法笔记20:优先队列

205 阅读1分钟

上一篇笔记说了堆的特性和如何利用这个特性排序。利用堆的特性也可以实现优先队列。这种数据结构可以维护一个优先级队列,这个队列虽然不能保证所有元素在队列里都是按照优先级从高到低排列,但是它会保证下一个出队列的元素一定是所有元素中优先级最高的。

所以使用大顶堆的特性就可以了,保持堆顶的元素一定是最大的,每次出队列的时候出堆顶,然后入队列的时候替换位置。

代码如下:

class PriorityQueue {
    queue: number[] = [];
    
    parentIndex(i: number) {
        return Math.floor((i - 1) / 2)
    }
    
    leftChildIndex(i: number) {
        return i * 2 + 1;
    }
    
    rightChildIndex(i: number) {
        return i * 2 + 2;
    }
  
    offer(item: number) {
        this.queue.push(item);
        this.shiftUp(this.queue.length - 1);
    }
    
    poll() {
        const item = this.queue.shift();

        if (this.queue.length !== 0) {
            const lastLeaf = this.queue.pop();
            this.queue.unshift(lastLeaf);
            this.shiftDown(0);
        }    
        return item;
    }
    
    shiftUp(i: number) {
        const parentIndex = this.parentIndex(i);
        if (i > 0 && this.queue[parentIndex] < this.queue[i]) {
            this.swap(i, parentIndex);
            this.shiftUp(parentIndex);
        }
    }
    
    shiftDown(i: number) {
        let largest = i;
        const l = this.leftChildIndex(i);
        const r = this.rightChildIndex(i);
        
        if (l < this.queue.length && this.queue[largest] < this.queue[l]) {
            largest = l;
        }
        if (r < this.queue.length && this.queue[largest] < this.queue[r]) {
            largest = r;
        }
        
        if (largest != i) {
            this.swap(i, largest);
            this.shiftDown(largest);
        }
    }
    
    swap(l: number, r: number) {
        const t = this.queue[l];
        this.queue[l] = this.queue[r];
        this.queue[r] = t;
    }
}