用java实现堆

    科技2022-07-11  99

    1、堆是一种特殊的二叉树

    堆总是一颗完全二叉树(即除最底层外,其它层节点都被元素填满,且最底层从左向右尽可能填满结点)

    2、分为最大堆和最小堆,最大堆中某结点的值总是不大于其父节点的值,最小堆中某结点的值总是不小于其父节点的值

    3、堆的实现:  用数组实现    构造二叉树     

    ArrayList<Integer> array=new ArrayList<Integer>(); //ArrayList<Integer> array=new ArrayList<Integer>(capacity);

    数组是按层次存放堆这棵二叉树中的结点值的

    数组中的元素并不是按从大到小的顺序排列的,从堆中取出元素只能取出堆顶元素,即只能获得最大值或最小值

    4、index为数组中当前元素的索引,则该元素的父节点在数组中的索引为(index-1)/2,该元素的左孩子在数组中的索引为2*index+1,该元素的右孩子在数组中的索引为2*index+2

    5、以最大堆为例

    (1)向堆中添加元素:

    时间复杂度:O(logn)

    将该元素先添加到数组的尾部(即充当最底层的最后一个叶结点),然后将该元素与其父节点进行大小比较,若大于其父节点则与父节点进行交换,继续与上一层父节点进行比较,如此重复,直至小于等于父节点为止

    //向堆中添加元素 public void addValue(ArrayList<Integer> array,int value) { if(array==null) return; array.add(value); int i=array.size()-1; while(i>=1&&value>array.get((i-1)/2)) { array.set(i,array.get((i-1)/2)); array.set((i-1)/2,value); i=(i-1)/2; } }

    (2)删除堆顶元素:

    时间复杂度:O(logn)

    将堆顶元素A与最后一个元素B交换后(即数组的首尾元素互换),删除A,从堆顶元素开始比较其与左右孩子的大小,若同时小于左右孩子,则与左右孩子中的较大者交换,否则与大于其的孩子交换,继续与下一层左右孩子进行比较,如此重复,直至大于等于左右孩子为止

    removeValue=swap+sift

    //删除堆顶元素 public void removeValue(ArrayList<Integer> array) { if(array==null||array.size()==0) return; array.set(0,array.get(array.size()-1)); array.remove(array.size()-1); int i=0; while(2*i+1<array.size()) { int value=array.get(i); int a=array.get(2*i+1); int max=a; int index=2*i+1; //左右孩子都存在 if(2*i+2<array.size()) { int b=array.get(2*i+2); if(b>a) { max=b; index=2*i+2; } } if(value<max) { array.set(i,max); array.set(index,value); i=index; } else break; } }

    (3)返回堆中的元素个数

    return array.size();

    (4)判断堆是否为空

    return array.isEmpty();

    (5)返回数组索引

    //返回父节点在数组中的索引 return (index-1)/2; //返回左孩子在数组中的索引 return 2*index+1; //返回右孩子在数组中的索引 return 2*index+2;

    (6)替换:将堆顶元素替换为其他元素

             时间复杂度:O(logn)

    removeValue()+addValue()

    (7)Heapify:将任意数组转化为堆的形状

    时间复杂度:O(n)

    将数组看成一棵完全二叉树,从最后一个叶节点的父节点开始,到根节点结束,依次判断各节点与其左右孩子的大小关系并进行调整

    0~array.size()-1/2进行sift

    public void heapify(ArrayList<Integer> array) { int y=array.size()-1; int i=(y-1)/2; for(int j=i;j>=0;j--) sift(array,j); return; } public void sift(ArrayList<Integer> array,int i) { while(2*i+1<array.size()) { int value=array.get(i); int a=array.get(2*i+1); int max=a; int index=2*i+1; //左右孩子都存在 if(2*i+2<array.size()) { int b=array.get(2*i+2); if(b>a) { max=b; index=2*i+2; } } if(value<max) { array.set(i,max); array.set(index,value); i=index; } else break; } }

    将n个元素插入一个空堆中,时间复杂度为O(nlogn)

    6、优先队列具有最高优先级先出的特点,所以采用最大堆数据结构

          java.util.PriorityQueue类底层就是通过优先级堆实现的

    Processed: 0.009, SQL: 8