二叉堆(Binary Heap)

Binary Heap:
一个二叉堆(Binary Heap)是具有下面一些属性的二叉树:
1)是一个完全二叉树,即:除了叶子节点以外的其他节点全部有左右子树,并且最后一层的叶子节点按照从左到右填充。
2) 一个二叉堆可以是最大堆或者最小堆。 在最大堆中,根节点的值最大; 在最小堆中,根节点的值最小;
3) 所有子树符合性质2)

最小二叉堆实例

             10                      10
         /      \               /       \  
       20        100          15         30  
      /                      /  \        /  \
    30                     40    50    100   40

二叉堆如何表示
二叉堆是一个完全二叉树,可以用数组来表示。

  1. 根节点在数组arr[0]的位置

  2. 下面的列表中展示对于第i个node 的父,左,右节点的位置

    • Arr[i-1/2] Returns the parent node
    • Arr[(2*i)+1] Returns the left child node
    • Arr[(2*i)+2] Returns the right child node

    使用二叉树的层次遍历得到数组。
    这里写图片描述
    二叉堆的应用
    (1) 堆排序 Heap Sort: 在O(nLogn)时间内排序;
    (2) Priority Queue: Binary Heap支持O(logn)时间的insert() delete() 和extractmax().
    (3)图算法,如Dijkstra’s Shortest Path and Prim’s Minimum Spanning Tree.
    (4) 许多问题可以使用堆解决,如:
    a) K’th Largest/minimum Element in an array.
    b) Sort an almost sorted array
    c) Merge K Sorted Arrays.

最小堆上的操作
(1)获取最小值(getMin):返回根节点,时间复杂度为O(1);
(2)删除最小值extractMin():删除根节点,重建堆, O(logn)
(3)insert(), 在树的末端添加节点,如果节点比parent大,则return, 否则需要向上遍历重建, O(logn)。

Binary Heap相关代码

public class BinaryHeap {
    private static final int DIVID = 2;
    private int heap_size;
    private int[] heap;

    public BinaryHeap(int capacity) {
        heap_size = 0;
        heap = new int[capacity];
        Arrays.fill(heap, -1);
    }

    public boolean isEmpty() {
        return this.heap_size == 0;
    }

    public boolean isFull() {
        return this.heap_size == heap.length;
    }

    //返回parent的index
    private int parent(int index) {
        return (index - 1) / DIVID;
    }

    public int leftChild(int index) {
        return index * DIVID + 1;
    }

    public int rightChild(int index) {
        return index * DIVID + 2;
    }

    // 插入元素i
    public void insert(int i) {
        if (isFull())
            throw new NoSuchElementException("Overflow Exception");
        /** Percolate up **/
        heap[heap_size++] = i;
        heapifyUp(heap_size - 1);
    }

    public int findMin() {
        if (isEmpty())
            throw new NoSuchElementException("Underflow Exception");
        return heap[0];
    }

    public int deleteMin() {
        int keyItem = heap[0];
        delete(0);
        return keyItem;
    }

    public int delete(int index) {
        if (isEmpty())
            throw new NoSuchElementException("Underflow Exception");
        int keyItem = heap[index];
        heap[index] = heap[heap_size - 1];
        heap_size--;
        heapifyDown(index);
        return keyItem;
    }


    private void heapifyUp(int childIndex) {
        int tmp = heap[childIndex];
        while (childIndex > 0 && tmp < heap[parent(childIndex)]) {
            heap[childIndex] = heap[parent(childIndex)];
            childIndex = parent(childIndex);
        }
        heap[childIndex] = tmp;
    }

    private void heapifyDown(int index) {
        int childIndex;
        int tmp = heap[index];
        while (hasChild(index)) {
            childIndex = minChildIndex(index);
            if (heap[childIndex] < tmp)
                heap[index] = heap[childIndex];
            else
                break;
            index = childIndex;
        }
        heap[index] = tmp;
    }

    private int minChildIndex(int index) {
        if (DIVID * index + 2 < heap_size || heap[DIVID * index + 1] < heap[DIVID * index + 2]) {
            return DIVID * index + 1;
        }
        return DIVID * index + 2;
    }

    private boolean hasChild(int index) {
        return DIVID * index + 1 < heap_size;
    }
}

public class BinaryHeapTest {
    @Test
    public void test(){
        BinaryHeap binaryHeap = new BinaryHeap(5);
        binaryHeap.insert(1);
        binaryHeap.insert(4);
        binaryHeap.insert(2);
        binaryHeap.insert(5);
        binaryHeap.insert(0);

        binaryHeap.deleteMin();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值