排序---堆排序

堆排序

  • 堆排序思想

  • Java代码

  • 总结

堆排序思想

思想:(堆排序的思想比较简单,但是涉及到的知识点比较多,所以实现起来还是不容易的,以从小到大排序为例)
1.将待排序数组初始化为大顶堆
2.将大顶堆根元素和最后一个节点交换
3.将除最后一个元素外的其他元素继续调整为大顶堆
4.重复2、3操作直到没有元素可以调整为止
因为每一次都将当前最大元素根元素与最后一个元素交换调整到最后,所以此时数组已经按照从小到大的顺序排列好了

Java代码

package cn.com.mp.sort;

public class HeapSortDemo {

    public static void main(String[] args) {
        // int[] array={56,2,8,5,9,46,53,7,1};
        int[] array = { 12, 56, 8, 6, 50, 45, 2, 13, 89, 21 };
        int len = array.length;
        sort(array, len);
        /* 遍历排序后的数组,输出结果 */
        for (int i = 0; i < len; i++) {
            System.out.print(array[i] + " ");
        }
    }

    /* 堆排序 */
    public static void sort(int[] array, int len) {
        /* 建立初始堆 */
        buildHeap(array);
        for (int i = len - 1; i >= 0; i--) {
            /* 交换调整好的大顶堆根元素与最后一个元素 */
            swap(array, 0, i);
            /* 每一次交换完毕,将除最后一个节点的元素外的其他元素继续调整为大顶堆 */
            adjustHeap(array, 0, i);
        }
    }

    /* 建立初始堆 */
    public static void buildHeap(int[] array) {
        int len = array.length;
        /* 从最后一个非非叶子节点开始,从下往上从右往左,调整成大顶堆 */
        for (int i = len / 2; i >= 0; i--) {
            /* 调整交换处理堆 */
            adjustHeap(array, i, len);
        }
    }

    /* 调整交换处理堆 */
    public static void adjustHeap(int[] array, int parent, int len) {
        /*
         * 定义左右子树的下标,因为数组、堆都从0下标开始,所以左右子树定义如下
         */
        int left = 2 * parent + 1;
        int right = 2 * parent + 2;
        /* 默认定义父节点、左右子树三者中最大值为parent下标 */
        int max = parent;
        /* 比较父节点、左右子树,将最大值的下标赋值给max */
        if (left < len && array[left] > array[max]) {
            max = left;
        }
        if (right < len && array[right] > array[max]) {
            max = right;
        }
        /* 判断max==parent,若不是证明parent下标对应的值并不是三者中的最大值,则将其与最大值交换 */
        if (max != parent) {
            swap(array, max, parent);
            /* 递归调用调整刚刚换下来的"父节点"到合适的位置,因为其很有可能会破坏以它为根的子树的堆的性质 */
            adjustHeap(array, max, len);
        }
    }

    /* 交换 */
    public static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

运行结果:
这里写图片描述

总结:

1.堆排序本身的思想还是比较简单,但是要完成一次堆排序,涉及到的知识点很多,这也影响最终堆排序程序并不好编写

(由于时间关系,笔者此处只做简单解释,详细解释有时间再完善)
主要涉及到的知识点有:

  • 首先涉及到堆,那么什么是堆呢?
  • 堆简单的理解就是具有堆性质的完全二叉树
  • 此处又涉及到两个知识点,什么是堆性质?什么是完全二叉树?
  • 堆性质简单的理解如下:
    这里写图片描述
    如上图所示,满足第一行性质,称为小顶堆;满足第二行性质,称为大顶堆,
    完全二叉树简单的理解:假设此二叉树有n层,那么完全二叉树由前n-1层满二叉树和第n层最后一个元素可以是左子树即可以没有右子树组成。
  • 此处又涉及到一个知识点,什么是满二叉树?
    满二叉树简单的理解就是除最后一层节点外,其余的节点都有左右两颗子树。
    满二叉树
    完全二叉树
    2.时间复杂度:
    平均时间复杂度为:O(NlogN)
    最坏时间复杂度为:O(NlogN)
    3.稳定性
    不稳定排序
    排序过程图解,后续补充,欢迎批评指正
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值