演算法設計:兩種快速排序程式碼實現
阿新 • • 發佈:2018-11-23
快速排序是一種高效且使用廣泛的排序演算法,在很多語言的標準庫中自帶的排序都是快速排序,所以我們也有必要了解快排的原理以及其實現方法。
快排的大致思想
快速排序實現的重點在於陣列的拆分,通常我們將陣列的第一個元素定義為比較元素,然後將陣列中小於比較元素的數放到左邊,將大於比較元素的放到右邊,
這樣我們就將陣列拆分成了左右兩部分:小於比較元素的陣列;大於比較元素的陣列。我們再對這兩個陣列進行同樣的拆分,直到拆分到不能再拆分,陣列就自然而然地以升序排列了。
不難看出,拆分演算法是整個快速排序中的核心,快速排序擁有非常多的拆分方式,在本篇文章中我們介紹其中的兩種,我個人將它稱作:單指標遍歷法與雙指標遍歷法(在下文中用英文單詞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 }