• 排序算法之 Heap Sort


    Heap Sort (cpp_heap_sort.cc)
    ================================================================================
    最好时间复杂度  O(nlogn)
    平均时间复杂度  O(nlogn)
    最坏时间复杂度  O(nlogn)
    空间复杂度    O(1)
    是否稳定     否

      Heap Sort利用的是二叉堆结构能在O(logn)时间内取出最大元素的特点,将所有元素构建成堆后依次取出完成排序。
      经典的取出最大元素的算法是将最后一个元素放到根的位置然后向下调整,由于调整后的位置理论上还是接近堆底,所以这种方法的复杂度接近O(2logn),在测试中我使用了一个改进算法,首先向上调整填充空出的根位置,在堆底留出空位,再将最后一个元素放入空位向上调整。这个改进算法减少了复杂度因子,在很大程度上提高了算法效率。
      Heap Sort是高级排序算法中能保证O(nlogn)时间界的和O(1)空间界的少数算法之一(还有两个是Inplace Merge Sort和堆排序的改进版Smooth Sort),在理论上是一个相当完美的算法。但由于堆排序所需比较次数较多,而且在比较、交换元素的时候也是大范围跳跃的,所以速度并不是很快。 

     1 #include <cstdio>
    2 #include <cstdlib>
    3 #include <ctime>
    4
    5 static unsigned int set_times = 0;
    6 static unsigned int cmp_times = 0;
    7
    8 template<typename item_type> void setval(item_type& item1, item_type& item2) {
    9 set_times += 1;
    10 item1 = item2;
    11 return;
    12 }
    13
    14 template<typename item_type> int compare(item_type& item1, item_type& item2) {
    15 cmp_times += 1;
    16 return item1 < item2;
    17 }
    18
    19 template<typename item_type> void swap(item_type& item1, item_type& item2) {
    20 item_type item3;
    21
    22 setval(item3, item1);
    23 setval(item1, item2);
    24 setval(item2, item3);
    25 return;
    26 }
    27
    28 template<typename item_type> void heap_sort(item_type* array, int size) {
    29 item_type tempitem;
    30 int current;
    31 int next;
    32 int top = size / 2;
    33
    34 while(size > 0) {
    35 if(top > 0) top -= 1; else swap(array[--size], array[0]);
    36
    37 setval(tempitem, array[top]);
    38 current = top;
    39 while(1) {
    40 next = current * 2 + 1;
    41 if(next + 1 < size && compare(array[next], array[next + 1])) {
    42 next += 1;
    43 }
    44 if(next < size) {
    45 setval(array[current], array[next]);
    46 current = next;
    47 } else break;
    48 }
    49
    50 while(next > 0) {
    51 next = (current - 1) / 2;
    52 if(next >= top && compare(array[next], tempitem)) {
    53 setval(array[current], array[next]);
    54 current = next;
    55 } else break;
    56 }
    57 setval(array[current], tempitem);
    58 }
    59 return;
    60 }
    61
    62 int main(int argc, char** argv) {
    63 int capacity = 0;
    64 int size = 0;
    65 int i;
    66 clock_t clock1;
    67 clock_t clock2;
    68 double data;
    69 double* array = NULL;
    70
    71 // generate randomized test case
    72 while(scanf("%lf", &data) == 1) {
    73 if(size == capacity) {
    74 capacity = (size + 1) * 2;
    75 array = (double*)realloc(array, capacity * sizeof(double));
    76 }
    77 array[size++] = data;
    78 }
    79
    80 // sort
    81 clock1 = clock();
    82 heap_sort(array, size);
    83 clock2 = clock();
    84
    85 // output test result
    86 fprintf(stderr, "heap_sort:\t");
    87 fprintf(stderr, "time %.2lf\t", (double)(clock2 - clock1) / CLOCKS_PER_SEC);
    88 fprintf(stderr, "cmp_per_elem %.2lf\t", (double)cmp_times / size);
    89 fprintf(stderr, "set_per_elem %.2lf\n", (double)set_times / size);
    90 for(i = 0; i < size; i++) {
    91 fprintf(stdout, "%lf\n", array[i]);
    92 }
    93 free(array);
    94 return 0;
    95 }

  • 相关阅读:
    人工智能实战2019第一次作业_李大
    300道四则运算题目
    build to win读后感
    C# WinForm(简易计算器示例)
    WPF关于Calendar的Style
    winform下实现Label在窗体中从右到左不断循环的动画效果
    WPF 选中datagrid列头中checkbox则全选对应整列checkbox
    Window下android 模拟器SD卡的使用方法
    Linux下在Android模拟器中使用SD 卡的操作步骤
    WPF之VLC流媒体播放
  • 原文地址:https://www.cnblogs.com/richselian/p/2179146.html
Copyright © 2020-2023  润新知