美文网首页
堆排序(Java)

堆排序(Java)

作者: aruba | 来源:发表于2021-08-18 10:56 被阅读0次

堆排序:堆排序的思想比较难理解,首先将数据看成是一个二叉树,对数据进行二叉树的建立(建堆),这个过程也是排序的过程,将最小或最大的值排到根节点上,如果采用最大值,则称为最大堆,反之,称为最小堆
例如:有一个数组为[8,1,4,2,3],将他变为二叉树为:

        8
    1     4
2    3

要对它进行排序,可以从8开始,和他的左孩子和右孩子比较,将小的那个和本身进行替换,第一次替换变为:

        1
    8     4
2    3

再以替换的节点作为父节点,和他的左孩子和右孩子比较,将小的和本身那个交换

        1
    2     4
8    3

另外我们观察索引发现,当前节点索引 * 2 + 1即为左孩子的索引,当前节点索引 * 2 + 2即为右孩子索引
实现代码:

    /**
     * 建堆
     *
     * @param nums
     * @param size
     * @param index
     */
    private void createHeap(int[] nums, int size, int index) {
        //数组索引:0 1 2 3 4 5 6
        //0的左孩子索引是1 ,0的右孩子索引是2
        //1的左孩子索引是3,右孩子是4
        //2的左孩子索引是5,右孩子是6
        //得出:
        int leftIndex = 2 * index + 1;//左孩子索引
        int rightIndex = leftIndex + 1;//右孩子索引

        //将当前节点、左孩子、右孩子的值进行比较,较小的值和当前节点替换
        if (leftIndex >= size && rightIndex >= size) {//没有孩子,不用处理了
            return;
        }

        int currentValue = nums[index];
        int leftValue = leftIndex < size ? nums[leftIndex] : Integer.MAX_VALUE;//可能没有(代码走到这,左孩子其实不可能没有)
        int rightValue = rightIndex < size ? nums[rightIndex] : Integer.MAX_VALUE;//可能没有

        if (currentValue <= leftValue && currentValue <= rightValue) {//当前节点已经小了,不用处理
            return;
        }

        if (leftValue < rightValue) {//左孩子替换当前节点
            nums[index] = leftValue;
            nums[leftIndex] = currentValue;
            createHeap(nums, size, leftIndex);
        } else {//右孩子替换当前节点
            nums[index] = rightValue;
            nums[rightIndex] = currentValue;
            createHeap(nums, size, rightIndex);
        }
    }

但是我们发现自上而下建立二叉树,是不可行的
比如:数组为:[8,2,4,1,3]
二叉树为:

        8
    2     4
3    1

那么调用我们代码后形成的树为:

        2
    1     4
3    8

最小值1,并没有到达根节点,这时转变思路,不用从根节点开始建立,而是从树的底部开始建立堆,过程为:
先将1,2,3进行排序

        8
    1     4
3    2

然后1,4,8进行排序

        1
    8     4
3    2

思想就是从最深度- 1的深度的倒数第一个节点开始倒着建堆,以上面的数据就是从4开始,由于是完全二叉树,所以索引为:(数组大小 - 1) / 2
实现代码:

    /**
     * 自下而上建堆
     *
     * @param nums
     */
    public void buildHeap(int[] nums) {
        for (int i = (nums.length - 1) / 2; i >= 0; i--) {
            createHeap(nums, nums.length, i);
        }

        //取出最小的
        int n = nums.length;
        while (n > 0) {
            System.out.print(nums[0] + " ");
            nums[0] = nums[n - 1];
            n--;
            createHeap(nums, n, 0);
        }
    }

测试代码:

        int[] nums = new int[]{5, 7, 1, 3, 9, 0, 1, 6, 8, 4};
        buildHeap(nums);

结果:
0 1 1 3 4 5 6 7 8 9
堆排序本身用来排序性能并不高,但是作为查找的时候性能很高,由于二分查找只针对已经排好序的顺序表,对于大数据量的散列表,推排序就可以出场了,因为推排序的建堆过程,尽可能少的访问节点,减少了对一个节点的重复访问,而又具有二分的思想,相比于其他排序,查找性能非常高

相关文章

  • 堆排序(非递归版)

    时间复杂度是O(nlogN) 但是不常用堆排序,因为堆排序不稳定 Java实现

  • 排序

    八大排序算法 一、归并排序 递归及非递归的JAVA实现 二、快速排序 快排算法JAVA实现 三、堆排序 堆排序堆排...

  • 排序算法-堆排序

    参考: Java排序算法(五):堆排序 【算法与数据结构】图说堆排序 【数据结构】排序算法:希尔、归并、快速、堆排...

  • java堆排序

    什么是堆排序:图解堆排序堆排序:利用了堆这种数据结构堆数据结构:特殊的完全二叉树,因为具有以下的特点:1)每个结点...

  • 堆排序(java)

    将待排序序列构造成一个大顶堆,此时序列的最大值就是堆顶元素,将它和数组的末尾元素交换,再将剩余的n-1个元素构造成...

  • 堆排序(Java)

    堆排序:堆排序的思想比较难理解,首先将数据看成是一个二叉树,对数据进行二叉树的建立(建堆),这个过程也是排序的过程...

  • 堆排序

    一、堆排序 堆排序是我们所掌握的重要的排序算法之一,理解并使用,可以让我们对它的了解更加深刻: 话不多说上代码 java

  • 堆排序java实现

    //堆排序://基本思想://首先要了解堆这种数据结构://堆是实质上是一个满足如下条件的完全二叉树:树中任意非叶...

  • 堆排序java代码

    public class HeapSort { }

  • 堆排序(Java版)

    堆排序的原理是先构造一个大顶堆,每次弹出堆中一个最大元素填充到数组倒数第N的位置(逆序),即可将数组由小到大进行排...

网友评论

      本文标题:堆排序(Java)

      本文链接:https://www.haomeiwen.com/subject/khzbbltx.html