zoukankan      html  css  js  c++  java
  • 堆排序 heap sort

    https://github.com/hotwater99/practice_datastructure_and_algorithm.git

    《数据结构与算法分析——C语言描述》机械工业出版社,原书第2版,7.5节


    可以参考这篇文章,有一步步的图解:

    https://blog.csdn.net/u010452388/article/details/81283998

    另外这个动图也可以帮助理解:

    https://www.jianshu.com/p/0d383d294a80

    1940317-9c37b4be1b7c96d1

    堆排序分为两步:

    1、把待排序的数组(N个元素)变成一个Max堆;

    2、数组分为两部分,前一部分为堆空间(初始大小N),后一部分为排序空间(初始大小0);

    3、取出堆顶的数,即堆空间的第一个数A[堆顶]与最后一个数B交换,堆空间-1,同时A进入排序空间(因为每次取出的都是堆中最大的数,交换后的位置也是连续的),排序空间+1;

    4、剩下的数再重新构造成Max堆,即将B在堆中下滤;

    5、最后得到的数组就变成了从小到大排列的有序数组。


    堆排序:

      1 #define LeftChild(i)    (2 * (i) + 1)
      2 
      3 void PercDown(int array[], int i, int N)
      4 {
      5   int child;
      6   int tmp;
      7 
      8   for (tmp = array[i]; LeftChild(i) < N; i = child) {
      9     child = LeftChild(i);
     10     if (child + 1 < N && array[child + 1] > array[child]) {
     11       child++;
     12     }
     13     if (tmp < array[child]) {
     14       array[i] = array[child];
     15     }
     16     else {
     17       break;
     18     }
     19   }
     20   array[i] = tmp;
     21 }
     22 
     23 void Swap(int *a, int *b)
     24 {
     25   int tmp = *a;
     26   *a = *b;
     27   *b = tmp;
     28 }
     29 
     30 void HeapSort(int array[], int N)
     31 {
     32   int i;
     33 
     34   // build heap
     35   for (i = N / 2; i >= 0; i--) {
     36     PercDown(array, i, N);
     37   }
     38   // delete max
     39   for (i = N - 1; i > 0; i--) {
     40     Swap(&array[0], &array[i]);
     41     PercDown(array, 0, i);
     42   }
     43 }

    void PercDown(int array[], int i, int N) 的功能是把array[i]这个元素下滤。

    构造Max堆:array[0]到array[N/2]将是非叶子节点,array[N/2]之后的将是叶子节点(不一定是在堆的最后一层,但都是叶子节点)。所以从非叶子节点开始处理,且从下往上,从右到左,即35行中i从N/2开始递减。

    删除最大数:交换堆顶array[0]--a和array[i]--b,堆顶a放到array[i],array[i]之后就不属于堆了,完成了从堆中删除最大数的操作,同时因为每次取出的都是堆中最大数,i也是从N-1开始递减,这样也完成了排序的工作;之后对b进行一次下滤操作,完成了重新构造Max堆的操作。


    完整代码:
      1 #include <iostream>
      2 #include <ctime>
      3 
      4 using namespace std;
      5 
      6 #define random(x)       (rand()%x)
      7 #define ARRAY_LENTH     100000
      8 
      9 #define LeftChild(i)    (2 * (i) + 1)
     10 
     11 void PercDown(int array[], int i, int N)
     12 {
     13   int child;
     14   int tmp;
     15 
     16   for (tmp = array[i]; LeftChild(i) < N; i = child) {
     17     child = LeftChild(i);
     18     if (child + 1 < N && array[child + 1] > array[child]) {
     19       child++;
     20     }
     21     if (tmp < array[child]) {
     22       array[i] = array[child];
     23     }
     24     else {
     25       break;
     26     }
     27   }
     28   array[i] = tmp;
     29 }
     30 
     31 void Swap(int *a, int *b)
     32 {
     33   int tmp = *a;
     34   *a = *b;
     35   *b = tmp;
     36 }
     37 
     38 void HeapSort(int array[], int N)
     39 {
     40   int i;
     41 
     42   // build heap
     43   for (i = N / 2; i >= 0; i--) {
     44     PercDown(array, i, N);
     45   }
     46   // delete max
     47   for (i = N - 1; i > 0; i--) {
     48     Swap(&array[0], &array[i]);
     49     PercDown(array, 0, i);
     50   }
     51 }
     52 
     53 int main() {
     54   int test_array[ARRAY_LENTH];
     55   int i, N = ARRAY_LENTH;
     56   clock_t start_time, stop_time;
     57 
     58   for (i = 0; i < N; i++) {
     59     test_array[i] = random(N);
     60   }
     61 
     62   cout << "raw : ";
     63   for (i = 0; i < N; i++) {
     64     cout << test_array[i] << " ";
     65   }
     66   cout << endl;
     67 
     68   start_time = clock();
     69 
     70   HeapSort(test_array, N);
     71 
     72   stop_time = clock();
     73 
     74   cout << "sort: " ;
     75   for (i = 0; i < N; i++) {
     76     cout << test_array[i] << " ";
     77   }
     78   cout << endl;
     79 
     80   cout << "HeapSort(" << N << ")..." << endl;
     81   cout << "total time used: ";
     82   cout  << (double)(stop_time - start_time) / CLOCKS_PER_SEC << "s" << endl;
     83 
     84   system("pause");
     85 
     86   return 0;
     87 }


    测试结果


    N=10

    raw : 1 7 4 0 9 4 8 8 2 4
    sort: 0 1 2 4 4 4 7 8 8 9
    HeapSort(10)...
    total time used: 0s

    N=100

    raw : 41 67 34 0 69 24 78 58 62 64 5 45 81 27 61 91 95 42 27 36 91 4 2 53 92 82 21 16 18 95 47 26 71 38 69 12 67 99 35 94 3 11 22 33 73 64 41 11 53 68 47 44 62 57 37 59 23 41 29 78 16 35 90 42 88 6 40 42 64 48 46 5 90 29 70 50 6 1 93 48 29 23 84 54 56 40 66 76 31 8 44 39 26 23 37 38 18 82 29 41
    sort: 0 1 2 3 4 5 5 6 6 8 11 11 12 16 16 18 18 21 22 23 23 23 24 26 26 27 27 29 29 29 29 31 33 34 35 35 36 37 37 38 38 39 40 40 41 41 41 41 42 42 42 44 44 45 46 47 47 48 48 50 53 53 54 56 57 58 59 61 62 62 64 64 64 66 67 67 68 69 69 70 71 73 76 78 78 81 82 82 84 88 90 90 91 91 92 93 94 95 95 99
    HeapSort(100)...
    total time used: 0s

    N=1000

    HeapSort(1000)...
    total time used: 0s

    N=10000

    HeapSort(10000)...
    total time used: 0.001s

    N=100000

    HeapSort(100000)...
    total time used: 0.017s
  • 相关阅读:
    Vue路由机制
    谷歌浏览器打不开应用商店的解决方法
    Vue报错——Component template should contain exactly one root element. If you are using vif on multiple elements, use velseif to chain them instead.
    Vue.js学习之——安装
    Vue使用axios无法读取data的解决办法
    关于localstorage存储JSON对象的问题
    2013年整体计划
    个人喜欢的警语收集
    Linux防火墙的关闭和开启
    Flex修改title 转载
  • 原文地址:https://www.cnblogs.com/hotwater99/p/12800865.html
Copyright © 2011-2022 走看看