zoukankan      html  css  js  c++  java
  • 《数据结构与算法分析:C语言描述》复习——第六章“排序”——堆排序

    2014.06.17 03:29

    简介:

      堆排序,是从这本教材上看,最好的排序算法。它是稳定排序,时间复杂度稳定保持在O(n * log(n)),空间复杂度为O(1)。原理非常简单,实现也比较简单。但是,应用却不如快速排序和归并排序那么广。原因咱们下面说说。

    描述:

      如果你要把数组排成升序,你可以依次把最小的元素放前面,或把最大的元素往后放。我们在第五章学习了堆,知道可以用数组来表示一个堆。那么我们就通过建堆算法,把这个数组变成一个大顶堆,堆顶元素最大。每次从这个堆拿出堆顶放在数组的后面,放了n - 1次以后,整个数组就排好序了。

      那堆排序有什么不如快速排序的呢?应该是输在常系数上了,从代码里可以看到堆排序在随机访问元素的时候,下标的变化很大。如果你还考虑了内存里数据寻址的耗时,那么快速排序、归并排序要访问的内存总是离得更近(人家用的是++和--),这样就不会像堆排序那样到处寻址了。不过,这个理由也没有很大的说服力。因为你自己手写一个快速排序和堆排序进行比较,很有可能堆排序会胜出。而目前最优秀的排序算法sort君,其内涵是非常丰富的,绝不是简单的快速排序。纠结于这些算法到底谁最好,不如取长补短。在找工作时,堆排序确实有个实实在在的好处,当你写不出快排的时候,堆排序就容易多了。因为——不论快速排序还是快速选择,都是既不好分析又容易写错的算法。如果sort不让用,还是堆排序吧;万一堆排序也忘了,就归并了吧;如果归并也忘了,你就回家等通知吧。

    实现:

     1 // My implementation for selection sort.
     2 #include <iostream>
     3 #include <vector>
     4 using namespace std;
     5 
     6 static inline int leftChild(int n)
     7 {
     8     return n * 2 + 1;
     9 }
    10 
    11 static inline int rightChild(int n)
    12 {
    13     return n * 2 + 2;
    14 }
    15 
    16 static inline void swap(int &x, int &y)
    17 {
    18     int tmp;
    19     
    20     tmp = x;
    21     x = y;
    22     y = tmp;
    23 }
    24 
    25 static inline int max(const int &x, const int &y)
    26 {
    27     return x > y ? x : y;
    28 }
    29 
    30 static void percolateDown(vector<int> &v, int i, int n)
    31 {
    32     if (n <= 1 || i < 0 || i >= n) {
    33         return;
    34     }
    35     int max_val;
    36 
    37     while (leftChild(i) < n) {
    38         if (leftChild(i) == n - 1) {
    39             max_val = v[leftChild(i)];
    40         } else {
    41             max_val = max(v[leftChild(i)], v[rightChild(i)]);
    42         }
    43         if (v[i] < max_val) {
    44             if (max_val == v[leftChild(i)]) {
    45                 swap(v[i], v[leftChild(i)]);
    46                 i = leftChild(i);
    47             } else {
    48                 swap(v[i], v[rightChild(i)]);
    49                 i = rightChild(i);
    50             }
    51         } else {
    52             break;
    53         }
    54     }
    55 }
    56 
    57 void heapSort(vector<int> &v)
    58 {
    59     int n;
    60     int i;
    61     
    62     n = (int)v.size();
    63     for (i = (n - 1) / 2; i >= 0; --i) {
    64         percolateDown(v, i, n);
    65     }
    66     
    67     int val;
    68     for (i = 0; i < n - 1; ++i) {
    69         val = v[0];
    70         v[0] = v[n - 1 - i];
    71         percolateDown(v, 0, n - 1 - i);
    72         v[n - 1 - i] = val;
    73     }
    74 }
    75 
    76 int main()
    77 {
    78     vector<int> v;
    79     int n, i;
    80     
    81     while (cin >> n && n > 0) {
    82         v.resize(n);
    83         for (i = 0; i < n; ++i) {
    84             cin >> v[i];
    85         }
    86         heapSort(v);
    87         for (i = 0; i < n; ++i) {
    88             cout << v[i] << ' ';
    89         }
    90         cout << endl;
    91     }
    92     
    93     return 0;
    94 }
  • 相关阅读:
    TCP/IP协议栈与数据包封装+TCP与UDP区别
    MySQL数据库优化总结
    MySQL存储引擎,锁,优化简述
    java实现常见查找算法
    Java的几种常见排序算法
    UML类图学习
    高性能的RTC服务器OpenFire
    常用的设计模式
    Swing JInternalFrame的使用
    Qt 模态与非模态
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3792084.html
Copyright © 2011-2022 走看看