温习Algs4 (二):优先级队列(堆)

优先级队列

优先级队列 (Priority Queue) 实质上是一个堆, 支持的操作是push和pop, pop时总是返回当前队列中的最小(大)值.

PQ.java

/******************************************************************************
 *  Compilation:  javac PQ.java
 *  Execution:    java PQ
 *  Author:       Chenghao Wang
 ******************************************************************************/

public class PQ<T extends Comparable<T>> {
    public static final int MIN_PQ = 0;
    public static final int MAX_PQ = 1;
    private Vector<T> heap = new Vector<T>();
    private int type;

    PQ() {
        this(MIN_PQ);
    }

    PQ(int type) {
        this.type = type;
        heap.add(null);
    }

    private boolean shouldSwap(int up, int down) {
        T a = heap.get(up);
        T b = heap.get(down);
        int cmp = a.compareTo(b);
        if (type == MIN_PQ) {
            return cmp > 0;
        } 
        else {
            return cmp < 0;
        }
    }

    private void swap(int i, int j) {
        T tmp = heap.get(i);
        heap.set(i, heap.get(j));
        heap.set(j, tmp);
    }

    public void push(T item) {
        heap.add(item);
        for (int curr = heap.size() - 1; curr > 1; curr /= 2) {
            int next = curr / 2;
            if (shouldSwap(next, curr)) {
                swap(next, curr);
            } 
            else {
                break;
            }
        }
    }

    public T pop() {
        T result = heap.get(1);
        swap(1, heap.size() - 1);
        heap.remove(heap.size() - 1);
        int next = 0;
        for (int curr = 1; (curr * 2) < heap.size(); curr = next) {
            next = curr * 2;
            if (next < (heap.size() - 1) && shouldSwap(next, next + 1)) {
                next++;
            }
            if (shouldSwap(curr, next)) {
                swap(curr, next);
            } 
            else {
                break;
            }
        }
        return result;
    }
}

索引优先级队列

索引优先级队列 (Indexed Priority Queue) 是在优先级队列的基础上添加了索引功能, 即可以将一个值与一个索引绑定, 主要用于 Dijkstra和最小生成树算法上.

IndexPQ.java

/******************************************************************************
 *  Compilation:  javac IndexPQ.java
 *  Execution:    java IndexPQ
 *  Author:       Chenghao Wang
 ******************************************************************************/

public class IndexPQ<T extends Comparable<T>> {
    public static final int MIN_PQ = 0;
    public static final int MAX_PQ = 1;
    private boolean[] mark;
    private int[] heap;
    private int heapPtr;
    private T[] indexes;
    private int type;
    private int capacity;

    IndexPQ(int size) {
        this(MIN_PQ, size);
    }

    IndexPQ(int type, int size) {
        capacity = size;
        this.type = type;
        heap = new int[size + 1];
        mark = new boolean[size];
        indexes = (T[]) (new Comparable[size]);
        heapPtr = 1;
    }

    private boolean shouldSwap(int up, int down) {
        T a = indexes[heap[up]];
        T b = indexes[heap[down]];
        int cmp = a.compareTo(b);
        if (type == MIN_PQ) {
            return cmp > 0;
        } 
        else {
            return cmp < 0;
        }
    }

    private void swap(int i, int j) {
        int tmp = heap[i];
        heap[i] = heap[j];
        heap[j] = tmp;
    }

    private void adjustBottomUp(int i) {
        for (int curr = i; curr > 1; curr /= 2) {
            int next = curr / 2;
            if (shouldSwap(next, curr)) {
                swap(next, curr);
            } 
            else {
                break;
            }
        }
    }

    private void adjustTopDown(int i) {
        int next  = 1;
        for (int curr = i; (curr * 2) < heapPtr; curr = next) {
            next = curr * 2;
            if ((next < (heapPtr - 1)) && shouldSwap(next, next + 1)) {
                next++;
            }
            if (shouldSwap(curr, next)) {
                swap(curr, next);
            } 
            else {
                break;
            }
        }
    }

    public void push(int index, T item) {
        if (mark[index]) {
            change(index, item);
            return;
        }

        mark[index] = true;
        heap[heapPtr++] = index;
        indexes[index] = item;
        adjustBottomUp(heapPtr - 1);
    }

    public void change(int index, T item) {
        T old = indexes[index];
        int cmp = old.compareTo(item);
        if (cmp == 0) return;
        indexes[index] = item;
        int i = 1;
        while (heap[i] != index) i++;
        if (type == MIN_PQ) {
            if (cmp < 0) {
                adjustTopDown(i);
            }
            else {
                adjustBottomUp(i);
            }
        }
        else {
            if (cmp > 0) {
                adjustTopDown(i);
            }
            else {
                adjustBottomUp(i);
            }        
        }
    }

    public int pop() {
        int result = heap[1];
        mark[result] = false;
        heapPtr--;
        swap(1, heapPtr);
        adjustTopDown(1);
        return result;
    }

    public T getValue(int index) {
        return indexes[index];
    }

    public boolean contains(int index) {
        return mark[index];
    }

    public boolean isEmpty() {
        return heapPtr == 1;
    }

    public int size() {
        return heapPtr - 1;
    }
}

总结

这两个数据结构我认为非常有用, 不仅可以代替排序算法, 而且在后续的最短路径, 最小生成树和最小费用最大流问题上扮演着关键的角色.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值