排序算法-------快速排序算法

快速排序算法Quicksort

  排序算法中最难的当属快速排序算法,但是快速排序算法的思想可以作为以后编程的一种想法,其基本思想是分治思想,简单的说就是分而治之,讲一个大问题分解为有限个问题,分解为的问题还可以继续向下分解,成为更简单的问题,我们将所有的小问题解决后,大的问题自然也就解决了。

  首先在解决快速排序之前,先要解决的一个问题是,我们选择一个标准值,大于这个数的,将他放在标准值的右侧,小于这个数的放在标准值的左侧,这样我们就将序列的排序问题划分成了两个小序列的快速排序问题。

首要问题是我们将序列以标准值划分的问题,左侧小于标准值的,右侧大于标准值,再将标准值插入其中的序列,即Split算法。

算法的基本思想:

  首先我们取第一个位置的元素作为标准值(取一个标记i),在以第二个值(取一个标记j),这样我们进行比较,假设数值并没有标准值大的话,i向前移动一位,(一般在数值比较的开头,看i和j是否相等,不相等就交换i和j的位置上的值,j++),如果值大于标准值,j++,直到遇到比标准值小得数字,交换i和j位置的数值,直到j取到最后一个数为止,此时i位置上的数字以及i之前的数字都比标准值要小,i后面的数字都比标准值要大,这是交换第一个数字和i位置的数字,就实现了在标准值的左侧都比标准值小的序列,而在标准值的右侧,所有的值都比标准值要大。

实例演示:

4,3,7,9,2,5,6

(1)第一步,取第一个值作为标准值,并且以low作为数字的标记,同时给出标记i,j=i+1,将j标记i后面的数,i比较j位置上的值与标准值的大小,如果比标准值小,i++,进行判断i是否等于将,如不等,交换i和j位置的值,否则不动,j++;;如果比标准值大,则j++;进行判断i是否等于将,如不等,交换i和j位置的值,否则不动;

 i                             i

4,3,7,9,2,5,6  -------------------------------结果  4,3,7,9,2,5,6               操作:1、比较(小于)  2、i++,判断i==j,等于,则j++

low  j                       low       j

(2)重复(1)的操作,得以下结果

       i                         i

4,3,7,9,2,5,6  -------------------------------结果  4,3,7,9,2,5,6               操作:1、比较(大于)  2、直接j++

low       j                     low           j

 (3)结果如下

       i                         i

4,3,7,9,2,5,6  -------------------------------结果  4,3,7,9,2,5,6               操作:1、比较(大于)  2、直接j++

low          j                   low                j

(4)结果如下

       i                               i

4,3,7,9,2,5,6  -------------------------------结果  4,3,2,9,7,5,6             操作:1、比较(小于)  2、i++,判断i==j(不等)交换i和j上的值

low             j                 low                  j

(5)结果如下

             i                         i

4,3,2,9,7,5,6  -------------------------------结果  4,3,2,9,7,5,6               操作:1、比较(大于)  2、直接j++

low               j                   low                      j

5)结果如下

             i                         i

4,3,2,9,7,5,6  -------------------------------结果  2,3,4,9,7,5,6        操作:1、比较(大于)  2、最后一个元素审查完,交换i和low上的值

low                     j                  low                             j

最终经过split算法后的结果为 2,3,4,9,7,5,6 ,在之前的都比4小,在4后面的都比4要大,算法完成

算法中的要点:i和j的比较是为了在开始时不存在比标准值大的时候防止交换;

代码如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 int split(int *a, int low, int high);
 4 int main() {
 5     int a[7] = { 4,3,7,9,2,5,6 };
 6     for (int i = 0; i < 7; i++)    {
 7         if (i != 6) {
 8             printf("%d,", a[i]);
 9         }
10         else {
11             printf("%d\n", a[i]);
12         }
13     }
14     int m = split(a, 0, 7);    
15     for (int i = 0; i < 7; i++) {
16         if (i != 6) {
17             printf("%d,", a[i]);
18         }
19         else {
20             printf("%d\n", a[i]);
21         }
22     }
23     system("pause");
24 }
25 
26 int split(int *a, int low, int high) {
27     int i = 0;
28     int x = a[low];
29     int temp;
30     for (int j = i + 1; j < high; j++) {
31         if (a[j] < x) {
32             i++;
33             if (i != j) {
34                 temp = a[i];
35                 a[i] = a[j];
36                 a[j] = temp;
37             }
38         }
39     }
40     temp = a[i];
41     a[i] = a[low];
42     a[low] = temp;
43     return i;
44 }

代码的结果:

上面的代码就是快速排序算法的核心步骤,下面我们来聊聊快速排序,我们使用一次split就会分出来两个部分,然后再对两个部分再次使用split算法,则又会向下分解,分解就调用quicksort算法,相当于是递归的过程,那么我们关心的就是这个排序的过程什么时候停下来。

当一个序列存在两个及两个以上的值的时候,都可以以其中一个作为标准值,另一个一定在左或者右,依旧可以调用quicksort算法,所以当一个序列中只有一个值的时候,递归就停止了,显示在序列中就是low=high,所以只要做判断low<high,递归算法继续

下面是Quicksort的代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 int split(int *a, int low, int high);
 4 int Quicksort(int *a, int low, int high);
 5 int main() {
 6     int a[7] = { 4,3,7,9,2,5,6 };
 7     for (int i = 0; i < 7; i++)    {
 8         if (i != 6) {
 9             printf("%d,", a[i]);
10         }
11         else {
12             printf("%d\n", a[i]);
13         }
14     }
15     Quicksort(a, 0, 6);    
16     for (int i = 0; i < 7; i++) {
17         if (i != 6) {
18             printf("%d,", a[i]);
19         }
20         else {
21             printf("%d\n", a[i]);
22         }
23     }
24     system("pause");
25 }
26 
27 int split(int *a, int low, int high) {
28     int i = low;
29     int x = a[low];
30     int temp;
31     int w;
32     for (int j = i + 1; j <= high; j++) {
33         if (a[j] < x) {
34             i++;
35             if (i != j) {
36                 temp = a[i];
37                 a[i] = a[j];
38                 a[j] = temp;
39             }
40         }
41     }
42     temp = a[i];
43     a[i] = a[low];
44     a[low] = temp;
45     w = i;
46     return w;
47 }
48 
49 int Quicksort(int *a, int low, int high) {
50     if (low < high) {
51         int m = split(a, low, high);
52         Quicksort(a, low, m - 1);
53         Quicksort(a, m+1, high);
54     }
55 }

代码运行结果如下:

Quicksort(a,0,6)

在split中j的取值范围:j<=high

Quicksort(a,0,7)

在split中j的取值范围:j<high

我在敲代码的发现第一种情况是成立,而第二种运行的结果并不对;

原因:是因为j的取值可以取到high,7是数组的上界取不到是必然,但是在循环中,可能会有一个小段high的值达不到7,(以5为例),j是可以取得到5的但是不等式中,要求j<high ,就会发生漏排的情况,所以Quicksort(a,0,7),j<high是错误的;

 

posted on 2017-08-14 01:15  waws520  阅读(800)  评论(0编辑  收藏  举报