快速排序的三种实现方法
文章目錄
- 1.快速排序的思想
- 2.基本實(shí)現(xiàn)
- 2.1第一種排序
- 2.2第二種排序
- 2.3第三種排序(挖坑法)
- 2.4代碼測試
- 3.代碼優(yōu)化
- 4.快速排序小結(jié)
1.快速排序的思想
快速排序的過程可以分為以下幾步:
2.基本實(shí)現(xiàn)
2.1第一種排序
首先找基準(zhǔn)值,然后cur標(biāo)記left,prev標(biāo)記cur-1,然后cur遍歷,分為兩個(gè)階段:第一個(gè)是cur沒找到比基準(zhǔn)值大的,prev和cur一直緊挨著。第二種是找到了,然后cur++,繼續(xù)遍歷,找到比基準(zhǔn)值小的,然后才讓++prev,此時(shí)prev和cur換一下位置,cur繼續(xù)遍歷,循環(huán)結(jié)束,最后right-1和++prev位置交換,放好基準(zhǔn)值的位置。
int Partion1(int* array, int left, int right) {int cur = left;int prev = cur - 1;int key = array[right - 1];while (cur < right){if (array[cur] < key && ++prev != cur)Swap(&array[cur], &array[prev]);cur++;}if (++prev != (right - 1))Swap(&array[prev], &array[right - 1]);return prev; }2.2第二種排序
先標(biāo)記基準(zhǔn)值(這里先取最后一個(gè)元素為基準(zhǔn)值,記錄起來),之后定義兩個(gè)指針,然后前后遍歷,找到比基準(zhǔn)值大的或者小的的元素的位置,然后進(jìn)行標(biāo)記,標(biāo)記成功后進(jìn)行交換,最后添加一個(gè)循環(huán),此時(shí)的begin和end是在一個(gè)位置的,你要將begin和right-1(其實(shí)就是基準(zhǔn)值的位置)位置的元素交換。
int Partion2(int* array, int left, int right) {int begin = left;int end = right - 1;//設(shè)置基準(zhǔn)值,取數(shù)組最右側(cè)的元素int key = array[end];while (begin < end){//尋找大于基準(zhǔn)值的數(shù)while (begin < end && array[begin] <= key)begin++;while (begin < end && array[end] >= key)end--;if (begin < end)Swap(&array[begin], &array[end]);}//這里將基準(zhǔn)值和begin(end)交換if (begin != right - 1)Swap(&array[begin], &array[right - 1]);return begin;//此時(shí)應(yīng)該返回begin,key只是值(這里是下標(biāo)操作) }2.3第三種排序(挖坑法)
這種還是先標(biāo)記基準(zhǔn)值,依舊是begin和end兩個(gè)指針,然后begin先找比基準(zhǔn)值大的元素,將其填寫到right-1的位置上,此時(shí)的begin的位置就是一個(gè)坑,然后end從后開始遍歷,找到比基準(zhǔn)值小的元素將其填寫到begin的位置,end的位置就是一個(gè)坑,循環(huán)以上操作,結(jié)束后就將標(biāo)記起來的基準(zhǔn)值填寫到begin(end)的位置。
int Partion3(int* array, int left, int right) {int begin = left;int end = right - 1;int key = array[end];//基準(zhǔn)值while (begin < end){//從頭開始大于key的值的位置while (begin < end && array[begin] <= key)begin++;//將這個(gè)值填到基準(zhǔn)值的位置if (begin < end){array[end--] = array[begin];//這里的end一定要往前走一步}//從尾開始大于key的值得位置while (begin < end && array[end] >= key)end--;//填坑在begin的位置if (begin < end){array[begin++] = array[end];}}//將基準(zhǔn)值填寫到begin的位置(此時(shí)的begin和end的位置是一樣的)array[begin] = key;return begin; }2.4代碼測試
void Swap(int *left, int* right) {int temp = *left;*left = *right;*right = temp; }void QuickSort(int* array, int left, int right) {//right-left>1說明中間必有元素if (right - left > 1){int div = Partion3(array, left, right);QuickSort(array, left, div);QuickSort(array, div + 1, right);} }void Print(int* array, int size) {for (int i = 0; i < size; i++){printf("%d ", array[i]);}printf("\n"); }#include "QuickSort.h"int main() {int array[] = { 9, 3, 8, 6, 7, 2, 1, 0, 4, 5 };Print(array, sizeof(array) / sizeof(array[0]));QuickSort(array, 0, sizeof(array) / sizeof(array[0]));Print(array, sizeof(array) / sizeof(array[0]));return 0; }3.代碼優(yōu)化
當(dāng)最右邊的數(shù)字是最大或者最小時(shí),此時(shí)我們對取基準(zhǔn)值進(jìn)行優(yōu)化,保證不至于偏差非常大。
//三值取中法 int GetIndexOfMid(int* array, int left, int right) {int mid = left + ((right - left) >> 1);if (array[left] > array[right - 1]){if (array[mid] > array[left])return left;else if (array[mid] < array[right - 1])return right;elsereturn mid;}else{if (array[mid] < array[left])return left;else if (array[mid] > array[right - 1])return right;elsereturn mid;} }注意:三值取中法返回的是下標(biāo)。
此時(shí)就需要優(yōu)化一下里面的三種排序里面的代碼。
int ret = GetIndexOfMid(array, left, right);int key = array[ret];//基準(zhǔn)值//將那個(gè)放到最后面,就可以和之前的代碼連接起來Swap(&array[ret], &array[right - 1]);4.快速排序小結(jié)
-
這個(gè)快排的時(shí)間復(fù)雜度為O(nlogn),空間復(fù)雜度為O(logn),快速排序是一個(gè)不穩(wěn)定的排序算法。
-
若對于一系列有序(不論是遞增有序還是遞減有序)的數(shù)據(jù)進(jìn)行快排時(shí),快排就會(huì)退化,相當(dāng)于冒泡排序,解決方法主要有兩種,一種是隨機(jī)找一個(gè)基準(zhǔn),另外一種是三位數(shù)取中的方法。
-
需要注意的是對于單鏈表中的數(shù)據(jù)不能用快速排序進(jìn)行,由于單鏈表只有一個(gè)后繼指針而沒有前驅(qū)指針,因此單鏈表是不能用快排進(jìn)行排序的。
-
當(dāng)數(shù)據(jù)量比較大的時(shí)候不適合用快速排序,此時(shí)堆排序?qū)@些數(shù)據(jù)進(jìn)行排序更為合適。
總結(jié)
以上是生活随笔為你收集整理的快速排序的三种实现方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux】Linux中vim的使用
- 下一篇: 程序编译连接原理