杂记:堆排序

堆排序

  堆排序是把一组无序数组,构建成一个二叉树形式的堆,有大顶堆和小顶堆两种。每一个根节点都比其子节点大的堆叫大顶堆,这样堆顶的元素就是最大值(对左右子节点的大小顺序无要求),反之则称为小顶堆。

  堆排序分为两步,第一步是根据要求构建一个大顶堆,或者小顶堆。第二步,(以大顶堆为例)将堆顶最大 值与堆中最后一位元素位置互换,之后将其取出。这样就得到了该数组的最大值,因为在这个过程中造成了对大顶堆的破坏,就需要对堆重新构建,成为一个大顶堆。之后再重复上述步骤,依次取出第二大、第三大、第四大、第五大、第六大........个元素,之后就得到了一个有序的数组。

  int[] arr = new int[] { 89,9,32,5,1,53,63,22,62,26,46,73,74,25 };// 测试数组
            heapSort(arr);
            System.out.println(Arrays.toString(arr));

        }

       public static void heapSort(int[] arr) {
            for (int i = arr.length - 1; i >= 0; i--) {//根据数组的长度,自下往上,从右到左构建一个大顶堆。
                heapBuild(arr, i, arr.length);//调用构建大顶堆的函数
            }
            for (int i = arr.length - 1; i >= 0; i--) {//
                int temp = arr[0];//将堆顶与堆尾的元素调换位置
                arr[0] = arr[i];
                arr[i] = temp;
                heapBuild(arr, 0, i);//调换一次位置后,大顶堆已经不是大顶堆,需要重新构建,但因为交换了堆顶与堆尾
            }                          //的值,这里的根节点可以从堆顶节点开始进行比较,重新构建大顶堆。
        }

        public static void heapBuild(int[] arr, int parent, int lenght) {
            int temp = arr[parent];//将父节点的数值存在temp中
            int Child = 2 * parent + 1;//大顶堆的规律,左节点与右节点的物理地址分别为:2 * parent + 1和2 * parent + 1+1;
            while (Child < lenght) {//循环条件是子树节点的物理位置小于数组长度。
                if (Child + 1 < lenght && arr[Child] < arr[Child + 1]) {//判断该父节点是否有右子树节点,并且左右节点的大小比较
                    Child++;
                }
                if (temp >= arr[Child]) {//注意!!!!!!!!!这里的child已经是右节点的物理地址、
                    break;
                }
                arr[parent] = arr[Child];//根节点小于子节点,将子节点数换到根节点位

                parent = Child;//将子节点位置换到根节点位
                Child = parent * 2 + 1;
            }
            arr[parent] = temp;//如果while循环发生实现,那么这里的arr[parent]=temp存储的性质已经改变为一个子节点。
        }
[1, 5, 9, 22, 25, 26, 32, 46, 53, 62, 63, 73, 74, 89]

Process finished with exit code 0

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值