堆排序Java代码实现

堆排序

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

算法描述

  1. 将初始待排序关键字序列 (R1,R2….Rn) 构建成大顶堆,此堆为初始的无序区;
  2. 将堆顶元素 R[1] 与最后一个元素 R[n] 交换,此时得到新的无序区 (R1,R2,……Rn-1) 和新的有序区 (Rn),且满足 R[1, 2… n-1] <= R[n];
  3. 由于交换后新的堆顶 R[1] 可能违反堆的性质,因此需要对当前无序区 (R1, R2, …… Rn-1) 调整为新堆,然后再次将 R[1] 与无序区最后一个元素交换,得到新的无序区 (R1, R2 …. Rn-2) 和新的有序区 (Rn-1, Rn)。不断重复此过程直到有序区的元素个数为 n-1,则整个排序过程完成。

算法分析

  • 时间复杂度:
    • 最佳情况:T(n) = O(nlogn) 
    • 最差情况:T(n) = O(nlogn) 
    • 平均情况:T(n) = O(nlogn)
  • 空间复杂度:O(1) 
  • 稳定性:不稳定

代码实现

public class HeapSort {
    public static void heapSort(int[] arr) {
        if (arr == null || arr.length <= 1) return;
        // 建堆。
        buildHeap(arr);
        int len = arr.length;
        while (len > 1) {
            // 把堆顶和最后一个元素交换。
            swap(arr, 0, len - 1);
            // 交换完之后,逻辑上去掉最后一个元素。
            len--;
            // 重新调整堆的顺序。
            heapfy(arr, 0 , len);

            // 把每一趟排序的结果也输出一下。
            print(arr);
        }
    }

    private static void buildHeap(int[] arr) {
        // 最后一个非叶子结点:2i + 1 >= arr.length  -->  i >= (arr.length - 1) / 2
        for (int i = (arr.length - 1) / 2 - 1; i >= 0; i--) {
            heapfy(arr, i, arr.length);
        }
    }

    // 调整堆的顺序,保持大顶堆。
    private static void heapfy(int[] arr, int i, int len) {
        while (true) {
            int maxPostion = i;
            int leftChild = 2 * i + 1;  // 左孩子索引。
            int rightChild = 2 * i + 2; // 右孩子索引。

            // 若左孩子大于最大值,则更新最大值。
            if (leftChild < len && arr[leftChild] > arr[maxPostion]) {
                maxPostion = leftChild;
            }

            // 若右孩子大于最大值,则更新最大值。
            if (rightChild < len && arr[rightChild] > arr[maxPostion]) {
                maxPostion = rightChild;
            }

            if (maxPostion == i) {
                break;  // 若已经是大顶堆了,则退出循环。
            } else {
                swap(arr, i, maxPostion);   // 若不是大顶堆,则交换位置。
                i = maxPostion;
            }
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] =temp;
    }

    public static void main(String[] args) {
        int[] arr = {6, 9, 1, 4, 5, 8, 7, 0, 2, 3};

        System.out.print("排序前:  ");
        print(arr);

        heapSort(arr);

        System.out.print("排序后:  ");
        print(arr);
    }

    // 打印数组
    public static void print(int[] arr) {
        if (arr == null)    return;

        for(int i : arr) {
            System.out.print(i + " ");
        }
        System.out.println();
    }
}
/*
排序前:  6 9 1 4 5 8 7 0 2 3 
8 6 7 4 5 1 3 0 2 9 
7 6 3 4 5 1 2 0 8 9 
6 5 3 4 0 1 2 7 8 9 
5 4 3 2 0 1 6 7 8 9 
4 2 3 1 0 5 6 7 8 9 
3 2 0 1 4 5 6 7 8 9 
2 1 0 3 4 5 6 7 8 9 
1 0 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
排序后:  0 1 2 3 4 5 6 7 8 9 
*/

 

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
堆排序是一种基于二叉堆数据结构的排序算法,它的时间复杂度为O(nlogn)。下面是一个使用Java实现堆排序代码示例: ```java public class HeapSort { public static void heapSort(int[] arr) { int n = arr.length; // 构建最大堆 for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i); // 逐个将堆顶元素移到数组末尾 for (int i = n - 1; i > 0; i--) { // 将当前堆顶元素(最大值)与数组末尾元素交换 int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; // 重新构建最大堆 heapify(arr, i, 0); } } // 调整以index为根节点的子树为最大堆 public static void heapify(int[] arr, int n, int index) { int largest = index; // 初始化最大值为根节点 int left = 2 * index + 1; // 左子节点索引 int right = 2 * index + 2; // 右子节点索引 // 如果左子节点大于根节点,则更新最大值索引 if (left < n && arr[left] > arr[largest]) largest = left; // 如果右子节点大于当前最大值,则更新最大值索引 if (right < n && arr[right] > arr[largest]) largest = right; // 如果最大值不是根节点,则交换根节点和最大值 if (largest != index) { int swap = arr[index]; arr[index] = arr[largest]; arr[largest] = swap; // 递归调整交换后的子树 heapify(arr, n, largest); } } public static void main(String[] args) { int[] arr = { 12, 11, 13, 5, 6, 7 }; heapSort(arr); System.out.println("排序后的数组:"); for (int i : arr) { System.out.print(i + " "); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值