快速排序
官方說法:快速排序(Quicksort)是對冒泡排序的一種改進。快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然后再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
通俗來說,就是不斷的挖坑和填坑
- 1、其實就是先選擇一個基准數,然后這個基准數我們保存為x,那它所在的位置就是一個空出來的坑。
- 2、我們從右向左迭代,如果遇到比基准數小的數,就將其填到上次挖的坑中,然后它自己在的這個地方就變成了一個新的坑。
- 3、然后再從左向右迭代,找比基准數大的數,將其填到上次挖的坑中,然后它所在的地方就變成了新的坑。
- 4、最后要將基准數填入最后的坑中,然后將基准數所在的位置返回,方便下次調用時候使用
//挖坑填數
int adjustArray(int s[],int l, int r) //傳入數組和左右的下標
{
int i = l,j = r; //分別表示左半邊的下標和右半邊的下標
int x = s[l]; //默認最左邊的數就是挖的第一個坑
while(i < j) //要保證數組中元素最少有兩個
{
//從右向左迭代,找比基准數小的
while(s[j] >= x && i < j)
j--;
if(i < j) //找到了比基准數小的
{
s[i] = s[j]; //將其填到原來挖的坑的地方上,現在j處又形成了一個新的坑
i++; //i處填入了新的數,所以i++,然后從左往右去找,在左半邊比基准數大的數
}
//從左向右迭代去找比基准數大的
while(s[i] < x && i < j)
i++;
if(i < j)
{
s[j] = s[i];
j--;
}
}
//退出時,要把坑用基准數填回去
s[i] = x;
return i; //返回調整后基准數的位置,方便下一次遞歸調用的時候
}
就這樣將原來的數組以返回的基准數所在的位置為中心,分成了兩個數組(理論上兩個,但在內存中還是在一起挨着的),然后分別對新的兩個數組遞歸進行挖坑和填坑的操作,當先前指示數組左右兩邊的下標的變量左邊的大於或等於(一般都是等於)右邊的時候(即數組已經被分的不能被分了),這時候原數組就變成有序的了,因為按照上面的思路,所有左邊的都小於右邊的,那既然數組都被分的變成一個數一個小數組那就是左邊的數比右邊的數小,即有序,排序完成!
void quick_sort(int s[], int l, int r)
{
if(l < r)
{
int i = adjustArray(s,l,r);
//不能將上次的基准數拉入新的兩個數組中的任何一個,因為其所在的位置已經是最終對的位置了,它左邊的數都比它小,右邊的都比它大
quick_sort(s,l,i-1);
quick_sort(s,i+1,r);
}
}