zoukankan      html  css  js  c++  java
  • 堆排序Heapsort的Java和C代码

    Heapsort排序思路

    将整个数组看作一个二叉树heap, 下标0为堆顶层, 下标1, 2为次顶层, 然后每层就是"3,4,5,6", "7, 8, 9, 10, 11, 12, 13, 14", ..., 对于其中的每一个非叶子节点, 其子节点的下标为 2 * pos + 1 和 2 * pos + 2

    循环进行以下工作:

    1. 标记当前堆的右边界
    2. 将堆初始化为大顶堆
    3. 将堆顶置换到右边界, 同时将右边界左移一位(即将堆缩小一格)

    将堆初始化为大顶堆的处理

    1. 从最后一个非叶子节点开始, 其下标为  length / 2 - 1, length为当前的堆大小, 往前挨个处理
    2. 检查节点值, 对节点与其子节点的值大小i进行比较, 如果子节点值比当前节点大, 将最大值的那个子节点换上来
    3. 如果发生了交换, 那么要对发生交换的这个子节点位置也进行检查, 如果还有交换, 则继续往下查, 直到达到叶子节点
    public class DemoHeapSort {
        // 待排序的数组
        private int[] ints;
        // 当前堆的右边界(下标)
        private int limit;
    
        public DemoHeapSort(int ... ints) {
            this.ints = ints;
            this.limit = ints.length - 1;
        }
    
        public void sortAll() {
            while (limit > 0) {
                resort();
                swap(0, limit);
                limit--;
            }
        }
    
        public void resort() {
            // 起点pos为当前堆length / 2 - 1
            for (int i = (limit + 1) / 2 - 1; i >= 0; i--) {
                int pos = i;
                while (true) {
                    pos = check(pos);
                    if (pos == 0) {
                        break;
                    }
                }
            }
        }
    
        /**
         * 检查pos位置, 自上而下判断是否都满足大顶堆的要求
         * 其左右子节点的下标为 2*pos+1 和 2*pos+2
         *
         * @param pos 当前要检查的下标
         * @return 如果无调整, 则返回0, 如果有调整, 则返回被调整的子节点下标
         */
        private int check(int pos) {
            int posLeft = 2 * pos + 1;
            int posRight = 2 * pos + 2;
            if (posLeft > limit) { // 没有子节点
                return 0;
            }
            if (posRight > limit) { // 仅有左节点
                if (ints[pos] < ints[posLeft]) {
                    swap(pos, posLeft);
                    return posLeft;
                } else {
                    return 0;
                }
            }
            // 左右节点都有
            if (ints[posLeft] > ints[posRight]) {
                if (ints[pos] < ints[posLeft]) {
                    swap(pos, posLeft);
                    return posLeft;
                } else {
                    return 0;
                }
            } else {
                if (ints[pos] < ints[posRight]) {
                    swap(pos, posRight);
                    return posRight;
                } else {
                    return 0;
                }
            }
        }
    
        public void print() {
            for (int a : ints) {
                System.out.printf("%3d", a);
            }
            System.out.print("
    ");
        }
    
        private void swap(int a, int b) {
            int tmp = ints[a];
            ints[a] = ints[b];
            ints[b] = tmp;
        }
    
        public static void main(String[] args) {
            DemoHeapSort hs = new DemoHeapSort(10, 97, 9, 1,63, 64, 8, 17, 33, 7, 21, 0, 7, 75, 13, 18, 2, 99, 87);
            hs.sortAll();
            hs.print();
        }
    }
    

    C代码, 在原数组上排序

    void heap_sort(int *nums, int size) {
        for (int i = 0; i < size; i++) {
            int num = *(nums + i);
            printf("%d ", num);
        }
        printf("
    ");
        for (int i = 0; i < size; i++) {
            int length = size - i;
            for (int pos = length / 2 - 1; pos >= 0; pos-- ) {
                int p = pos;
                do {
                    p = check(nums + i, length - 1, p);
                } while (p != 0);
            }
            for (int j = 0; j < size; j++) {
                int num = *(nums + j);
                printf("%d ", num);
            }
            printf(" %d
    ", i);
        }
    }
    
    int check(int *nums, int limit, int pos) {
        int ls = pos * 2 + 1;
        int rs = pos * 2 + 2;
        if (ls > limit) {
            return 0;
        }
        int p = *(nums + pos);
        if (rs > limit) {
            int l = *(nums + ls);
            if (l > p) {
                swap(nums + ls, nums + pos);
                return ls;
            } else {
                return 0;
            }
        } else {
            int l = *(nums + ls);
            int r = *(nums + rs);
            if (l > r) {
                if (l > p) {
                    swap(nums + ls, nums + pos);
                    return ls;
                } else {
                    return 0;
                }
            } else {
                if (r > p) {
                    swap(nums + rs, nums + pos);
                    return rs;
                } else {
                    return 0;
                }
            }
        }
    }
    
    void swap(int *a, int *b) {
        int t = *a;
        *a = *b;
        *b = t;
    }
    
  • 相关阅读:
    [ jquery 选择器 :hidden ] 此方法选取匹配所有不可见元素,或者type为hidden的元素
    剑指 Offer 03. 数组中重复的数字 哈希
    LeetCode 1736. 替换隐藏数字得到的最晚时间 贪心
    Leetcode 1552. 两球之间的磁力 二分
    Leetcode 88. 合并两个有序数组 双指针
    LeetCode 1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
    LeetCode 1743. 相邻元素对还原数组 哈希
    LeetCode 1745. 回文串分割 IV dp
    剑指 Offer 47. 礼物的最大价值 dp
    剑指 Offer 33. 二叉搜索树的后序遍历序列 树的遍历
  • 原文地址:https://www.cnblogs.com/milton/p/10873246.html
Copyright © 2011-2022 走看看