堆排序

1.堆的基本介绍

1)堆排序是利用堆的这种数据结构设计的排序算法,堆排序是一种选择排序,最好最坏时间复杂度为O(nlogn),它是不稳定的排序。

2)堆是具有以下性质的完全二叉树:每个节点的值都大于或等于其左右孩子结点的值,称为大顶堆,注意:没要求左右孩子之间的关系。

3)每个结点的值都小于或等于左右孩子结点的值为小顶堆
4)大顶堆

5)小顶堆

2.堆排序的思想

1)将待排序列构成一个大顶堆,此时整个序列的最大值就是堆顶的根节点;

2)将其与末尾元素进行交换,此时末尾元素为最大值;

3)然后将最大元素取出,剩下的n-1个元素重新构造成一个大顶堆,如此反复执行,便能得到一个有序序列。
3.构建大顶堆步骤

1)假设给定无序序列结构如下

2)此时我们从最后一个非叶子节点开始(叶子节点不用调整,第一个非叶子节点:arr.length/2-1,也就是下面的6结点),从左至右,从下至上调整。让6与自己的左右子节点进行比较,与大的交换,如下图

3)找到第二个非叶子节点4,由于【4,9,8】中9最大,4和9交换

4)这时,交换导致左子树【4,5,6】结构混乱,继续调整,将4和6交换

5)此时完成,
代码:

package com.sratct.tree;

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args) {
        int [] arr = {14,52,31,61,41,25,32,16,62};
        headSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void headSort(int[] arr) {
        int temp =0;
        // 构建大顶堆
        for (int i = arr.length/2-1; i>=0; i--) {
            adjustHeap(arr, i, arr.length);
        }

        // 将堆顶元素和末尾元素交换,再重新构建
        for (int j=arr.length-1;j>0;j--) {
            // 交换元素
            temp = arr[0];
            arr[0] =arr[j];
            arr[j] = temp;
            adjustHeap(arr,0,j);
        }
    }
   /* *
     * 以i对应的非叶子节点,将其调整为大顶堆
     * @param arr 待数组
     * @param i // 表示非叶子节点在数组中的索引
     * @param length 表示对多少个元素进行调整,length逐渐减少*/

    public static void adjustHeap(int[] arr, int i, int length) {
        int temp = arr[i];  // 需要调整的值
        // k的初始值为i结点的左子结点
        for (int k = i*2+1; k<length; k=k*2+1) {
              if (k+1<length && arr[k] < arr[k+1]) {
                  k++;
              }
              if (temp < arr[k]) {
                  arr[i] = arr[k];  // 将较大值赋给当前结点
                  i = k;
              } else {
                  break;
              }
        }
        // 当for循环结束后,已将i为父节点的树的最大值,放在了最顶(局部)
        arr[i] = temp; // 结束后将temp放到调整后的位置
    }
}

原文地址:https://www.cnblogs.com/cqyp/p/14745320.html