算法設計:兩種快速排序代碼實現
快速排序是一種高效且使用廣泛的排序算法,在很多語言的標準庫中自帶的排序都是快速排序,所以我們也有必要了解快排的原理以及其實現方法。
快排的大致思想
快速排序實現的重點在於數組的拆分,通常我們將數組的第一個元素定義爲比較元素,然後將數組中小於比較元素的數放到左邊,將大於比較元素的放到右邊,
這樣我們就將數組拆分成了左右兩部分:小於比較元素的數組;大於比較元素的數組。我們再對這兩個數組進行同樣的拆分,直到拆分到不能再拆分,數組就自然而然地以升序排列了。
不難看出,拆分算法是整個快速排序中的核心,快速排序擁有非常多的拆分方式,在本篇文章中我們介紹其中的兩種,我個人將它稱作:單指針遍歷法與雙指針遍歷法(在下文中用英文單詞split和partition稱呼)
split算法解析
split算法使用一個單向的指針來對數組進行遍歷,首先將數組首元素設置爲比較元素,然後將第二個開始的元素依次與比較元素比較,如果大於比較元素則跳過,如果小於比較元素,則將其與前面較大的元素進行交換,將數組中所有元素交換完畢後,再將比較元素放到中間位置。
split算法實現(java):
//快速排序split實現方法
public class T1 {
public static void main(String args[])
{
int a[] = {5,7,1,6,4,8,3,2};
quickSort(a, 0, a.length-1);
for(int i=0;i<a.length;i++)
System.out.print(a[i] + " ");
System.out.println();
}
//交換方法
public static void swap(int a[], int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
//劃分數組
public static int split(int a[], int low, int high)
{
int i = low; //i指向比較元素的期望位置
int x = a[low]; //將該組的第一個元素作爲比較元素
//從第二個元素開始,若當前元素大於比較元素,將其跳過
for(int j = low+1; j <= high; j++)
//若找到了小於比較元素的元素,將其與前面較大的元素進行交換
if(a[j] <= x)
{
i++;
if(i != j)
swap(a, i, j);
}
swap(a, i, low); //將比較元素交換到正確的位置上
return i; //返回比較元素的位置
}
public static void quickSort(int a[], int low, int high)
{
if(low < high)
{
int i = split(a, low, high); //劃分並獲取比較元素的位置
quickSort(a, low, i-1); //對比較元素左邊的數組進行排序
quickSort(a, i+1, high); //對比較元素右邊的數字進行排序
}
}
}
partition算法解析
partition算法使用頭尾兩個方向相反的指針進行遍歷,先將數組第一個元素設置爲比較元素,頭指針從左至右找到第一個大於比較元素的數,尾指針從右至左找到第一個小於比較元素的數,全部交換完畢後將比較元素放到中間位置。
partition算法(java):
//快速排序partition實現方法
public class T2 {
public static void main(String args[])
{
int a[] = {5,7,1,6,4,8,3,2};
quicksort(a, 0, a.length-1);
for(int i=0;i<a.length;i++)
System.out.print(a[i] + " ");
System.out.println();
}
public static void swap(int a[], int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
//劃分數組
public static int partition(int a[], int low, int high)
{
int x = a[low]; //將該數組第一個元素設置爲比較元素
int i=low;
int j=high;
while(i < j)
{
while(i<j && a[j] >= x)
j--; //從右至左找到第一個小於比較元素的數
while(i<j && a[i] <= x)
i++; //從左至右找到第一個大於比較元素的數
/*需要注意的是,這裏的j--與i++的順序不可以調換!
*如果調換了順序,i會走過頭,以至於將後面較大的元素交換到數組開頭*/
//將大數與小數交換
if(i!=j)
swap(a, i, j);
}
swap(a, i, low); //將比較元素交換到期望位置
return i; //返回比較元素的位置
}
public static void quicksort(int a[], int low, int high)
{
if(low < high)
{
int i = partition(a, low, high); //劃分數組並獲取比較元素的位置
quicksort(a, low, i-1); //對比較元素左邊進行排序
quicksort(a, i+1, high); //對比較元素右邊進行排序
}
}
}