堆排序
这里以小顶堆为例:
思路:
对于堆排序来说,首先需要做的是要建堆,建堆是一个不断调整堆的过程,能够在线性时间内完成。
堆排序的过程
1、建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2) 其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。
2、调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,如果最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为是沿着深度方向进行调整的。
3、堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是被最后一个节点覆盖掉),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)
代码:
1 #include <fstream> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstdio> 5 #include <cstring> 6 #include <cmath> 7 #include <vector> 8 #include <cstdlib> 9 10 using namespace std; 11 12 #define PI acos(-1.0) 13 #define EPS 1e-10 14 #define lll __int64 15 #define ll long long 16 #define INF 0x7fffffff 17 18 //tree为小根堆(这里用数组来实现) 19 vector<int> tree; 20 //排好序的序列fix 21 int *fix; 22 23 void buildTree(); 24 void insertElement(int x); 25 void deleteMinElement(); 26 void swim(int ii); 27 void order(); 28 29 int main(){ 30 //freopen("D:\\input.in","r",stdin); 31 //freopen("D:\\output.out","w",stdout); 32 int n; 33 scanf("%d",&n); 34 tree.resize(n+1); 35 for(int i=1;i<=n;i++) scanf("%d",&tree[i]); 36 buildTree(); 37 insertElement(9); 38 deleteMinElement(); 39 n=tree.size(); 40 fix=new int[n]; 41 order(); 42 for(int i=1;i<n;i++) printf("%d ",fix[i]); 43 return 0; 44 } 45 void buildTree(){ 46 int cur=(tree.size()-1)/2; 47 while(cur){ 48 swim(cur); 49 cur--; 50 } 51 } 52 void insertElement(int x){ 53 tree.push_back(x); 54 int cur=tree.size()-1; 55 int son; 56 while(1){ 57 son=cur; 58 cur>>=1; 59 if(!cur){ 60 tree[son]=x; 61 break; 62 } 63 if(tree[cur]>=x){ 64 tree[son]=tree[cur]; 65 }else{ 66 tree[son]=x; 67 break; 68 } 69 } 70 } 71 void deleteMinElement(){ 72 tree[1]=tree[tree.size()-1]; 73 tree.pop_back(); 74 swim(1); 75 } 76 void swim(int ii){ 77 int son,t=tree[ii]; 78 int n=tree.size()-1; 79 while((ii<<1)<=n){ 80 if((ii<<1)+1<=n&&tree[ii<<1]>=tree[(ii<<1)+1]) son=(ii<<1)+1; 81 else son=(ii<<1); 82 if(t>tree[son]){ 83 tree[ii]=tree[son]; 84 ii=son; 85 }else{ 86 break; 87 } 88 } 89 tree[ii]=t; 90 } 91 void order(){ 92 int cur=1; 93 while(tree.size()!=1){ 94 fix[cur++]=tree[1]; 95 deleteMinElement(); 96 } 97 }