Java 排序算法:堆排序

有关堆排序的概念等基本内容请参考以下链接:1.7 堆排序 | 菜鸟教程堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法: 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列; 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列; 堆排序的平均时间复杂度为 Ο(nlogn)。..https://www.runoob.com/w3cnote/heap-sort.html


思路步骤:

1. 建立二叉树结构:

    获取需要排序的数组长度,判断要装满所有元素,需要几层(设层数为 n)。

    判断条件:2 ^ n - 1 > length;

2. 从下至上,从右至左遍历“二叉树”:

    层数减一:n - 1,以去除叶子结点层

    从该层最后结点(i = Array[(2 ^ n - 1) - 1])开始,判断是否存在子结点:right =  2 * i + 2;

                                                                                                                       left = 2 * i + 1;

    判断条件:right < length      left < length

3. 判断父子结点的大小:

    此处以大根堆(大顶堆)为例,若子结点大于父结点,交换二者

    判断条件:Array[right] > Array[i]     Array[left] > Array[i]

    此步可与上一步合成判断,即:right < length && Array[right] > Array[i]   

                                                      left < length && Array[left] > Array[i]

4. 结点左移:i--,重复 2 ,3 步,终止条件:i < 0

5. 将数组开始与末尾的元素互换,将最大值送去数组尾,剔除数组尾元素,即让其脱离循环:length--

6. 重复 2 ,3 ,4 步,终止条件:length < 0


Java代码如下:

//堆排序
public class heap_sort {
    public static void main(String[] args) {
        int[] arr = new int[] { 1, 2, 4, 3, 0, -1, -5, 3, 4 };//测试数组

        int len = arr.length;// 结点个数
        int n = 0;// 二叉树层数
        int points;// 记录满二叉树结点数
        
        //找到叶子结点上一层
        while (true) {
            points = (int) Math.pow(2, n) - 1;
            if (points > len) {
                n--;// 去除不满的层
                break;
            }
            n++;
        }
        // System.out.println(n);
        points = (int) Math.pow(2, n) - 1;
        while (len > 0) {
            for (int i = points - 1; i >= 0; i--) {
                // System.out.print(arr[i]);
                int left = 2 * i + 1;
                int right = 2 * i + 2;
                //判断有无子树,若有,先判断右结点,再判断左结点
                if (right < len && arr[right] > arr[i]) {
                    int temp = arr[i];
                    arr[i] = arr[right];
                    arr[right] = temp;
                }
                if (left < len && arr[left] > arr[i]) {
                    int temp = arr[i];
                    arr[i] = arr[left];
                    arr[left] = temp;
                }
            }
            System.out.println(Arrays.toString(arr));
            int temp = arr[0];
            arr[0] = arr[len - 1];
            arr[len - 1] = temp;// 将最大值换到数组末尾
            System.out.println(Arrays.toString(arr));
            len--;
        }
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值