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;
    }
    
  • 相关阅读:
    cf Round #764(Div. 3)
    查看w3wp.exe 进程
    CAML语法 Query写法
    InfoPaht 复选框
    性能工具MiniProfiler在Asp.Net WebForm跟踪EntityFramework
    CAML基础语法
    Moss 本机无法访问(转)
    STSADM 不是内部或外部命令
    spBodyOnLoadFunctionNames
    关于代码调用SSP获取UserProfile出错的解决方案(转)
  • 原文地址:https://www.cnblogs.com/milton/p/10873246.html
Copyright © 2011-2022 走看看