zoukankan      html  css  js  c++  java
  • 堆(优先队列)

    二叉堆

    二叉堆常常用于优先队列的实现。

    堆是一个被完全填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入。

    因为二叉堆是完全二叉树,所以可以使用数组表示,而不需要使用链表。(使用链表似乎代码实现方便点)

    堆序性质

    任意节点的值都小于它所有字节点的值

    代码实现

    /**
     * 二叉堆
     * 将堆数据存放在数组内,对自上而下,自左而右的数据依次放到数组中,数组索引从1开始,即array[0]不存放数据
     */
    public class BinaryHeap {
        public BinaryHeap(){}
    
        public BinaryHeap(int x){
            currentSize++;
            array[currentSize]=x;
        }
    
        public BinaryHeap(int[] items){
            currentSize=items.length;
            array = new int[(currentSize+2)*11/10];
            int i=1;
            for(int item:items){
                array[i++]=item;
            }
            buildHeap();
        }
    
        public void insert(int x){
            if(currentSize==array.length-1) enlargeHeap(array.length*2+1);
            //hole代表空穴的位置
            int hole = ++currentSize;
            //空穴的位置上浮
            for(;hole>1 && x<(array[hole/2]);hole/=2){
                array[hole]=array[hole/2];
            }
            //最后空穴的位置为hole
            //将x放入空穴
            array[hole]=x;
        }
    
        public int findMin() throws Exception{
            if(isEmpty()) throw new Exception("堆为空");
            return array[1];
        }
    
        public int deleteMin()throws Exception{
            if(isEmpty()) throw new Exception("无法对空堆作删除操作");
            int min = findMin();
            //把最后一个元素放在首位,并减小堆大小currentSize
            array[1]=array[currentSize--];
            //然后调整堆第一个元素的位置
            percolateDown(1);
            return min;
        }
    
        public boolean isEmpty(){
            return currentSize==0;
        }
    
        public void makeEmpty(){
            currentSize=0;
        }
    
        private static final int DEFAULT_CAPCITY=10;
    
        private int currentSize=0;
        private int[] array;
    
        //对hole位置的元素做下沉操作
        private void percolateDown(int hole){
            int child=0;
            int tmp = array[hole];
            for(;hole*2<=currentSize;hole=child){
                child=hole*2;
                if(child!=currentSize && array[child+1]<array[child]) child++;
                if(array[child]<tmp) array[hole]=array[child];
                else break;
            }
            array[hole]=tmp;
        }
    
        private void buildHeap(){
            for (int i=currentSize/2;i>0;i--){
                percolateDown(i);
            }
        }
    
        private void enlargeHeap(int newSize){
            if(newSize<=array.length) return;
            int[] tmp = new int[newSize];
            for(int i=1;i<=currentSize;i++){
                tmp[i]=array[i];
            }
            array=tmp;
        }
    }
    
  • 相关阅读:
    C++11多线程
    C++单例模式
    从五大结构体,带你掌握鸿蒙轻内核动态内存Dynamic Memory
    云小课 | 云硬盘不用了如何处理?
    Kafka 源码解析:Server 端的运行过程
    带你掌握4种Python 排序算法
    面试官问我:如何减少客户对交付成果的质疑
    如何基于MindSpore实现万亿级参数模型算法?
    Go 接口类型
    Go 结构体
  • 原文地址:https://www.cnblogs.com/wuchaodzxx/p/6811888.html
Copyright © 2011-2022 走看看