排序算法之堆排序

堆排序是一种基于比较的排序算法,它利用了完全二叉树(通常为近似完全二叉树)的结构特性——堆来实现对数据的排序。堆是一个特殊的树形数据结构,其中每个节点的值都大于或等于(对于大顶堆)其子节点的值,或者每个节点的值都小于或等于(对于小顶堆)其子节点的值。

**堆排序的基本步骤:**

1. **构建堆:**
   首先将待排序的数据构造成一个大顶堆或小顶堆。在数组中,根节点通常是数组的第一个元素,父节点与其孩子节点之间通过索引计算可以方便地访问到彼此。从最后一个非叶子节点开始(也就是倒数第一个有孩子的节点),逐个调用下沉操作(heapify)确保每个子树都是一个合法的大顶堆。

2. **交换堆顶元素与末尾元素:**
   将堆顶元素(即当前未排序部分的最大元素或最小元素,取决于是否是大顶堆还是小顶堆)与数组的最后一个元素进行交换。这样,最大(或最小)元素会被放到正确的位置上。

3. **调整堆:**
   由于交换了堆顶元素,原来满足堆性质的结构被破坏,需要重新调整剩余元素以恢复堆的性质。因此,对新的堆顶元素执行下沉操作,使它下面的子树重新成为一个大顶堆。

4. **重复上述过程:**
   继续对剩下的元素(除已排好序的部分之外)构建堆并交换堆顶元素和下一个未排序元素的位置,直到所有元素都被排序完毕。

通过这样的方式,堆排序保证了每次都能将当前未排序序列中的最大(或最小)元素放在正确的位置上,最终完成整个数组的排序。堆排序的时间复杂度为O(n log n),并且是不稳定的排序算法,因为相同元素之间的相对顺序可能会在排序过程中改变。

以下是通过一个视频对整个过程进行的讲解:

堆排序图画讲解

import java.util.Arrays;

public class HeapSort {
    public static void heapify(int arr[], int n, int i) {
        int largest = i;  // 初始化最大值为根节点
        int left = 2 * i + 1;  // 左孩子结点的位置
        int right = 2 * i + 2;  // 右孩子结点的位置

        // 如果左孩子大于根节点
        if (left < n && arr[left] > arr[largest])
            largest = left;

        // 如果右孩子大于当前最大值
        if (right < n && arr[right] > arr[largest])
            largest = right;

        // 如果最大值不是根节点,交换它们,并对新的根节点递归调用heapify
        if (largest != i) {
            int swap = arr[i];
            arr[i] = arr[largest];
            arr[largest] = swap;

            // 对新的最大值进行调整
            heapify(arr, n, largest);
        }
    }

    // 堆排序函数
    public static void sort(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);
        }
    }

    // 测试堆排序方法
    public static void main(String args[]) {
        int arr[] = {12, 11, 13, 5, 6, 7};
        System.out.println("Before sorting: " + Arrays.toString(arr));

        sort(arr);

        System.out.println("After sorting: " + Arrays.toString(arr));
    }
}

以上代码首先定义了一个heapify方法用于构建和维护最大堆属性,然后在sort方法中先构建一个最大堆,再通过循环将堆顶元素(即当前未排序部分的最大元素)与末尾元素交换,最后递归地对剩余部分重建最大堆。整个过程完成之后,数组就被排序好了。

  • 33
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值