交換排序:快速排序(Quick Sort)

基本思想:

1)選擇一個(gè)基準(zhǔn)元素,通常選擇第一個(gè)元素或者最后一個(gè)元素。

2)通過一趟排序?qū)⒋判虻挠涗浄指畛瑟?dú)立的兩部分速妖,其中一部分記錄的元素值均比基準(zhǔn)元素值小沥匈;另一部分記錄的元素值均比基準(zhǔn)值大蔗喂。

3)此時(shí)基準(zhǔn)元素在其排好序后的正確位置

4)然后分別對這兩部分記錄用同樣的方法繼續(xù)進(jìn)行排序,直到整個(gè)序列有序高帖。

算法的實(shí)現(xiàn):

// 輸出數(shù)組內(nèi)容
void print(int array[], int length, int i) {
    printf("privot=%d:",i);
    for (int j = 0; j < length; j++) {
        printf(" %d ", array[j]);
    }
    printf("\n");
}

// 交換兩個(gè)數(shù)據(jù)的位置
void swap(int *num1, int *num2) {
    int temp = *num1;
    *num1 = *num2;
    *num2 = temp;
}

// 將數(shù)組分割成獨(dú)立的兩部分
int partition(int array[], int low, int high) {
    int privotKey = array[low]; // 基準(zhǔn)元素
    while (low < high) { // 從表的兩端交替地向中間掃描
        while (low < high && array[high] >= privotKey) {
            -- high; // 從 high 所指位置向前搜索缰儿,至多到 low+1 位置。將比基準(zhǔn)元素小的交換到前端
        }
        swap(&array[low], &array[high]);
        while (low < high && array[low] <= privotKey) {
            ++ low; // 從 low 所指位置向后搜索散址,至多到 high-1 位置乖阵。將比基準(zhǔn)元素大的交換到后端
        }
        swap(&array[low], &array[high]);
    }
    print(array, 8, low);
    return low;
}

// 快速排序(Quick Sort)
void quickSort(int array[], int low, int high) {
    if (low < high) {
        int privotLoc = partition(array, low, high); // 將表一分為二
        quickSort(array, low, privotLoc - 1); // 遞歸對低子表遞歸排序
        quickSort(array, privotLoc + 1, high); // 遞歸對高子表遞歸排序
    }
}

int main(int argc, const char * argv[]) {
    int arrayQuickSort[8] = { 49, 38, 65, 97, 76, 13, 27, 49 };
    quickSort(arrayQuickSort, 0, 7);
    
    printf("\n");
    return 0;
}

快速排序的改進(jìn)

快速排序是通常被認(rèn)為在同數(shù)量級(O(nlog2n))的排序方法中平均性能最好的。但若初始序列按關(guān)鍵碼有序或基本有序時(shí)预麸,快排序反而蛻化為冒泡排序瞪浸。為改進(jìn)之,通常以“三者取中法”來選取基準(zhǔn)記錄吏祸,即將排序區(qū)間的兩個(gè)端點(diǎn)與中點(diǎn)三個(gè)記錄關(guān)鍵碼居中的調(diào)整為支點(diǎn)記錄对蒲。快速排序是一個(gè)不穩(wěn)定的排序方法贡翘。

在本改進(jìn)算法中蹈矮,只對長度大于k的子序列遞歸調(diào)用快速排序,讓原序列基本有序鸣驱,然后再對整個(gè)基本有序序列用插入排序算法排序泛鸟。實(shí)踐證明,改進(jìn)后的算法時(shí)間復(fù)雜度有所降低踊东,且當(dāng)k取值為 8 左右時(shí)北滥,改進(jìn)算法的性能最佳刚操。

// 輸出數(shù)組內(nèi)容
void print(int array[], int length, int i) {
    printf("privot=%d:",i);
    for (int j = 0; j < length; j++) {
        printf(" %d ", array[j]);
    }
    printf("\n");
}

// 交換兩個(gè)數(shù)據(jù)的位置
void swap(int *num1, int *num2) {
    int temp = *num1;
    *num1 = *num2;
    *num2 = temp;
}

// 將數(shù)組分割成獨(dú)立的兩部分
int partition(int array[], int low, int high) {
    int privotKey = array[low]; // 基準(zhǔn)元素
    while (low < high) { // 從表的兩端交替地向中間掃描
        while (low < high && array[high] >= privotKey) {
            -- high; // 從 high 所指位置向前搜索,至多到 low+1 位置碑韵。將比基準(zhǔn)元素小的交換到前端
        }
        swap(&array[low], &array[high]);
        while (low < high && array[low] <= privotKey) {
            ++ low; // 從 low 所指位置向后搜索赡茸,至多到 high-1 位置。將比基準(zhǔn)元素大的交換到后端
        }
        swap(&array[low], &array[high]);
    }
    print(array, 8, low);
    return low;
}

// 快速排序改進(jìn)(Quick Sort)
void quickSortImprove(int array[], int low, int high, int k) {
    if (high - low > k) { // 長度大于k時(shí)遞歸祝闻,k為指定數(shù)
        int privotLoc = partition(array, low, high);
        quickSortImprove(array, low, privotLoc - 1, k);
        quickSortImprove(array, privotLoc + 1, high, k);
    }
}

// 快速排序改進(jìn)(Quick Sort)
void quickSort(int array[], int low, int high, int k) {
    quickSortImprove(array, low, high, k); // 先調(diào)用改進(jìn)算法占卧,使之基本有序

    // 再用插入排序?qū)居行蛐蛄信判?    for (int i = 1; i <= high; i ++) {
        int j = i - 1;
        int sentry = array[i]; // 復(fù)制為哨兵,即存儲待排序元素
        while (j >= 0 && sentry < array[j]) { // 查找在有序表的插入位置
            array[j+1] = array[j];
            j--; // 元素后移
        }
        array[j+1] = sentry; // 插入到正確位置
    }
}

int main(int argc, const char * argv[]) {
    int arrayQuickSort[8] = { 49, 38, 65, 97, 76, 13, 27, 49 };
    quickSort(arrayQuickSort, 0, 7, 4);
    print(arrayQuickSort, 8, 0);
    printf("\n");
    
    return 0;
}

總結(jié)

快速排序是目前基于比較的內(nèi)部排序中被認(rèn)為是最好的方法联喘,當(dāng)待排序的關(guān)鍵字是隨機(jī)分布時(shí)华蜒,快速排序的平均時(shí)間最短。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末豁遭,一起剝皮案震驚了整個(gè)濱河市叭喜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蓖谢,老刑警劉巖捂蕴,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異闪幽,居然都是意外死亡啥辨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門盯腌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來溉知,“玉大人,你說我怎么就攤上這事腕够〖墩В” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵帚湘,是天一觀的道長玫荣。 經(jīng)常有香客問我,道長客们,這世上最難降的妖魔是什么崇决? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮底挫,結(jié)果婚禮上恒傻,老公的妹妹穿的比我還像新娘。我一直安慰自己建邓,他們只是感情好盈厘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著官边,像睡著了一般沸手。 火紅的嫁衣襯著肌膚如雪外遇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天契吉,我揣著相機(jī)與錄音跳仿,去河邊找鬼。 笑死捐晶,一個(gè)胖子當(dāng)著我的面吹牛菲语,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惑灵,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼山上,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了英支?” 一聲冷哼從身側(cè)響起佩憾,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎干花,沒想到半個(gè)月后妄帘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡池凄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年寄摆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片修赞。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖桑阶,靈堂內(nèi)的尸體忽然破棺而出柏副,到底是詐尸還是另有隱情,我是刑警寧澤蚣录,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布割择,位于F島的核電站,受9級特大地震影響萎河,放射性物質(zhì)發(fā)生泄漏荔泳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一虐杯、第九天 我趴在偏房一處隱蔽的房頂上張望玛歌。 院中可真熱鬧,春花似錦擎椰、人聲如沸支子。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽值朋。三九已至叹侄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昨登,已是汗流浹背趾代。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丰辣,地道東北人撒强。 一個(gè)月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像糯俗,于是被迫代替她去往敵國和親尿褪。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 概述:排序有內(nèi)部排序和外部排序得湘,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序杖玲,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    每天刷兩次牙閱讀 3,729評論 0 15
  • 概述 排序有內(nèi)部排序和外部排序淘正,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序摆马,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,170評論 0 52
  • 一鸿吆、直接插入排序 直接插入排序(Insertion Sort)的基本思想是:每次將一個(gè)待排序的元素記錄囤采,按其關(guān)鍵字...
    kevin16929閱讀 553評論 0 0
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 將一個(gè)記錄插入到已排序好...
    依依玖玥閱讀 1,245評論 0 2
  • 概述排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序惩淳,而外部排序是因排序的數(shù)據(jù)很大蕉毯,一次不能容納全部的...
    Luc_閱讀 2,259評論 0 35