1.堆简介:

  • 堆是一个完全二叉树,这就是它的一个优秀的特点,因此可将它看为一个一维数组,并且每个结点都对应数组元素。
  • 堆的根结点>孩子结点(称为大堆)或 根结点<孩子结点(称为小堆)。
    (本篇文章全以大堆为例)
    排序算法--堆排序之堆的构建以及怎样通过heapify操作完成堆排序排序算法--堆排序之堆的构建以及怎样通过heapify操作完成堆排序
    2,堆排序
    堆排序可以看做以下几个步骤:
  • ①将一个完全无序的数组建成堆
  • ②建成的堆的根结点就是所有结点中最大值,将其与最后一个结点交换
  • ③砍断最后一个结点,即得到了这个数组中的最大值
  • ④重新从新的第一个结点开始堆化
  • 重复以上步骤,直到堆中只剩一个结点

举例:
①这是一个建好的大堆:
排序算法--堆排序之堆的构建以及怎样通过heapify操作完成堆排序
②交换根结点和最后一个结点,砍断最后一个结点
排序算法--堆排序之堆的构建以及怎样通过heapify操作完成堆排序
因为交换了根结点和最后一个结点,此时一定破坏了堆的结构,所有要对其从根结点开始重新堆化。
排序算法--堆排序之堆的构建以及怎样通过heapify操作完成堆排序
排序算法--堆排序之堆的构建以及怎样通过heapify操作完成堆排序
③再次交换根结点和最后一个结点,砍断,堆化。这样重复下去直到堆中只有一个结点

注意:

  • 堆化的前提是是完全二叉树并且只有一个地方不满足堆的条件,堆化是从上往下
  • 建堆程是从第一个非叶子结点到根结点一直做堆化的过程
  • 具体的建堆以及堆化大家快去看up主正月点灯笼的视频啦,超级棒!

Java实现:

//堆排序
    private static void heapSort(int[] array,int size){
        //建堆
        createHeap(array);
        for(int i=size-1;i>=0;i--){
            //交换根结点(最大值)和最后一个结点
            int tmp=array[i];
            array[i]=array[0];
            array[0]=tmp;

            //砍断最后一个结点并继续堆化,得到新的根结点(最大值)
            heapify(array,0,i);
        }
    }



    private static void createHeap(int[] array){
        for(int i=(array.length-2)/2;i>=0;i--){
            heapify(array,i,array.length);
        }
    }

    private static void heapify(int[] array, int index,int size) {
        int max=index*2+1;  //假定左孩子是最大值
        while(max<size){  //左孩子存在
           if(max+1<size && array[max+1]>array[max]){  //如果右孩子存在并且右孩子是最大值,交换
               max=max+1;
           }
           if(array[index]>=array[max]){   //如果要堆化的结点值本身就大于最大值,直接退出循环
               break;
           }
           //否则交换要堆化的结点值和最大值
           int tmp=array[index];
           array[index]=array[max];
           array[max]=tmp;

           index=max;  //向下继续堆化
           max=max*2+1

        }
    }

相关文章: