树形选择排序

树形选择排序一个很重的条件就是:所排序的数组个数必须是2的次幂,这样才能满足完全二叉树的形态,如果不是2的次幂,则用无穷大值去填充,使其个数称为2的次幂。

代码如下:

  /**
     * 树形选择排序。
     * 注意:datas的长度必须满足2的k次幂。
     *
     * @param datas 待排序数据
     */
    public static void treeSelectionSort(int[] datas) {
        int length = datas.length; // 待排序的数组长度,length一定要是2的幂次方,如果不是则扩大到2的幂次方

        if (!((length & (length - 1)) == 0)) {// 判断length是否是2的幂次方
            int minPower = minPower(length);
            length = (int) Math.pow(2, minPower + 1);
        }
        int treeSize = length * 2 - 1; // 树的存储大小
        int[] tree = new int[treeSize]; // 树的存储空间

        // 由后向前将待排序数据存储在树中(叶子节点)
        for (int i = length - 1, j = treeSize - 1; i >= 0; i--, j--) {
            if (i > datas.length - 1) {
                tree[j] = MAX;
            } else {
                tree[j] = datas[i];
            }
        }
        // 填充非叶子节点
        for (int i = treeSize - 1 - length; i >= 0; i--) {
            tree[i] = Integer.min(tree[2 * i + 1], tree[2 * i + 2]);
        }
        PrintUtil.printIntArray(tree);


        // 排序
        int i = 0;
        while (i < datas.length) {
            int minValue = tree[0];
            datas[i] = minValue; // 最小值

            // 将树中次最小值替换为无穷大值
            int minIndex = 0;// 最小值下标
            while (true) {
                int a = (minIndex + 1) * 2 - 1;
                int b = (minIndex + 1) * 2;
                if (a > tree.length - 1 || b > tree.length - 1) {
                    break;
                }
                int v1 = tree[a];
                int v2 = tree[b];
                // 将最小值的结点置为无穷大
                minIndex = Math.min(v1, v2) == v1 ? a : b;
                tree[minIndex] = MAX;
            }

            // 重新选择生成胜利树,找出最小值
            while (minIndex > 0) {
                if (minIndex % 2 == 0) {
                    tree[minIndex / 2 - 1] = Math.min(tree[minIndex], tree[minIndex - 1]);
                    minIndex = minIndex / 2 - 1;
                } else {
                    tree[minIndex / 2] = Math.min(tree[minIndex], tree[minIndex + 1]);
                    minIndex = minIndex / 2;
                }
            }
            i++;
        }
    }

    /**
     * 求number的2的对数
     */
    private static int minPower(int number) {
        for (int i = 1; i < Integer.MAX_VALUE; i++) {
            if (Math.pow(2, i) < 10 && Math.pow(2, i + 1) > 10) {
                return i;
            }
        }
        return -1;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值