1. 程式人生 > >演算法設計:兩種快速排序程式碼實現

演算法設計:兩種快速排序程式碼實現

快速排序是一種高效且使用廣泛的排序演算法,在很多語言的標準庫中自帶的排序都是快速排序,所以我們也有必要了解快排的原理以及其實現方法。

快排的大致思想

快速排序實現的重點在於陣列的拆分,通常我們將陣列的第一個元素定義為比較元素,然後將陣列中小於比較元素的數放到左邊,將大於比較元素的放到右邊,

這樣我們就將陣列拆分成了左右兩部分:小於比較元素的陣列;大於比較元素的陣列。我們再對這兩個陣列進行同樣的拆分,直到拆分到不能再拆分,陣列就自然而然地以升序排列了。

 

不難看出,拆分演算法是整個快速排序中的核心,快速排序擁有非常多的拆分方式,在本篇文章中我們介紹其中的兩種,我個人將它稱作:單指標遍歷法與雙指標遍歷法(在下文中用英文單詞split和partition稱呼)

 

split演算法解析

split演算法使用一個單向的指標來對陣列進行遍歷,首先將陣列首元素設定為比較元素,然後將第二個開始的元素依次與比較元素比較,如果大於比較元素則跳過,如果小於比較元素,則將其與前面較大的元素進行交換,將陣列中所有元素交換完畢後,再將比較元素放到中間位置。

 

 

split演算法實現(c):

 1 //劃分陣列的函式
 2 int split(int a[], int low, int high)
 3 {
 4     int i = low;    //i指向比較元素的期望位置
 5     int x = a[i];    //
將該陣列第一個元素設定為比較元素 6 //從陣列的第二個元素起開始遍歷,若找到的元素大於比較元素,則跳過 7 for(int j = low+1;j<=high;j++) 8 //若找到了小於比較元素的數,則將其與前面較大的數進行交換 9 if (a[j] <= x) 10 { 11 i++; 12 swap(a[i], a[j]); 13 } 14 swap(a[low], a[i]); //將比較元素交換到期望位置 15 return i;
16 }

split演算法實現(java):

 1 //劃分陣列
 2     public static int split(int a[], int low, int high)
 3     {
 4         int i = low;    //i指向比較元素的期望位置
 5         int x = a[low];    //將該組的第一個元素作為比較元素
 6         //從第二個元素開始,若當前元素大於比較元素,將其跳過
 7         for(int j = low+1; j <= high; j++)
 8             //若找到了小於比較元素的元素,將其與前面較大的元素進行交換
 9             if(a[j] <= x)
10             {
11                 i++;
12                 if(i != j)
13                     swap(a, i, j);
14                 
15             }
16         swap(a, i, low);     //將比較元素交換到正確的位置上
17         return i;    //返回比較元素的位置
18     }

partition演算法解析

partition演算法使用頭尾兩個方向相反的指標進行遍歷,先將陣列第一個元素設定為比較元素,頭指標從左至右找到第一個大於比較元素的數,尾指標從右至左找到第一個小於比較元素的數,全部交換完畢後將比較元素放到中間位置。

 

partition演算法實現(c):

 1 int partition(int a[], int low, int high)
 2 {
 3     int x = a[low];    //將該陣列第一個元素設定為比較元素
 4     int i = low;    //指向陣列頭的指標
 5     int j = high;    //指向陣列尾的指標
 6     while (i < j)
 7     {
 8         while (i < j && a[j] >= x)
 9             j--;    //從右至左找到第一個小於比較元素的數
10         while (i < j && a[i] <= x)
11             i++;    //從左至右找到第一個大於比較元素的數
12         /*需要注意的是,這裡的j--與i++的順序不可以調換!
13           如果調換了順序,i會走過頭,以至於將後面較大的元素交換到陣列開頭*/
14 
15         //將大數與小數交換
16         if (i != j)
17             swap(a[i], a[j]);
18     }
19     swap(a[low], a[i]);    //將比較元素交換到期望位置
20     return i;    //返回比較元素的位置
21 }

partition演算法實現(java):

 1     //劃分陣列
 2     public static int partition(int a[], int low, int high)
 3     {
 4         int x = a[low];    //將該陣列第一個元素設定為比較元素
 5         int i=low;
 6         int j=high;
 7         while(i < j)
 8         {
 9             while(i<j && a[i] <= x)
10                 i++;
11             while(i<j && a[j] >= x)
12                 j--;
13             
14             
15             if(i!=j)
16                 swap(a, i, j);
17         }
18         swap(a, j, low);
19         return j;
20     }

兩種演算法的完整程式碼和實際演示

split演算法(c):

 1 #include<stdio.h>
 2 
 3 void swap(int &a, int &b)
 4 {
 5     int t = a;
 6     a = b;
 7     b = t;
 8 }
 9 
10 //劃分陣列的函式
11 int split(int a[], int low, int high)
12 {
13     int i = low;    //i指向比較元素的期望位置
14     int x = a[i];    //將該陣列第一個元素設定為比較元素
15     //從陣列的第二個元素起開始遍歷,若找到的元素大於比較元素,則跳過
16     for(int j = low+1;j<=high;j++)
17         //若找到了小於比較元素的數,則將其與前面較大的數進行交換
18         if (a[j] <= x)
19         {
20             i++;
21             swap(a[i], a[j]);
22         }
23     swap(a[low], a[i]);    //將比較元素交換到期望位置
24     return i;
25 }
26 
27 //快速排序
28 void quicksort(int a[], int low, int high)
29 {
30     if (low < high)
31     {
32         int i = split(a, low, high);    //劃分陣列並獲得比較元素位置
33         quicksort(a, low, i - 1);    //對比較元素左邊進行排序
34         quicksort(a, i + 1, high);    //對比較元素右邊進行排序
35     }
36 }
37 
38 int main()
39 {
40     int a[] = { 5,7,1,6,4,8,3,2 };
41     int length = sizeof(a) / sizeof(a[0]);
42     quicksort(a, 0, length - 1);
43     for (int i = 0; i < length; i++)
44         printf("%d ", a[i]);
45     printf("\n");
46     return 0;
47 }

split演算法(java):

 1 //快速排序split實現方法
 2 public class T1 {
 3     public static void main(String args[])
 4     {
 5         int a[] = {5,7,1,6,4,8,3,2};
 6         quickSort(a, 0, a.length-1);
 7         for(int i=0;i<a.length;i++)
 8             System.out.print(a[i] + " ");
 9         System.out.println();
10     }
11     
12     //交換方法
13     public static void swap(int a[], int i, int j)
14     {
15         int t = a[i];
16         a[i] = a[j];
17         a[j] = t;
18     }
19     
20     //劃分陣列
21     public static int split(int a[], int low, int high)
22     {
23         int i = low;    //i指向比較元素的期望位置
24         int x = a[low];    //將該組的第一個元素作為比較元素
25         //從第二個元素開始,若當前元素大於比較元素,將其跳過
26         for(int j = low+1; j <= high; j++)
27             //若找到了小於比較元素的元素,將其與前面較大的元素進行交換
28             if(a[j] <= x)
29             {
30                 i++;
31                 if(i != j)
32                     swap(a, i, j);
33                 
34             }
35         swap(a, i, low);     //將比較元素交換到正確的位置上
36         return i;    //返回比較元素的位置
37     }
38     
39     public static void quickSort(int a[], int low, int high)
40     {
41         if(low < high)
42         {
43             int i = split(a, low, high);    //劃分並獲取比較元素的位置
44             quickSort(a, low, i-1);     //對比較元素左邊的陣列進行排序
45             quickSort(a, i+1, high);     //對比較元素右邊的數字進行排序
46         }
47     }
48 }

 

partition演算法(c):

 1 #include<stdio.h>
 2 
 3 //交換函式
 4 void swap(int &a, int &b)
 5 {
 6     int t = a;
 7     a = b;
 8     b = t;
 9 }
10 
11 int partition(int a[], int low, int high)
12 {
13     int x = a[low];    //將該陣列第一個元素設定為比較元素
14     int i = low;    //指向陣列頭的指標
15     int j = high;    //指向陣列尾的指標
16     while (i < j)
17     {
18         while (i < j && a[j] >= x)
19             j--;    //從右至左找到第一個小於比較元素的數
20         while (i < j && a[i] <= x)
21             i++;    //從左至右找到第一個大於比較元素的數
22         /*需要注意的是,這裡的j--與i++的順序不可以調換!
23           如果調換了順序,i會走過頭,以至於將後面較大的元素交換到陣列開頭*/
24 
25         //將大數與小數交換
26         if (i != j)
27             swap(a[i], a[j]);
28     }
29     swap(a[low], a[i]);    //將比較元素交換到期望位置
30     return i;    //返回比較元素的位置
31 }
32 
33 void quicksort(int a[], int low, int high)
34 {
35     if (low < high)
36     {
37         int i = partition(a, low, high);    //劃分陣列並獲取比較元素的位置
38         quicksort(a, low, i - 1);    //對比較元素左邊進行排序
39         quicksort(a, i + 1, high);    //對比較元素右邊進行排序
40     }
41 }
42 
43 int main()
44 {
45     int a[] = { 5,7,1,6,4,8,3,2 };
46     int length = sizeof(a) / sizeof(a[0]);
47     quicksort(a, 0, length - 1);
48     for (int i = 0; i < length; i++)
49         printf("%d ", a[i]);
50     printf("\n");
51     return 0;
52 }

 

partition演算法(java):

 1 //快速排序partition實現方法
 2 public class T2 {
 3     public static void main(String args[])
 4     {
 5         int a[] = {5,7,1,6,4,8,3,2};
 6         quicksort(a, 0, a.length-1);
 7         for(int i=0;i<a.length;i++)
 8             System.out.print(a[i] + " ");
 9         System.out.println();
10     }
11     
12     public static void swap(int a[], int i, int j)
13     {
14         int t = a[i];
15         a[i] = a[j];
16         a[j] = t;
17     }
18     
19     //劃分陣列
20     public static int partition(int a[], int low, int high)
21     {
22         int x = a[low];    //將該陣列第一個元素設定為比較元素
23         int i=low;
24         int j=high;
25         while(i < j)
26         {
27             while(i<j && a[j] >= x)
28                 j--;     //從右至左找到第一個小於比較元素的數
29             while(i<j && a[i] <= x)
30                 i++;     //從左至右找到第一個大於比較元素的數
31             /*需要注意的是,這裡的j--與i++的順序不可以調換!
32              *如果調換了順序,i會走過頭,以至於將後面較大的元素交換到陣列開頭*/
33             
34             //將大數與小數交換
35             if(i!=j)
36                 swap(a, i, j);
37         }
38         swap(a, i, low);    //將比較元素交換到期望位置
39         return i;     //返回比較元素的位置
40     }
41     
42     public static void quicksort(int a[], int low, int high)
43     {
44         if(low < high)
45         {
46             int i = partition(a, low, high);    //劃分陣列並獲取比較元素的位置
47             quicksort(a, low, i-1);     //對比較元素左邊進行排序
48             quicksort(a, i+1, high);     //對比較元素右邊進行排序
49         }
50     }
51 }