/*
* quickSort.cpp(快速排序)
*
* Created on: 2012-4-21
* Author: jiyiqin
*
* 快速排序:
*
* 分治法:
* 和歸併排序一樣,快速排序也是基於分治思想的。
* 代價:
* 時間複雜度,期望為o(n log n), 但是最壞可能達到o(n^2)
* 空間複雜度,o(1),因為是基於交換元素的。
* 穩定性:
* depends
* 描述:
* 選擇一個partitioner,然後兩個指標從頭尾各自開始掃描
* 如果前面的比他大,停止,如果後面的比他小,停止,然後交換
*
* 迭代進行前半部分和後半部分(partitioner為分割點)
*/
#include <iostream>
using namespace std;
class QuickSort{
private:
/**
* 特別注意:
* 這種交換方式在交換同一個記憶體的元素時,
* 會導致記憶體中的元素變為0。
* */
void swap(int *a, int *b){
//*a = *a + *b;
//*b = *a - *b;
//*a = *a - *b;
int temp = *a;
*a = *b;
*b = temp;
}
public:
/**
* 選擇一個分割點,將a[low~high]分隔為兩部分
* 返回選擇的分割點最終所在位置
* 分隔點值:隨機化可以有效避免最壞時間複雜度
* 分隔點位置:最好在high處,在low處會麻煩一些,除非倒著掃描
*
* ###交換的思想:
*
* 這裡將小於x的元素和大於x的元素劃分開利用了
* 類似於(荷蘭國旗)的思想。
* 即用指標i指向第一個應該被交換到後面的元素(大於x)。
* 然後另外用j作為掃描一遍的掃描指標,如果掃描到小於
* 分割點x,則將其與a[i]交換(各取所需)。
*
* 這樣一遍下來,i一直向前(擴張),比x大的元素就會慢慢被
* (逼到)後面。掃描到a[high]的時候將其與第一個大於分割點
* 的元素a[i]交換即可將分隔點放到最終正確位置。
* 3,4,6,3,7,8,3,2,6,11,5
* */
int partition(int a[], int low, int high){
int pviot = a[high]; //最後一個元素作為分割點,否則會比較麻煩
int p = low; //指標p指向第一個不滿足小於pviot的元素
//掃描一遍
for(int j=low;j<high;j++){
if(a[j] < pviot){
swap(&a[p], &a[j]);
p++;
}
}
//將分割點與第一個不滿足小於pviot的元素交換
swap(&a[p], &a[high]);
return p;
}
/**
* 基於分治思想的快速排序
* */
void quickSort(int a[], int low, int high){
int p;
//注意if的條件
if(low < high){
p = partition(a, low, high); //find partition
quickSort(a, low, p-1);
quickSort(a, p+1, high);
}
}
};
int main(){
QuickSort qsort;
int a[] = {12,2,16,-3,0,-1,4,10,20,6,18};
//quickSort
qsort.quickSort(a, 0, 10);
for(int i=0;i<10;i++){
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}