排序——选择排序之堆排序

堆排序(HeapSort)是利用完全二叉树特性的一种选择排序。

定义如下:

设n个元素的数据序列{K0,k1,k2,...,kn-1},当且仅当满足下列关系时,称为最小/大堆。Ki<=K2i+1且Ki<=K2i+2或Ki>=K2i+2,i=0,1,2,...,[n/2-1]换言之,将{{K0,K1,...,Kn-1}}序列看成是一棵完全二叉树的层次遍历序列,如果任意一个结点元素<=/>=其孩子结点元素,则称该序列为最小/大堆,根结点值最小/大。

堆排序简单说来就是:将一个数据序列建成最小/大堆,则根结点值最小/大。

代码实现如下:


package g;

public class HeapSort {
    public static int[] randomInt(int n, int size) {
        int[] value = new int[n];
        for (int i = 0; i < value.length; i++) {
            value[i] = (int) (Math.random() * size);
        }
        return value;
    }

    public static void print(int[] keys) {
        for (int i : keys) {
            System.out.print(i + " ");            
        }
        System.out.println();
    }

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

    // 将keys数组中以parent为根的子树调整成最小/大堆,子序列范围为parent~end
    // 私有方法,只被堆排序方法调用,确保parent、end在范围内
    public static void sift(int[] keys, int parent, int end, boolean minheap) {
        System.out.print("sift   " + parent + ".." +end+ "\t");
        // child是parent的左孩子,因为根据二叉树性质5,完全二叉树中的第i(0<=i<n)个结点,如果有孩子
        // 则左孩子为第2i+1个结点,右孩子为第2i+2个结点
        int child = 2 * parent + 1;
        int value = keys[parent];
        // 沿较小/大值孩子结点向下筛选
        while (child <= end) {
            if (child < end && (minheap ? keys[child] > keys[child + 1] : keys[child] < keys[child + 1])) {
                // child记住孩子值较小/大者
                child++;
            }
            // 若父母结点值较小/大
            if (minheap ? value > keys[child] : value < keys[child]) {
                // 将较小/大孩子结点值上移
                keys[parent] = keys[child];
                // parent、child两者都向下一层
                parent = child;
                child = 2 * parent + 1;
            } else {
                break;
            }

        }
        // 当前子树的原根值调整后的位置
        keys[parent] = value;
        print(keys);
    }

    // 堆排序(降序),最小堆
    public static void heapSort(int[] keys) {
        heapSort(keys, true);
    }

    // 堆排序,当minheap为true时,创建最小堆,降序排序;否则创建最大堆,升序排序
    public static void heapSort(int[] keys, boolean minheap) {
        // 创建最小/大堆,根结点值最小/大
        for (int i = keys.length / 2 - 1; i >= 0; i--) {
            sift(keys, i, keys.length - 1, minheap);
        }
        // 每趟将最小/大值交换到后面,再调整成最小/大堆
        for (int i = keys.length - 1; i > 0; i--) {
            // 交换keys[0]与keys[i]
            swap(keys, 0, i);
            sift(keys, 0, i - 1, minheap);
        }
    }
      public static void main(String[] args){
          int[] values=HeapSort.randomInt(10, 100);
          System.out.print("关键字序列:");
          HeapSort.print(values);
          HeapSort.heapSort(values);
      }
}

输出如下:

关键字序列:64 57 29 75 8 53 98 78 78 53
sift   4..9    64 57 29 75 8 53 98 78 78 53
sift   3..9    64 57 29 75 8 53 98 78 78 53
sift   2..9    64 57 29 75 8 53 98 78 78 53
sift   1..9    64 8 29 75 53 53 98 78 78 57
sift   0..9    8 53 29 75 57 53 98 78 78 64
sift   0..8    29 53 53 75 57 64 98 78 78 8
sift   0..7    53 57 53 75 78 64 98 78 29 8
sift   0..6    53 57 64 75 78 78 98 53 29 8
sift   0..5    57 75 64 98 78 78 53 53 29 8
sift   0..4    64 75 78 98 78 57 53 53 29 8
sift   0..3    75 78 78 98 64 57 53 53 29 8
sift   0..2    78 98 78 75 64 57 53 53 29 8
sift   0..1    78 98 78 75 64 57 53 53 29 8
sift   0..0    98 78 78 75 64 57 53 53 29 8



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
堆中,如果要进行增序排序,则需要使用小顶堆进行排序。引用中提到,堆排序是利用堆进行排序的方法,如果我们想要得到一个递增的有序序列,就需要使用小顶堆。小顶堆的基本思想和大顶堆相反,它将待排序的序列构造成一个小顶堆,此时整个序列的最小值就是堆顶的根节点。将它移走(将其与堆数组的末尾元素交换),然后将剩余的 n - 1 个序列重新构造成一个小顶堆,这样就会得到 n 个元素的次最小值。如此反复执行,便能得到一个递增的有序序列。因此,如果要进行增序排序,就需要使用小顶堆来实现堆排序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [十大经典排序算法详解(三)-堆排序,计数排序,桶排序,基数排序](https://blog.csdn.net/lovely__RR/article/details/112867458)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [堆排序——详细教学](https://blog.csdn.net/qq_51294669/article/details/122770054)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值