(数据结构)堆、二叉堆(java实现)

1.堆是一种完全二叉树:

2.在堆中有两个重要的公式:

已知parent下标,left=2*parent+1 right=2*parent+2

已知child的下标(不分左右) parent=(child-1)/2;

3.堆    1)逻辑上是一种完全二叉树     2)物理上是一个数组

4.满足任意位置的值>=它的左右孩子的值 大堆

反之                         <=                              小堆

5.

关于堆有以下几个重要操作:

向下调整(堆化)大堆:

前提:在整个堆中,除了要调整的位置之外,其余位置都已经满足堆的性质了

0)如果要调整的位置是叶子结点,调整结束

1)找到两个孩子中最大的一个孩子

2)比较最大孩子的值和要调整位置的值

a.如果满足堆的性质了,调整结束

b.否则,交换两个的值,继续调整原来最大的孩子的下标位置

只有左孩子 =》左孩子

左右都有,左孩子大 =》左孩子

左右都有,右孩子大 =》右孩子


 /**
     * 前提:除了index和它的孩子外,其他位置已经满足堆的性质了,调整堆,调整为大堆,向下调整
     * @param array 被看作堆的数组
     * @param size  数组中被看作堆的值的个数
     * @param index 要调整位置的下标
     */
    public static void heapify(int [] array,int size,int index){
        while(true){
            int left=2*index+1;
            if(left>=size){
                return;
            }
            int max=left;
            if(left+1<size&&array[left+1]>array[left]){
                max=left+1;
            }
            if(array[index]>=array[max]){
                return;
            }
            swap(array,index,max);
            index=max;
        }
    }

//调整为小堆,向下调整
    public static void heapifyMin(int [] array,int size,int index){
        while(true){
            int left=2*index+1;
            if(left>=size){
                return;
            }
            int min=left;
            if(left+1<size&&array[left+1]<array[left]){
                min=left+1;
            }
            if(array[index]<=array[min]){
                return;
            }
            swap(array,index,min);
            index=min;
        }
    }

建堆:任意数组转成堆

1)从[最后一个非叶子结点,0],向下调整

2)最后一个非叶子结点:最后一个节点的双亲 下标为:(size-2)/2

3)最后一个结点的下标:size-1

//建堆,构建为大堆
    //复杂度为O(n),粗略为0(n*log(n))
    public static void createHeap(int [] array,int size){
       for(int i=(size-2)/2; i>=0; i--){
           heapify(array,size,i);
        }
    }


    //建堆,构建为小堆
    public static void createHeapMin(int [] array,int size){
        for(int i=(size-2)/2;i>=0;i--){
            heapifyMin(array,size,i);
        }
    }

向上调整大堆:

前提:在整个堆中,除了要调整的位置之外,其余位置都已经满足堆的性质了

1)利用公式找到index的父结点

2)设max为父结点,

3)如果满足堆的性质了,直接返回

4)如果不满足,交换两个下标中数组的值,,令max为index

  //向上调整大堆,除了index和它的孩子外,其余位置已经满足堆的性质了
    public static void adjustUp(int [] array,int index) {
        while (true) {
            if(index<=0){
                return;
            }
            int parent = (index - 1) / 2;
            int max = parent;
            if (array[max] >= array[index]) {
                return;
            }
            swap(array, index, max);
            index = max;
        }
    }
    //向上调整小堆,前提:除了index和它的孩子外,其余位置已经满足堆的性质了
    public static void adjustUpMin(int [] array,int index){
        while(index >0){
            int parent=(index-1)/2;
            int min=parent;
            if(array[min]<=array[index]){
                return;
            }
            swap(array,index,min);
            index=min;
        }
    }

发布了62 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43669007/article/details/100541000