理解快速排序

快速排序(QuickSort)

1 原理

     快速排序是基于分治思想上的排序,由冒泡排序改进而来.排序效率较高,时间复杂度:O(n*lgn),最坏时是:O(n^2).主要思想如下:

     1 选取基准元素(一般为第一个或最后一个元素)进行分解

     2 将分解后的子数组再排序

     3 合并

2 实例

    下面结合具体的例子分析:

    数组如下:

0 1 2 3 4 5

6

5  98 45 134 23 54

78

 

 

    首先 i = 0, j = 6,temp(哨点)=num[i]=5

    此时已经有temp这个变量保持num[0]的值了,可理解为在此处挖了个坑,需要其他的数据来填充.下面就从j开始往左一直找到一个比temp小的值,然后放在num[0]处,此例中5为最小的所以直到j变为0跟i相等才会停止.i= j = 0,,这样第一轮就结束,i的值没变仍为0,num[0]=temp.就说明num[0]是最小的,这样就把数组分成了两部分:左边的为空,右边的从num[1]~num[6].

    下面要排的就是右边的部分,此时 i = 1, j = 6, temp = num[i] = 98

     还是从右边找比temp小的数,78就符合,那么把78赋值给num[i](即num[1]),[注意此时num[6]的指还是78没变!!!,i=1,j=6].

     数组变为

0 1 2 3 4 5 6
5 78 45 134 23 54 78

   现在 i = 1, j = 6, temp = 98, 98的值不在数组中但没消失.

 

然后i++,i = 2,现在从左边开始找比temp= 98 大的数,i加到3时,134符合,就把134赋值给num[j],然后j--;

现在的数组是:

0 1 2 3 4 5 6
5 78 45 134 23 54 134

    现在 i = 3, j = 5, temp = 98,此时一轮分解扔未结束!!(因为仍然有i < j)

 

现在从 j = 5 从右向左找比98小的数,54符合, num[i= 3]= 54, i++ (i= 4)

现在的数组是

0 1 2 3 4 5 6
5 78 45 54 23 54 134

   现在 i= 4 j = 5 

 

然后从 i = 4 找比temp大的数,23不符合则i++; i = j = 5;然后num[i] = temp = 98;至此第二轮分解完毕.

现在成了

0 1 2 3 4 5 6
5 78 45 54 23 98 134

     现在分成了左边的num[1]~ num[4] 比98小,右边比98 大,然后就排num[1]~num[4],右边就一个数不用排了.

 

3 代码

    经过上面的实例分析,以下为代码

    

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 /*   快速排序 QuickSort
 5  *   @Date: 2014-08-05
 6  *   @Author: cjr
 7  */
 8 
 9 int quicksort(int *num,int l,int r)
10 {
11     int i,j,temp,k;
12     if(l < r)
13     {
14      i = l,j = r,temp = num[l];
15     while(i < j)
16     {
17         while(num[j] > temp && j > i)   // 从右往左找比哨点小的值
18             j--;
19         if(i < j)
20             num[i++] = num[j];
21         while(num[i] < temp && i < j)   //  从左往右找比哨点大的值
22             i++;
23         if(i < j)
24             num[j--] = num[i];
25     }
26     printf("%d ",i);
27     num[i] = temp;
28     for(k = l; k <= r; k++)
29             printf("%d ",num[k]);
30     printf("\n");
31     quicksort(num,l,i-1);
32     quicksort(num,i+1,r);
33     }
34     return 0;
35 }
36 
37 int main()
38 {
39     int num[7] = {5,98,45,134,23,54,78};
40     int i;
41     quicksort(num,0,6);
42     for(i = 0; i < 7; i++)
43         printf("%d ",num[i]);
44     return 0;
45 }

4 总结反思

     自己写的时候犯的第一个错误:每次找到合适的数时只是进行简单的赋值操作而不是互换,本人依旧像其他排序一样进行了交换.

     需要注意理解何时才算是分解完成,不是把while(i < j)中走了一遍而是走到 i = j,走一遍仍可能有 i  < j 本例就是如此.

     本例中的代码体现的分治的思想还不是很明显;快排还有另外的一种写法,可参考一下文章:

     http://www.cnblogs.com/foreverking/articles/2234225.html 

     http://blog.csdn.net/morewindows/article/details/6684558

 

     

posted @ 2014-08-07 08:40  Programmer-cjr  阅读(268)  评论(0编辑  收藏  举报