• heapsort


    heap-sort
    基本操作a, push_heap,将新元素加入heap中。做法是先将元素加至序列最后,然后逐渐向上交换,直到到达合适位置,即所谓sift-up操作。
    基本操作b, pop_heap,从堆中删除根元素。做法是先将根元素交换至最后(待删除位置),然后调整新的根到合适位置,即所谓sift-down操作。
    基本操作c,make_heap,调整一个随机序列使其满足堆结构。
    以上三个基本操作STL中就有提供,用这三个基本操作,可以直接搞出heap-sort了。实际上,heap-sort只需要make_heap和pop_heap即可。push_heap在实现类似priority_queue的时候会有用。
    用STL的make_heap与pop_heap来实现heap-sort:

    View Code
     1 #include <cstdio>
    2 #include <algorithm>
    3
    4 #define MAX_N 20
    5 int arr[MAX_N];
    6
    7 void print_arr(void)
    8 {
    9 int i;
    10 for (i = 0; i < MAX_N; i++)
    11 std::printf("%d ", arr[i]);
    12 std::printf("\n");
    13 }
    14
    15 int main(int argc, char *argv[])
    16 {
    17 int i;
    18 for (i = 0; i < MAX_N; i++)
    19 arr[i] = i;
    20 //print_arr();
    21 std::random_shuffle(arr, arr + MAX_N);
    22 //print_arr();
    23 std::make_heap(arr, arr + MAX_N);
    24 //print_arr();
    25 for (i = MAX_N; i > 0; i--) {
    26 std::pop_heap(arr, arr + i);
    27 }
    28 //print_arr();
    29
    30 return 0;
    31 }

    make_heap的实现:即构建满足heap结构的隐式二叉树。可以自顶向下建立,这是一个从左向右循环调用push_heap的过程。复杂度更低的是自底而上建立,这是因为后一半节点都是叶子节点,只需从后向前,每次加入一个根节点并调节位置即可(sift-down)。

    sift_down的实现:略。

    heap_sort的实现:与上面的STL版类似。

    放到一起,heap_sort的实现:

    View Code
     1 #include <string.h> /* memcpy */
    2 #include <stdlib.h> /* ssize_t */
    3
    4 #define SWAP_ELEM(pl, pr, size) do {\
    5 char temp[size]; /* C99 */ \
    6 memcpy(temp, pl, size); \
    7 memcpy(pl, pr, size); \
    8 memcpy(pr, temp, size); \
    9 } while (0)
    10
    11 // find the appropriate place for the specified node and put it there.
    12 static void sift_down(char *base, size_t nmemb, size_t curr_idx, size_t size,
    13 int(*compare_func)(const void *, const void *))
    14 {
    15 if (nmemb <= 1)
    16 return;
    17
    18 while (curr_idx < nmemb) { // sift-down arr[curr_idx].
    19 char *curr = base + curr_idx * size;
    20 char *max = curr;
    21 size_t max_idx = curr_idx;
    22 // find the greatest of (curr, left(curr), right(curr))
    23 size_t left_idx = curr_idx * 2 + 1;
    24 char *pl = base + left_idx * size;
    25 if ((left_idx < nmemb) && (compare_func(pl, max) > 0)) { // *pl is greater than *max.
    26 max = pl;
    27 max_idx = left_idx;
    28 }
    29 size_t right_idx = curr_idx * 2 + 2;
    30 char *pr = base + right_idx * size;
    31 if ((right_idx < nmemb) && (compare_func(pr, max) > 0)) { // *pr is greater than *max.
    32 max = pr;
    33 max_idx = right_idx;
    34 }
    35 if (max_idx == curr_idx) {
    36 break;
    37 } else { // turn into left or right subtree.
    38 SWAP_ELEM(curr, max, size);
    39 curr_idx = max_idx;
    40 }
    41 }
    42 }
    43
    44 static void my_make_heap(char *base, size_t nmemb, size_t size,
    45 int(*compare_func)(const void *, const void *))
    46 {
    47 if (nmemb <= 1)
    48 return;
    49
    50 ssize_t i = nmemb / 2 - 1; // size_t will fail due to its unsigned-ness.
    51 for (; i >= 0; i--) { // build the heap bottom-up
    52 sift_down(base, nmemb, i, size, compare_func);
    53 }
    54 }
    55
    56 /* Implementation of heap-sort, following a libc-qsort-like interface. */
    57 void my_heapsort(void *base, size_t nmemb, size_t size,
    58 int(*compare_func)(const void *, const void *))
    59 {
    60 char *pbase = base;
    61
    62 my_make_heap(pbase, nmemb, size, compare_func);
    63
    64 size_t curr_last_idx = nmemb - 1;
    65 while (curr_last_idx > 0) {
    66 char *curr_last = pbase + curr_last_idx * size;
    67 SWAP_ELEM(pbase, curr_last, size);
    68 --curr_last_idx;
    69 // sift the new root node to its place.
    70 sift_down(pbase, curr_last_idx + 1, 0, size, compare_func);
    71 }
    72 }
    73
    74 #undef SWAP_ELEM

    heap_sort的测试代码:

    View Code
      1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <time.h>
    4
    5 extern void my_heapsort(void *base, size_t nmemb, size_t size,
    6 int(*compare_func)(const void *, const void *));
    7
    8 #define MAX_N 27
    9 int arr[MAX_N];
    10
    11 void print_arr(void)
    12 {
    13 int i;
    14
    15 for (i = 0; i < MAX_N; i++)
    16 printf("%d ", arr[i]);
    17 printf("\n");
    18 }
    19
    20 /* A simplified version of the STL algorithm random_shuffle */
    21 void my_random_shuffle(int *arr, int n)
    22 {
    23 int i;
    24
    25 srand(time(0));
    26 for (i = 1; i < n; i++) {
    27 int selected_index = rand() % (i + 1); // OK, forgive my using rand(),
    28 //which is of limited random digits.
    29 int temp = arr[selected_index]; // swap to current position.
    30 arr[selected_index] = arr[i];
    31 arr[i] = temp;
    32 }
    33 /* equivalent to:
    34 for (i = n - 1; i > 0; i--) {
    35 int selected_index = rand() % (i + 1); // select a random element.
    36 int temp = arr[selected_index]; // swap to current position.
    37 arr[selected_index] = arr[i];
    38 arr[i] = temp;
    39 }
    40 */
    41 }
    42
    43 int comp(const void *lhs, const void *rhs)
    44 {
    45 return *(int *)lhs - *(int *)rhs;
    46 }
    47
    48 int main(int argc, char *argv[])
    49 {
    50 int i;
    51
    52 setbuf(stdout, NULL);
    53
    54 for (i = 0; i < MAX_N; i++)
    55 arr[i] = MAX_N - 1 - i;
    56 // case #1, sequence of 1 element
    57 printf("case #1: \n");
    58 my_heapsort(arr, 1, sizeof(arr[0]), comp);
    59 print_arr();
    60 // case #2, sequence of 2 elements
    61 printf("case #2: \n");
    62 my_heapsort(arr, 2, sizeof(arr[0]), comp);
    63 print_arr();
    64 // case #3, sequence of 3 elements
    65 printf("case #3: \n");
    66 my_heapsort(arr, 3, sizeof(arr[0]), comp);
    67 print_arr();
    68
    69 // case #4, all 0's
    70 printf("case #4: \n");
    71 for (i = 0; i < MAX_N; i++)
    72 arr[i] = 0;
    73 my_heapsort(arr, MAX_N, sizeof(arr[0]), comp);
    74 print_arr();
    75
    76 // case #5, ascent sequence.
    77 printf("case #5: \n");
    78 for (i = 0; i < MAX_N; i++)
    79 arr[i] = i;
    80 my_heapsort(arr, MAX_N, sizeof(arr[0]), comp);
    81 print_arr();
    82
    83 // case #6, descent sequence.
    84 printf("case #6: \n");
    85 for (i = 0; i < MAX_N; i++)
    86 arr[i] = MAX_N - 1 - i;
    87 my_heapsort(arr, MAX_N, sizeof(arr[0]), comp);
    88 print_arr();
    89
    90 // case #7, random permutated sequence.
    91 printf("case #7: \n");
    92 for (i = 0; i < MAX_N; i++)
    93 arr[i] = i;
    94 my_random_shuffle(arr, MAX_N);
    95 print_arr();
    96 //qsort(arr, MAX_N, sizeof(arr[0]), comp);
    97 //print_arr();
    98 my_heapsort(arr, MAX_N, sizeof(arr[0]), comp);
    99 print_arr();
    100
    101 return 0;
    102 }
  • 相关阅读:
    jQuery EasyUI介绍
    CodeMirror:基于JavaScript的代码编辑器
    概述:分布式文件系统+分布式存储+分布式处理
    HTML学习笔记——标准网页设计+使用CSS、Javascript
    HTML学习笔记——常用元素及其属性(二)
    HTML学习笔记——常用元素及其属性(一)
    Remmarguts' Date(k短路问题)
    K短路问题模板(spfa+A*)
    树状数组求逆序对模板
    桐桐的糖果计划(tarjan求桥+双连通分量)
  • 原文地址:https://www.cnblogs.com/qsort/p/2160213.html
Copyright © 2020-2023  润新知