基礎知識見:
《建議先閱讀基礎知識,並自己手推一遍》
演算法原理:
第一步:取陣列最後乙個數作為num,將陣列中的 <= num的數放在陣列的左邊,> num的數放在陣列的右邊,這是可以理解為分成了兩個陣列;
第二步:然後將 <= num的部分當成乙個陣列,繼續第一步;> num的部分同理;
第三步:若陣列的大小 < 2,則結束。
流程圖:
以下列陣列為例子:
圖中,可以看到每次將陣列partition過程中,都是將左陣列中最後乙個數排除掉(因為我們的基數是選擇陣列最後乙個數,而且partition是將陣列分為<=和》部分)。若不將partition後左陣列最後乙個數(這個數必定是基數)排除掉,那麼遞迴將無限進行。
**實現
int partition(std::vector&arr, int left, int right, int num)
} return pos;
}void classicquicksort(std::vector&arr, int left, int right)
int num = arr[right];
int pos = partition(arr, left, right, num);
classicquicksort(arr, left, pos - 1);
classicquicksort(arr, pos + 1, right);
}
經典快排中的技術選擇是陣列最後乙個數,而隨機快排基數的選擇是隨機的,其實也就是partition中num的選擇,所以將陣列的最後乙個數與隨機數交換位置。
**如下:
void randomquicksort(std::vector&arr, int left, int right)
srand(unsigned(time(0)));
int arraysize = right - left + 1;
int randomindex = rand() % arraysize + left;
int num = arr[randomindex];
int temp = arr[right];
arr[right] = num;
arr[randomindex] = temp;
int pos = partition(arr, left, right, num);
randomquicksort(arr, left, pos - 1);
randomquicksort(arr, pos + 1, right);
}
演算法原理第一步:取陣列最後乙個數作為num,將陣列中的 < num的數放在陣列的左邊,=num的數放在陣列中間,> num的數放在陣列的右邊,這是可以理解為分成了3個陣列;
第二步:然後將 num的部分同理;
第三步:若陣列的大小 < 2,則結束。
流程圖:
以下列陣列為例子:
**實現
std::vectorpartition1(std::vector&arr, int left, int right, int num)
else if (arr[i] == num)
else
}result[0] = posleft;
result[1] = posright;
return result;
}void dutchflagquicksort(std::vector&arr, int left, int right)
int num = arr[right];
std::vectorpos = partition1(arr, left, right, num);
dutchflagquicksort(arr, left, pos[0]);
dutchflagquicksort(arr, pos[1], right);
}
快排最好的時間複雜度為o(n*logn),最壞的時間複雜度為o(n^2);空間複雜度為o(logn),最差空間複雜度為o(n)。同時快排是個不穩定的排序,那麼穩定性的概念是什麼?
表示兩個值相同的元素在排序前後是否有位置變化所以從上述流程圖可以明顯看出,相同兩個值的相對前後位置是會發生變化的,所以快排不穩定。
那為什麼快排的空間複雜度為o(logn)?
空間浪費在記錄邊界處。
快排其實很好理解,自己畫個圖,完整走個流程就ok了。**實現其實只要主要一些小細節,比如說經典快排中要主要避免無限遞迴,partition中的迴圈引數判斷等。
但是工程上不能用遞迴函式。所以工程上實現快排,不用遞迴。
利用荷蘭國旗問題改進經典快排和隨機快排
每次取陣列中最後乙個值,依照這個值把陣列分為兩份,小於的在左邊,大於的在右邊。再依次按照這樣的思想進行操作。ps 荷蘭國旗問題可以看另一篇部落格 荷蘭國旗問題把陣列是分為三個部分的,小於 等於 大於這三個部分。按照這樣的思想,等於部分就不需要進行再次進行排序,這樣就能減少很大一部分的開銷。改進之後的...
演算法 快速排序 經典快排 隨機快排
經典快排的思路是選取陣列的最後乙個數 x,按照問題一的思路把整個陣列劃分成小於等於 x 大於 x兩個部分,將 x 和 大於 x 部分陣列的第乙個元素交換位置。此時整個陣列劃分成小於等於 x x 大於 x三個部分,也就是這一次排序將 x 值排好位置。再分別對小於等於 x和大於 x中的陣列遞迴劃分,直到...
快排和堆排
一 快速排序 最常用的排序演算法,速度通常也是最快的。時間複雜度 o nlogn 最壞 o n 2 空間複雜度 o nlgn 不穩定 比如 5 3 3 4 3 8 9 10 11 這個序列,在中樞元素5和3交換就會把元素3的穩定性打亂 實現原理 快排主要是通過選擇乙個關鍵值作為基準值。比基準值小的都...