堆排序

一、算法基本思想

(1)基本思想

堆排序的基本思想就是:从最大(小)堆得顶部不断取走堆顶元素放到有序序列中,直到堆的元素被全部取完。堆排序完全依赖于最大(小)堆的相关操作。

(2)运行过程
堆排序算法的运作如下:
1、创建一个最大(小)堆H;
2、把堆首和堆尾元素互换;
3、把堆的大小减1,重新构造一个最大(小)堆;
4、重复步骤2、3,直到堆的大小减少为1。

(3)最大堆的构建
在这里插入图片描述
(4)堆排序过程
在这里插入图片描述
(5)Java代码实现

public class HeapSortTest {

    public static void main(String[] args) {
       int[] arr = {3,6,1,7,2,9,5};
       HeapSortTest.heapSort(arr);
       System.out.println(Arrays.toString(arr));
   }
   
   /**
    * 选择排序-堆排序
    * @param array 待排序数组
    * @return 已排序数组
    */
    public static int[] heapSort(int[] array) {
       //这里元素的索引是从0开始的,所以最后一个非叶子结点array.length/2 - 1
       for (int i = array.length / 2 - 1; i >= 0; i--) {
           adjustHeap(array, i, array.length);  //调整堆
           System.out.println(Arrays.toString(array));
       }
    
       // 上述逻辑,建堆结束
       // 下面,开始排序逻辑
       for (int j = array.length - 1; j > 0; j--) {
          // 元素交换,作用是去掉大顶堆
          // 把大顶堆的根元素,放到数组的最后;换句话说,就是每一次的堆调整之后,都会       // 有一个元素到达自己的最终位置
          swap(array, 0, j);
          // 元素交换之后,毫无疑问,最后一个元素无需再考虑排序问题了。
          // 接下来我们需要排序的,就是已经去掉了部分元素的堆了,这也是为什么此方法放       //在循环里的原因
          // 而这里,实质上是自上而下,自左向右进行调整的
          adjustHeap(array, 0, j);
       }
       return array;
   }
    
       /**
       * 整个堆排序最关键的地方
       * @param array 待组堆
       * @param i 起始结点
       * @param length 堆的长度
       */
       public static void adjustHeap(int[] array, int i, int length) {
           // 先把当前元素取出来,因为当前元素可能要一直移动
           int temp = array[i];
           for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {  //2*i+1为左树 i的左子树(因为i是从0开始的),2*k+1为k的左子树
               // 让k先指向子节点中最大的节点
               if (k + 1 < length && array[k] < array[k + 1]) {  //如果有右子树, 并且右子树大于左子树
                   k++;
               }
               //如果发现结点(左右子结点)大于根结点,则进行值的交换
               if (array[k] > temp) {
                   swap(array, i, k);
                   // 如果子节点更换了,那么,以子节点为根的子树会受到影响,所以,循环对子节点所在的树继续进行判断
                   i  =  k;
               } else {  //不用交换,直接终止循环
                   break;
               }
           }
       }
    
       /**
       * 交换元素
       * @param arr
       * @param a 元素的下标
       * @param b 元素的下标
       */
       public static void swap(int[] arr, int a, int b) {
           int temp = arr[a];
           arr[a] = arr[b];
           arr[b] = temp;
       }
      
}



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值