JonsenElizee

Software Developing Blog

"An idea is fragile . It can be killed by a scornful smile or a yawn .It can be mound down by irony and scared to death by a cold look."
"Most cultures throughout human history have not liked creative individuals .They ignore them or kill them.It is a very efficient way of stopping creativity."

------Advertising boss Charles Browe and Howard Gardner ,professor at Harvard

   :: 首页 :: 新随笔 ::  ::  :: 管理 ::

关于快速排序

我们都知道快速排序有很好的O(nlogn),那么更快的快速排序在哪里呢?下面是我的学习记录。

--By JonsenElizee 2010/09/23

常规的快速排序

学习快速排序,最让人熟悉的是两个ptr左右来回指,一次排序后就把一个mid值放在了合适的位置上。这是我一个朋友的非递归的C++实现。我改写一点点,就是加了Crand()来设置数组值,然后编译运行这个算法,你可能还不能随随便便的写出这个算法,但效果真的很不乐观,也不知道要运行多久才能排序完26*50的字符串。后面我们会看到一个很精悍的算法。。。

 1 #include <stack>
 2 #include <vector>
 3 #include <iostream>
 4 #include <stdlib.h>
 5 #include <stdio.h>
 6 #include <time.h>
 7 
 8 using namespace std;
 9 
10 typedef struct _record
11 {
12     int begin;
13     int end;
14 }record;
15 
16 void quick_sort(int a[],int len)
17 {
18     vector<record> do_job;
19     record temp;
20     temp.begin = 0;
21     temp.end = len-1;
22     do_job.push_back(temp);
23 
24     while (do_job.size()  != 0) {
25         record temp = do_job.back();
26         do_job.pop_back();
27     
28         int low = temp.begin;
29         int high = temp.end;
30         int key = a[low];
31         while (low < high) {
32             while(low < high && a[high] >= key) high--;
33             a[low] = a[high];
34             while(low < high && a[low] <= key) low++;
35             a[high] = a[low];
36         }
37         a[low] = key;
38 
39         record temp1;
40         temp1.begin = temp.begin;
41         temp1.end = low-1;
42         if (temp1.begin < temp1.end) { do_job.push_back(temp1); }
43 
44         record temp2;
45         temp2.begin = low+1;
46         temp2.end = temp.end;
47         if (temp2.begin < temp2.end) { do_job.push_back(temp2); }
48     }
49 }
50 int main()
51 {
52     int a[26*50];
53     int i = 0;
54     while(i < 26*50) a[i] = rand() % 100;
55     int count =sizeof(a) / sizeof(int);
56     quick_sort(a,count);
57     for (int i = 0; i < count; i++) cout<<a[i]<<endl;
58     return 0;
59 }
60 


更简更快快速排序

这种快速排序不是最快的,特别是基本有序时会退化到O(n^2),理论上基于比较的排序不会小于O(nlogn),但还是有加速的可能。下面这个是《Programming Pearls 2nd》里面的方法,这个算法真的很精悍,运行完26*50的一个排序,只需要0.09秒,我的实现如下。


运行时是给的一个长度为26*50的一个字符数组,对它进行排序:



更简更快快速排序++

研究上面算法的执行过程,遵循大师的思路,我改写了算法,在我的X61Redhat EL5上运行速度比上面的算法快了8倍,也就是运行完26*50长的排序,只需要0.01秒!最后我明白一个道理,要有思想,要有毅力,要有实践。完稿时,我发现这个算法还有改进的余地。特和大家分享。多多指点。

运行输入和quick.c中的一样:

运行结果对比

常规的那个非递归的算法从我写这个文件到现在,它还在运行着。。。

第二个和第三个时间对比如下图:

(加不加优化-O3都是一样的结果,在我的X61上,gcc version 4.1.2 20080704 (Red Hat 4.1.2-48))


改进的myquick.c的运行时间是quick.c1/9

最后,我不得不用CtrlC把那个常规的给KILL掉。

Real, User and Sys process time statistics

One of these things is not like the other. Real refers to actual elapsed time; User and Sys refer to CPU time used only by the process.
    *Real is wall clock time - time from start to finish of the call. This is all elapsed time including time slices used by other processes and time the process spends blocked (for example if it is waiting for I/O to complete).
    *User is the amount of CPU time spent in user-mode code (outside the kernel) within the process. This is only actual CPU time used in executing the process. Other processes and time the process spends blocked do not count towards this figure.
    *Sys is the amount of CPU time spent in the kernel within the process. This means executing CPU time spent in system calls within the kernel, as opposed to library code, which is still running in user-space. Like 'user', this is only CPU time used by the process.
      User+Sys will tell you how much actual CPU time your process used.

 

源代码

核心算法对比图



quick.c源代码

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <time.h>
 5 
 6 void quick(char* str, int low, int hig);
 7 void swap(char* a, char* b);
 8 
 9 int main()
10 {
11     char ary[] = //26*50长的字符串数组,内容参考上图。
12     char* str = ary;
13     printf("calling quick");
14     quick(str, 0, strlen(str)-1);
15     return 0;
16 }
17 
18 void quick(char* str, int low, int hig) {
19     if(low >= hig) return;
20     srand(time(NULL));
21     // get a random key
22     //swap(str + low, str + low + (rand() % (hig - low + 1)));
23     int i = low, j = hig + 1, key = str[low];
24     while(1)
25     {
26         while(++<= hig && str[i] <= key);
27         while(-->= low && str[j] >  key);
28         if(i > j) break// no need to do swap
29         swap(str + i, str + j);
30     }
31     swap(str + low, str + i - 1); // swap key to i-1 position
32     quick(str, low, i - 2);
33     quick(str, i, hig);
34 }
35 
36 void swap(char* a, char* b) {
37     if(a == b) return;
38     *^= *b; *^= *a; *^= *b;
39 }
40 

 

 

myquick.c源代码

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <time.h>
 5 
 6 void myquick(char* str, int low, int hig);
 7 void swap(char* a, char* b);
 8 
 9 int main()
10 {
11     char ary[] = //26*50长的字符串,同quick.c的输入。
12     char* str = ary;
13     printf("calling myquick");
14     myquick(str, 0, strlen(str)-1);
15     return 0;
16 }
17 
18 void myquick(char* str, int low, int hig) {
19     if(low >= hig) return;// no need to sort elements
20     // elements in the right of [m] are not sorted
21     int m = low, i = low, j = hig, key = low;
22     // skip any elements that <= [key]
23     while(i <= hig && str[i] <= str[key]) {i++; m++;}
24     // skip elements > [key]
25     while(j >= low && str[j] > str[key]) j--;
26     // initially, i==j is impossible
27     while(i <= j) {
28         // swap small one to m-position
29         if(str[i] <= str[key]) { swap(str + m++, str + i); }
30         i++;
31     }
32     swap(str + low, str + m-1);
33     myquick(str, low, m - 2);
34     myquick(str, m, hig);
35     return;
36 }
37 
38 void swap(char* a, char* b) {
39     if(a == b) return;
40     *^= *b; *^= *a; *^= *b;
41 }
42 




posted on 2010-09-23 15:24 JonsenElizee 阅读(2783) 评论(0)  编辑 收藏 引用 所属分类: C.BasicLinux.CLinux.C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


By JonsenElizee