数据结构与算法分析 - 快速排序

大二其实已经学习过了快排,但是现在基本上已经忘记了快排的细节和具体实现。现在为了准备可能的面试,重新复习一下快速排序。温故知新,古人诚不欺我。主要以《算法导论》为教材。

《算法导论》这本书在介绍算法时,首先给出算法的描述,也就是伪码,然后就是算法的正确性证明和优化。本文首先也是给出算法的伪码,至于正确性的证明,还是看自己能否胜任。

快排的大致框架

1
2
3
4
5
QUICKSORT(A,p,r)
if  p < r
     then q = PARTITION(A,p,r)
     QUICKSORT(A,p,q-1)
     QUICKSORT(A,q+1,r)

 了解快排,就会知道快排的核心思想就是每次实现这样一个数组:选定数组中某一个值,确保该值左边的元素都比它小,右边的元素都比它大。这样虽然不能保证改值左边和右边的元素一定是有序的,但是一定能够保证该值在排序后的数组中的相对位置不会改变。比如说A[i]此时在第i个位置,当整个数组排完序之后,A[i]一定还是在i。这样也就知道为什么上面代码中递归的时候不用包含q的值,因为它的位置已经确定了。

经过以上的分析,就不难在实际编码中写出快排的大致框架了。

快排的分治

显而易见,快排采用的是分治的思想。每次将一个任务分为两个或者多个部分来解决。但是如何分治其实才是快排的难点和重点。

如果要保证每次排序后的数组都满足左边的都比指定元素要小,右边则都要大,必须要选择一个参照值作为比较的对象,这个参考值就叫做主元。确定了组员,就开始遍历比较。

假设每次选取的都是最右边的元素作为主元,兴义博爱医院那么就可以从左到右来比较和确定元素的位置。具体见下面的伪码。

1
2
3
4
5
6
7
8
9
PARTITION(A,p,r)
x = A[r]
i = p - 1
for  j : p to r
     do  if  A[j] < x
             then i = i + 1
             exchange(A[i],A[j])
exchange(A[i+1],A[r])
return  i+1<br><br><br><br><br>

大致的策略就是尽量让比主元小的元素排在前面。就这样,很神奇的整个数组就排完序了。

C代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*************************************************************************
     > File Name: myfiles/C/sort/quicksort.c
     > Author: ma6174
     > Mail: ma6174@163.com
     > Created Time: 2014年10月06日 星期一 11时38分28秒
  ************************************************************************/
 
#include<stdio.h>
#define maxn 100
int  A[maxn];
int  n;
/* 输入数据 */
void  read()
{
     printf ( "input the num:\n" );
     scanf ( "%d" ,&n);
     int  i;
     for (i = 0; i < n; i++) {
         scanf ( "%d" ,&A[i]);
     }
}
/* 分治 */
int  partition( int  A[], int  p, int  r)
{
     int  key = A[r];
     int  i = p - 1;
     int  j;
     for (j = p; j < r; j++) {
         if (A[j] < key) { /* 目前为止,没有等于好也可以正确执行,但是我不确定要不要等号*/
             i++;
             int  temp = A[i];
             A[i] = A[j];
             A[j] = temp;
         }
     }
     int  temp = A[i+1];
     A[i+1] = key;
     A[r] = temp;
     return  i+1;
}
/* 快排 */
void  quick_sort( int  A[], int  p, int  r)
{
     if (p < r) {
         int  q = partition(A,p,r);
         quick_sort(A,p,q-1);
         quick_sort(A,q+1,r);
     }
}
/* 输出 */
void  write()
{
     printf ( "the sorted array:\n" );
     int  i;
     for (i = 0; i < n; i++) {
         printf ( "%d " ,A[i]);
     }
     printf ( "\n" );
}
int  main()
{
     read();
     quick_sort(A,0,n-1);
     write();
}<br><br><br><br><br><br><br><br><br>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值