优先队列的实现

该优先队列的实现依赖于最大堆。关于最大堆,之前的博文:堆排序有讲。

  • heapMaximum返回堆中键最大的元素,即array[0]。
  • heapExtractMax方法删除并返回最大堆中最大键元素。
  • heapIncreaseKey的作用是将元素i的关键字值增加到key
  • maxHeapInsert方法是将元素插入到最大堆中
/**
 * desc : 优先队列
 * Created by tiantian on 2018/7/29
 */
public class PriorityQueue {

    public static int heapSize = 0;

    // 返回集合中最大键元素
    public Integer heapMaximum(Integer[] array) {
        return array[0];
    }

    // 去掉并返回集合中最大键元素
    public Integer heapExtractMax(Integer[] array) throws Exception {
        heapSize = array.length;
        if (heapSize < 1) {
            throw  new Exception("heap underflow");
        }
        Integer max = array[0];
        array[0] = array[--heapSize];
        MaxHeap.heapMaxHeapfy(array, 0);
        return max;
    }

    // 将元素i的关键字值增加到key
    public  void heapIncreaseKey(Integer[] array, int i, Integer key) throws Exception {
        if (i > key) {
            throw new Exception("key is smaller than current key");
        }
        array[i] = key;
        int parent = MaxHeap.HeapNode.parent(i);
        while (i > 0 && array[parent] < array[i]) {
            MaxHeap.exchange(array, i, parent);
            i = parent;
            parent = MaxHeap.HeapNode.parent(parent);
        }
    }

    // 将元素插入到最大堆中
    public Integer[] maxHeapInsert(Integer[] array, Integer key) throws Exception {
        heapSize = array.length + 1;
        Integer[] newArray = new Integer[heapSize];
        System.arraycopy(array, 0, newArray, 0, heapSize-1);
        // 构造堆中最后一个元素为最小元素
        newArray[heapSize-1] = -65535;
        // 将最小元素增加到key即完成插入操作
        heapIncreaseKey(newArray, heapSize-1, key);
        return newArray;
    }
}

优先队列所依赖的最大堆数据结构的实现如下

/**
 * desc : 最大堆
 * Created by tiantian on 2018/7/29
 */
public class MaxHeap {

    public static int heapSize = 0;
    // 维护最大堆
    public static void heapMaxHeapfy(Integer[] array, int i) {
        heapSize = array.length;
        int l = HeapNode.left(i);
        if (l >= heapSize) { 
            return;
        }

        int r = HeapNode.right(i);
        if (r >= heapSize) {
            return;
        }

        int largest;
        if (l <= heapSize && array[l] > array[i]) {
            largest = l;
        } else {
            largest = i;
        }

        if (r <= heapSize && array[r] > array[largest]) {
            largest = r;
        }

        if (largest != i) {
            exchange(array, i, largest);
            heapMaxHeapfy(array, largest);
        }
    }

    // 构建最大堆
    public static void heapBuiltMaxHeap(Integer[] array) {
        int i = (array.length)/2;
        while (i >= 0) {
            heapMaxHeapfy(array, i);
            i--;
        }
    }

    public static void exchange(Integer[] array, int a, int b) {
        Integer temp = array[a];
        array[a] = array[b];
        array[b] = temp;
    }

    // 返回堆元素父节点下标,或者左右子节点下标。
    public static class HeapNode {
        public static int parent(int i) {
            if (i == 2) {
                return 0;
            }
            return i/2;
        }

        public static int left(int i) {
            return 2*i+1;
        }

        public static int right(int i) {
            return 2 * i + 2;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37577221/article/details/81437107