問題描述 上次的博客討論了排序算法中的插入排序和交換排序兩個(gè)大類,今天將剩下的常見排序算法全部梳理出來。 選擇排序 基本思想:每一趟排序從待排序的序列中選擇出最小的元素,順序放入到元素序列中,直到排序完成。該算法是一個(gè)不穩(wěn)定的算法并且效率與初始數(shù)據(jù)順序無關(guān)。 空間復(fù)雜度為O(1) 時(shí)間復(fù)雜度最高,平均,最低都為O(n2)
堆排序 基本原理:堆排序是一種樹形選擇排序算法,其原理是將R[1…n]看成一棵完全二叉樹的順序存儲(chǔ)結(jié)構(gòu)。利用完全二叉樹中雙親節(jié)點(diǎn)和孩子結(jié)點(diǎn)的關(guān)系,在當(dāng)前無序區(qū)中選擇關(guān)鍵字最大(最?。┑脑貥?gòu)建成大根堆(小根堆)。堆排序的主要流程便是,建立大(?。└?,然后輸出元素(頂部和底部元素進(jìn)行交換),再調(diào)整堆,直到元素全部輸出。堆排序是一個(gè)不穩(wěn)定的算法。 堆的定義為:n個(gè)關(guān)鍵字序列R[1…n]稱為堆,堆通??梢员豢醋鲆豢脴涞臄?shù)組對(duì)象。 當(dāng)且僅當(dāng)序列滿足R[i≤R[2i]且R[i]≤R[2i+1]時(shí)稱為該堆為大根堆,其中1≤i≤? n/2? 當(dāng)且僅當(dāng)序列滿足R[i]≥R[2i]且R[i]≥R[2i+1]時(shí)稱為該堆為小根堆,其中1≤i≤?n/2? 比如在大根堆中,最大的元素放在根節(jié)點(diǎn)中,且對(duì)于任一非根節(jié)點(diǎn),它的值小于等于其雙親節(jié)點(diǎn)的值。 對(duì)于堆排序來說關(guān)鍵在于構(gòu)造堆,而建堆是一個(gè)反復(fù)調(diào)整篩選的過程。首先從樹的最后一個(gè)非葉子節(jié)點(diǎn)開始調(diào)整,按照堆的性質(zhì)移動(dòng)元素位置。如下圖便是一個(gè)大頂推的調(diào)整過程。 初始堆建立完成后,就是進(jìn)行排序操作,排序操作的主要步驟是:以大根堆為例,每一次排序?qū)⒍秧斣嘏c堆尾元素進(jìn)行交換,然后再調(diào)用調(diào)整堆的算法使除了堆尾元素以外剩下的堆再次調(diào)整成一個(gè)大根堆,這樣循環(huán)length-1次就可以將元素調(diào)整為從小到大的順序,完成排序。 空間復(fù)雜度為O(1) 時(shí)間復(fù)雜度的最高,平均,最低都為O(nlog2n) Java實(shí)現(xiàn):
歸并排序和基數(shù)排序 歸并排序 基本思想:“歸并”的意思是指將兩個(gè)或者兩個(gè)以上的有序表合并成一個(gè)新的有序表。假設(shè)一個(gè)待排序的序列長(zhǎng)度為n,首先我們可以將其視為n個(gè)有序表,即每個(gè)表中元素個(gè)數(shù)為1,然后我們將n個(gè)有序表進(jìn)行兩兩歸并,得到? \lceil?n/2? \rceil?個(gè)長(zhǎng)度為2或者1的有序表然后再再次基礎(chǔ)上進(jìn)行兩兩歸并直到得到一個(gè)長(zhǎng)度為n的有序表為止。這種方法就稱為2路歸并排序。歸并排序是一個(gè)穩(wěn)定的排序算法。PS.歸并排序的發(fā)明者是約翰·馮·諾伊曼,其速度僅次于快速排序(平均狀況下) 例如我們有一個(gè)初始值為[22,11,32,2,12,83,10]的序列,才有2路歸并排序 第一趟歸并后:[11,22],[2,32],[12,83],[10] 第二趟歸并后:[2,11,22,32],[10,12,83] 第三趟歸并后:[2,10,11,12,22,32,83] 空間復(fù)雜度為O(n) 時(shí)間復(fù)雜度的最高,平均,最低都為O(nlog2n) Java實(shí)現(xiàn):
基數(shù)排序(桶子排序) 基本思想:基數(shù)排序是一種不基于比較的排序,而采用多關(guān)鍵字排序思想,即基于關(guān)鍵字各位的大小進(jìn)行排序,主要使用“分配”和“收集”兩種基本操作對(duì)單邏輯關(guān)鍵字進(jìn)行排序?;鶖?shù)排序又分為最高位優(yōu)先(MSD)排序和最低位優(yōu)先(LSD)排序。他的主要思想是將待排序的整數(shù)按位數(shù)切割成不同的數(shù)字,然后對(duì)每一位的數(shù)進(jìn)行單獨(dú)的比較,具體做法是:將所有待比較數(shù)值統(tǒng)一為同樣的數(shù)位長(zhǎng)度,如有不同位數(shù)則在前面進(jìn)行補(bǔ)零操作,然后從最低位開始,依次進(jìn)行一次排序,這樣從最低位排序一直到最高位排序完成以后, 數(shù)列就變成一個(gè)有序序列。 舉個(gè)栗子: 待排序的數(shù)據(jù)為[222,123,580,996,965,854,775],使用最低位優(yōu)先排序 第一趟將最低位進(jìn)行排序: [580,222,123,854,965,775,996] 第二趟將中間位進(jìn)行排序: [222,123,854,965,775,580,996] 第三趟將最高位進(jìn)行排序: [123,222,580,775,854,965,996] 空間復(fù)雜度:一趟排序需要的輔助空間為O?(r個(gè)隊(duì)列或桶)用于存放d待排序的數(shù) 時(shí)間復(fù)雜度:O(d(n+r)),d趟的分配和收集,一趟分配為O(n),一趟收集為O?。 Java實(shí)現(xiàn)(代碼參考百度百科)
就此常見的幾個(gè)排序算法就總結(jié)得差不多了,下一次的博客準(zhǔn)備寫一下JDK8中默認(rèn)的排序算法是如何實(shí)現(xiàn)的以及介紹的這幾種排序算法的實(shí)際使用案例和場(chǎng)景。 主 編 | 張禎悅 責(zé) 編 | 楊 旭 where2go 團(tuán)隊(duì) |
|