堆排序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. 如果发生了交换, 那么要对发生交换的这个子节点位置也进行检查, 如果还有交换, 则继续往下查, 直到达到叶子节点

将堆初始化为大顶堆后, 堆顶即为最大元素, 将堆顶交换到右边界

之后因为除了堆顶都满足大顶堆的条件, 所以只需要从堆顶进行判断和交换就可以将堆恢复为大顶堆.

Java代码

public class HeapSort {

    public static <T> void sort(T[] array, Comparator<? super T> comparator) {
        for (int i = array.length / 2 - 1; i >= 0; i--) {
            int pos = i;
            while ((pos = heapify(array, comparator, pos, array.length - 1)) != 0);
        }
        for (int i = array.length - 1; i > 0; i--) {
            swap(array, 0, i);
            int pos = 0;
            while ((pos = heapify(array, comparator, pos, i - 1)) != 0);
        }
    }

    /**
     * 检查pos位置, 自上而下判断是否都满足大顶堆的要求
     * 其左右子节点的下标为 2*pos+1 和 2*pos+2
     *
     * @param pos 当前要检查的下标
     * @return 如果无调整, 则返回0, 如果有调整, 则返回被调整的子节点下标
     */
    private static <T> int heapify(T[] array, Comparator<? super T> comparator, int pos, int limit) {
        int left = 2 * pos + 1;
        int right = 2 * pos + 2;
        int largest = pos;
        if (left <= limit && comparator.compare(array[largest], array[left]) < 0) {
            largest = left;
        }
        if (right <= limit && comparator.compare(array[largest], array[right]) < 0) {
            largest = right;
        }
        if (largest != pos) {
            swap(array, pos, largest);
            return largest;
        }
        return 0;
    }

    private static <T> void swap(T[] array, int a, int b) {
        T tmp = array[a];
        array[a] = array[b];
        array[b] = tmp;
    }

    public static void main(String args[])
    {
        int size = 200000;
        int rounds = 5;
        Integer[] test2 = new Integer[size];
        long total = 0;
        for (int round = 0; round < rounds; round++) {
            for (int i = 0; i < size; i++) {
                test2[i] = (int)(Math.random()*10000);
            }
            long start = System.currentTimeMillis();
            HeapSort.sort(test2, (Integer o1, Integer o2) -> (o1 - o2));
            long elapse = System.currentTimeMillis() - start;
            total += elapse;
//            for (int i : test2) {
//                System.out.println(i);
//            }
            System.out.println("Elapsed: " + elapse + "ms");
        }
        System.out.println("Average: " + total / rounds + "ms");
    }
}

  

 C代码, 在原数组上排序

void heap_sort(int *nums, int size) {
    for (int i = 0; i < size; i++) {
        int num = *(nums + i);
        printf("%d ", num);
    }
    printf("\n");
    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\n", 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;
}

 

posted on 2019-05-16 01:58  Milton  阅读(181)  评论(0编辑  收藏  举报

导航