C++ 追溯 各类排序算法实现及效率

2015-01-13 20:19:25

总结:刚好数据结构课让我们做排序的实验,我来总结一下各类排序算法~

  主要实现:(1)插入排序 (2)归并排序 (3)快速排序 (4)堆排序 (5)希尔排序   (冒泡,选择啥的路过辣...)

  整理下各个算法的思路:

  (1)插入排序,这个按照最原始的扑克插入就很好想(借算导例子...)一个一个插入即可,这个算法的姿势可以很糟糕可以很优美,也可以用二分进行优化,不多说了。

  (2)归并排序,分而治之,将数列分成两块并且预先排完序后再将两者按大小归并成有序的总数列,需要借助两个全局数组L[]和R[]来存两半边的数列(尚未想到不用辅助数组的写法...)

  (3)快速排序,其实也是分而治之的思想,只不过这个是以某个数为标准,将整个数列中大于和小于这个数的数分为两部分,然后再分别处理这两个部分。

      在处理一个子区间时,选定的数可以是随机位置,也可以就是第一或者最后一个数,然后将比标准小的数放左,比它大的放右,最后别我忘记把标准数放回中间。

  (4)堆排序,这个思路比较简单,就是直接根据数列构造出最小 / 最大堆,然后逐个出堆即可。

  (5)希尔排序,插入排序的进化版,简而言之就是将数列分成那么几段:i , i + gap , i + 2*gap , i + 3*gap .... (1 <= i < gap),然后对这些段进行插入排序处理。每次处理完后

     都将这个增量gap缩小,一般缩小为gap/2,直到处理完gap=1的情况。(按照这种方法,gap初始值一般设为:size / 2)

  1 //Writer : Natureal
  2 //Address:Soochow University
  3 //Email  : 564374850@qq.com
  4 #include <cstdio>
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <ctime>
  8 #include <cmath>
  9 #include <set>
 10 #include <map>
 11 #include <stack>
 12 #include <queue>
 13 #include <fstream>
 14 #include <string>
 15 #include <iomanip>
 16 #include <iostream>
 17 #include <algorithm>
 18 using namespace std;
 19 #define MEM(a,b) memset(a,b,sizeof(a))
 20 #define REP(i,n) for(int i = 1; i <= (n); ++i) //1~n 循环
 21 #define REV(i,n) for(int i = (n); i >= 1; --i) //n~1 逆循环
 22 #define FOR(i,a,b) for(int i = (a); i <= (b); ++i) //a~b 循环
 23 #define FREV(i,a,b) for(int i = (a); i >= (b); --i) //b~a 逆循环
 24 #define MP(a,b) make_pair((a),(b))
 25 typedef long long ll;
 26 typedef pair<int,int> pii;
 27 const int INF = (1 << 30) - 1;
 28 const int maxn = 10010;
 29 
 30 int or20[maxn],or200[maxn],or2000[maxn];
 31 int re20[maxn],re200[maxn],re2000[maxn];
 32 int ra20[maxn],ra200[maxn],ra2000[maxn];
 33 int now20[maxn],now200[maxn],now2000[maxn];
 34 int cnt_cmp,cnt_move;//记录关键字比较次数,移动次数
 35 int ans[maxn];       //暂存的数据的辅助数组
 36 int L[maxn],R[maxn]; //归并排序所用的辅助数组
 37 double duration;     //耗时计数器
 38 clock_t st,ed;       //时间记录点
 39 
 40 void Insert_sort(int *val,int size){  //插入排序,参考《算法导论》
 41     int pos;
 42     cnt_cmp += size - 1;
 43     FOR(i,2,size) if(val[i] < val[i - 1]){
 44         val[0] = val[i],pos = i - 1;  //val[0]作为哨兵
 45         cnt_move++,cnt_cmp++;
 46         while(val[pos] > val[0]){
 47             val[pos + 1] = val[pos];
 48             pos--;
 49             cnt_cmp++,cnt_move++;
 50         }
 51         val[pos + 1] = val[0];
 52         cnt_move++;
 53     }
 54 }
 55 
 56 void Merge_sort(int *val,int l,int r){ //归并排序
 57     if(l < r){
 58         int mid = (l + (r - l) / 2);
 59         Merge_sort(val,l,mid);
 60         Merge_sort(val,mid + 1,r);
 61         int pl = 1,pr = 1,szl = mid - l + 1,szr = r - mid;
 62         REP(i,szl) L[i] = val[l - 1 + i];
 63         REP(i,szr) R[i] = val[mid + i];
 64         cnt_move += r - l + 1;
 65         FOR(i,l,r){
 66             if(pr > szr || (pl <= szl && L[pl] <= R[pr]))
 67                 val[i] = L[pl++];
 68             else val[i] = R[pr++];
 69             cnt_cmp++;
 70         }
 71     }
 72 }
 73 
 74 void Quick_sort(int *val,int l,int r){ //快速排序,递归版
 75     if(l < r){
 76         int x = val[l],i = l,j = r;   //这里以val[l]为基准,并把val[l]取出来存在x中
 77         while(i < j){
 78             while(i < j && val[j] > x) --j,++cnt_cmp;
 79             if(i < j) val[i++] = val[j],++cnt_move;   //从右到左找到第一个小于x的val位置
 80             while(i < j && val[i] < x) ++i,++cnt_cmp; //填补val[i](一开始的val[i]就是val[l])
 81             if(i < j) val[j--] = val[i],++cnt_move;   //从左到右找到第一个大于等于x的val位置
 82         }
 83         val[i] = x;        
 84         Quick_sort(val,l,i - 1);            //递归处理左半区间[l,i - 1]
 85         Quick_sort(val,i + 1,r);            //递归处理右半区间[i + 1,r]
 86     }
 87 }
 88 
 89 struct Heap{                         //堆结构体,由自己实现的独立结构(为了计算关键字次数进行了改进)
 90     int sz,t[maxn << 1];
 91     void clear(){ sz = 0;}
 92     void push(int val){
 93         int p = ++sz;
 94         while(p > 1){                //入堆操作,加入堆树的末尾,然后向上调整
 95             int fa = p / 2;
 96             ++cnt_cmp;
 97             if(t[fa] <= val) break;
 98             t[p] = t[fa],++cnt_move;
 99             p = fa;
100         }
101         t[p] = val,++cnt_move;
102     }
103     void pop(){                      //出堆操作,将堆树的最后一个元素调顶,然后向下调整
104         int val = t[sz--];
105         int p = 1;
106         while(p * 2 <= sz){
107             int a = p * 2,b = p * 2 + 1;
108             cnt_cmp += 2;
109             if(b <= sz && t[b] < t[a]) swap(a,b);
110             if(t[a] >= val) break;
111             t[p] = t[a],++cnt_move;
112             p = a;
113         }
114         t[p] = val,++cnt_move;
115     }
116     int top(){
117         return t[1];
118     }
119 };
120 
121 void Heap_sort(int *val,int size){ //堆排序
122     Heap h; h.clear();
123     REP(i,size) h.push(val[i]);
124     REP(i,size) val[i] = h.top(),h.pop();
125 }
126 
127 void Shell_sort(int *val,int size){ //希尔排序
128     for(int gap = size / 2; gap; gap /= 2){ //设定增量,从size / 2开始,然后每次的增量减半,直至为零退出
129         REP(i,gap) for(int j = i + gap; j <= size; j += gap){
130             ++cnt_cmp;
131             if(val[j] < val[j - gap]){
132                 val[0] = val[j];
133                 int pos = j - gap;
134                 ++cnt_cmp,++cnt_move;
135                 while(pos > 0 && val[0] < val[pos]){
136                     val[pos + gap] = val[pos];
137                     pos -= gap;
138                     ++cnt_cmp,++cnt_move;
139                 }
140                 val[pos + gap] = val[0];
141                 ++cnt_move;
142             }
143         }
144     }
145 }
146 
147 inline void Print(){
148     cout << " ,关键字比较次数:" << cnt_cmp
149          << " ,关键字移动次数:" << cnt_move << endl << endl;
150 }
151 
152 void Solve_insert_sort(int size){     //插入排序预处理
153     cnt_cmp = cnt_move = 0;           //排序前初始化
154     st = clock();                      //st为排序执行前的时间点
155     Insert_sort(ans,size);
156     ed = clock();                      //ed为排序执行后的时间点
157     duration = 1000.0 * (ed - st) / CLOCKS_PER_SEC; //计算排序算法耗时,单位是毫秒(ms)
158     cout << "<插入排序>耗时:" << duration << " ms";
159     Print();
160 }
161 
162 void Solve_quick_sort(int size){      //快速排序预处理
163     cnt_cmp = cnt_move = 0;
164     st = clock();
165     Quick_sort(ans,1,size);
166     ed = clock();
167     duration = 1000.0 * (ed - st) / CLOCKS_PER_SEC;
168     cout << "<快速排序>耗时:" << duration << " ms";
169     Print();
170 }
171 
172 void Solve_heap_sort(int size){       //堆排序预处理
173     cnt_cmp = cnt_move = 0;
174     st = clock();
175     Heap_sort(ans,size);
176     ed = clock();
177     duration = 1000.0 * (ed - st) / CLOCKS_PER_SEC;
178     cout << "<堆排序>耗时:" << duration << " ms";
179     Print();
180 }
181 
182 void Solve_merge_sort(int size){      //归并排序预处理
183     cnt_cmp = cnt_move = 0;
184     st = clock();
185     Merge_sort(ans,1,size);
186     ed = clock();
187     duration = 1000.0 * (ed - st) / CLOCKS_PER_SEC;
188     cout << "<归并排序>耗时:" << duration << " ms";
189     Print();
190 }
191 
192 void Solve_shell_sort(int size){      //希尔排序预处理
193     cnt_cmp = cnt_move = 0;
194     st = clock();
195     Shell_sort(ans,size);
196     ed = clock();
197     duration = 1000.0 * (ed - st) / CLOCKS_PER_SEC;
198     cout << "<希尔排序>耗时:" << duration << " ms";
199     Print();
200 }
201 
202 void Work(){
203     //First scale : 20
204     cout << "【数据规模】:20" << endl;
205 
206     memcpy(ans,now20,sizeof(now20));
207     Solve_insert_sort(20);
208     memcpy(ans,now20,sizeof(now20));
209     Solve_merge_sort(20);
210     memcpy(ans,now20,sizeof(now20));
211     Solve_quick_sort(20);
212     memcpy(ans,now20,sizeof(now20));
213     Solve_heap_sort(20);
214     memcpy(ans,now20,sizeof(now20));
215     Solve_shell_sort(20);
216 
217     //Second scale : 200
218     cout << "【数据规模】:200" << endl;
219 
220     memcpy(ans,now200,sizeof(now200));
221     Solve_insert_sort(200);
222     memcpy(ans,now200,sizeof(now200));
223     Solve_merge_sort(200);
224     memcpy(ans,now200,sizeof(now200));
225     Solve_quick_sort(200);
226     memcpy(ans,now200,sizeof(now200));
227     Solve_heap_sort(200);
228     memcpy(ans,now200,sizeof(now200));
229     Solve_shell_sort(200);
230 
231     //Third scale : 2000
232     cout << "【数据规模】:2000" << endl;
233 
234     memcpy(ans,now2000,sizeof(now2000));
235     Solve_insert_sort(2000);
236     memcpy(ans,now2000,sizeof(now2000));
237     Solve_merge_sort(2000);
238     memcpy(ans,now2000,sizeof(now2000));
239     Solve_quick_sort(2000);
240     memcpy(ans,now2000,sizeof(now2000));
241     Solve_heap_sort(2000);
242     memcpy(ans,now2000,sizeof(now2000));
243     Solve_shell_sort(2000);
244 
245 }
246 
247 int main(){
248     //指定文件
249     ifstream order20("order_20.txt");
250     ifstream order200("order_200.txt");
251     ifstream order10000("order_2000.txt");
252     ifstream reverse20("reverse_20.txt");
253     ifstream reverse200("reverse_200.txt");
254     ifstream reverse10000("reverse_2000.txt");
255     ifstream random20("random_20.txt");
256     ifstream random200("random_200.txt");
257     ifstream random10000("random_2000.txt");
258     
259     srand((unsigned)time(NULL));
260 
261     //读入数据
262     REP(i,20){
263         order20 >> or20[i];
264         reverse20 >> re20[i];
265         random20 >> ra20[i];
266     }
267     REP(i,200){
268         order200 >> or200[i];
269         reverse200 >> re200[i];
270         random200 >> ra200[i];
271     }
272     REP(i,2000){
273         order10000 >> or2000[i];
274         reverse10000 >> re2000[i];
275         random10000 >> ra2000[i];
276     }
277     //测试各类排序
278 
279     cout << "顺序数据:=======================================================" << endl << endl;
280     memcpy(now20,or20,sizeof(or20));
281     memcpy(now200,or200,sizeof(or200));
282     memcpy(now2000,or2000,sizeof(or2000));
283     Work();
284 
285     cout << "逆序数据:=======================================================" << endl << endl;
286     memcpy(now20,re20,sizeof(re20));
287     memcpy(now200,re200,sizeof(re200));
288     memcpy(now2000,re2000,sizeof(re2000));
289     Work();
290 
291     cout << "随机数据:=======================================================" << endl << endl;
292     memcpy(now20,ra20,sizeof(ra20));
293     memcpy(now200,ra200,sizeof(ra200));
294     memcpy(now2000,ra2000,sizeof(ra2000));
295     Work();
296 
297     return 0;
298 }

 

posted @ 2015-01-13 21:49  Naturain  阅读(172)  评论(0编辑  收藏  举报