堆排序(java实现)

堆排序

  • 什么是堆结构?

    • 堆结构是一种树结构,准确说是一种完全二叉树结构。树中的每一个结点对应着原始数据的一个记录,每个结点应满足:
    • 大顶堆:从小到大排列,要求非叶结点的数据要大于等于其左右结点的数据
    • 小顶堆:从大到小排列,要求非叶结点的数据要小于等于其左右结点的数据
    • 由此可知,如果按照从小到大输出数据时,堆结构的根节点为要求的最大值。
  • 如何进行堆排序?

    • 步骤:构造堆结构+堆排序输出

    -1. 构造堆结构

    • 将所有的无序数据放到完全二叉树的各个节点中,然后将其构造成堆结构,即非叶节点的值大于其左右结点的值。根节点的值为最大。

    -2. 堆排序输出

    • 将根节点和末尾元素进行交换,此时末尾元素为最大值。最后将剩余的n-1个元素重复执行这个过程,即先将剩余的n-1个元素构造成一个堆,再与末尾元素交换,得到n个元素的次小值并输出,以此类推得到最终结果。

- 堆排序举例:

  • 假设有n个需要排序的数据序列,使用堆排序将他们按照从小到大的顺序进行排序。

    - 分析:

    • 1.构造初始堆:将无序的序列构造为一个大顶堆(一般升序使用大顶堆,降序使用小顶堆)
    • 2.将堆顶元素和末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与当前堆的末尾元素进行交换得到第二大元素,如此循环往复,最终得到结果

实现:

package com.linchong.sorttest;

public class HeapDemo {

    static final int SIZE = 10;

    static void HeapSort(int[] arr, int n) {
        int i, j, k;
        //1.构造大顶堆
        for (i = n / 2 - 1; i >= 0; i--) {

            while (2 * i + 1 < n) { // 第i个结点有左子树
                j = 2 * i + 1;
                if (j + 1 < n) { // 第i个结点有右子树
                    if (arr[j] < arr[j + 1])
                        j++;
                }
                if (arr[i] < arr[j]) {
                    swap(arr, i, j);
                    i = j; // 改变,堆被破坏,重新调整
                } else {
                    break;
                }
            }
        }

        // 2.堆排序输出,重新调整堆结构
        for (i = n - 1; i > 0; i--) {
            swap(arr, i, 0);
            k = 0;
            while (2 * k + 1 < i) { // 调整堆结构
                j = 2 * k + 1;
                if (j + 1 < i) { // 有右子树
                    if (arr[j + 1] > arr[j])
                        j++;
                }

                if (arr[k] < arr[j]) {
                    swap(arr, k, j);
                    k = j; // 堆结构改变,重新调整堆结构
                } else {
                    break;
                }

            }
        }

    }

    static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

    public static void main(String[] args) {
        int[] array = new int[SIZE];
        int i;
        for (i = 0; i < SIZE; i++) {
            array[i] = (int) (100 + Math.random() * (100 + 1));
        }
        System.out.println("排序前的数组为:");
        for (int j : array) {
            System.out.print(j + " ");
        }
        System.out.printf("\n");
        HeapSort(array, SIZE);
        System.out.println("排序后的数组为:");
        for (int k : array) {
            System.out.print(k + " ");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罚站的孩子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值