Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
快速排序(Quiksort)是一種通過基準(zhǔn)劃分區(qū)塊并不斷交換左右項的排序方式,其采用了分治法,減少了交換的次數(shù)。平均算法復(fù)雜度:O(NlogN)。
步驟是:
圖1 快速排序執(zhí)行過程
從上圖可以看出:
1、遞歸新建數(shù)組版。無需交換,每個分區(qū)都是新數(shù)組。
圖2 快速排序遞歸新建數(shù)組版
這個版本最容易理解,先找準(zhǔn)基準(zhǔn)項(用中間項表示),把小于基準(zhǔn)項的全添加到左側(cè)新數(shù)組,大于等于基準(zhǔn)項的放在右側(cè)新數(shù)組,然后分別遞歸調(diào)用左、右新數(shù)組,再重復(fù)第一步找基準(zhǔn)項,再據(jù)此一分為二。直到把數(shù)組項拆分為一個個length為1的數(shù)組。最后自左往右將最小值與中間項和最大值連接起來。這里利用到JS語法中的concat,可以有效地連接數(shù)組。
這個版本好處是代碼簡單,非常容易理解,除了要注意基準(zhǔn)項不要放入到left和right,而是concat到結(jié)果即可。但是帶來的問題是要新建很多數(shù)組,所以這個方式并不是很優(yōu)的方式。
2、標(biāo)準(zhǔn)遞歸版本。需要交換,無需新建數(shù)組。
圖3 標(biāo)準(zhǔn)遞歸版本
圖4 標(biāo)準(zhǔn)遞歸版本執(zhí)行結(jié)果
這個版本好處是無需新建數(shù)組,而整個排序過程都是基于原數(shù)組的位置交換。其機制和排序過程與上一個方案基本類似(不同在于新方案的基準(zhǔn)項可交換會,因此遞歸有時需要帶上基準(zhǔn)項),直到把所有分區(qū)都比較過后就表示已經(jīng)排序完成。
其排序過程為:
3、非遞歸版本。需要交換,無需新建數(shù)組,利用stack或queue遍歷。
圖5 快速排序非遞歸版本
非遞歸版本基于標(biāo)準(zhǔn)遞歸版本,交換邏輯與排序規(guī)則完全一樣。所不同的是,將遞歸改為棧或隊列的循環(huán)。不同點是:
快速排序是一種相對巧妙的排序方式,相對選擇、插入、冒泡來講效率要高,也要稍微復(fù)雜一些。其交換過程也有點類似冒泡,但是不像冒泡兩兩逐個交換,而是根據(jù)基準(zhǔn)值比較大小按需要來交換,然后遞歸分區(qū)排序,這樣以來交換就減少了。但快排并不穩(wěn)定,如果遇到已排過序或全一樣的數(shù)字這種最壞情況那跟冒泡等一樣了。
PS:請對比之前關(guān)于選擇、插入、冒泡三種冒泡排序的文章。
選擇排序(Selection Sort)是從待排序數(shù)列中取出最小(或最大)的1位,與第一個位置交換,再從待排序數(shù)列中找出最小的跟整個數(shù)列的第二個交換。以此類推遍歷完待排序數(shù)列。平均算法復(fù)雜度:O(n^2)
步驟是:
例如數(shù)列: 4, 1, 3, 5, 2
從待排序區(qū)間中每次找到最小的項目,將其與第一項交換。
選擇排序過程
選擇排序的標(biāo)準(zhǔn)實現(xiàn)
選擇排序新建數(shù)組
插入排序是將數(shù)組分為待排序和已排序兩個區(qū)間。依次從待排序區(qū)間中取出一項,用該項跟已排序區(qū)間項逐個對比,通過位移來實現(xiàn)插入到對應(yīng)位置的排序方式。插入排序平均時間復(fù)雜度是:O(n^2)
步驟是:
插入排序有多種實現(xiàn)方式,這里介紹常見的3種:
1、通用實現(xiàn)方式,自左往右遍歷待排序數(shù)組,再從當(dāng)前的左側(cè)位置開始自右往左循環(huán)已排序數(shù)組,再逐個比較和移動被比較項,最后將當(dāng)前項填入到空缺位置上。
2、利用數(shù)組splice方法,類似打撲克牌,先拿出要排序的牌,然后找準(zhǔn)位置插入。這種方式利用了原生API,減少了數(shù)組反復(fù)移動位置的操作。性能上之前差不多。
3、新建數(shù)組法與splice結(jié)合法,這種方式會多建立一個數(shù)組,也就會多占用一個空間,但理解起來最容易,也利用了JS語言的特性。
插入排序與冒泡、選擇都是比較簡單好懂的排序方式,性能上也差不多。插入排序通俗來講就像打撲克牌排序,你抓了一手牌之后。假如是:2、1、5、3、4,你會:
1、先把牌分成兩組,假定左側(cè)第一張牌為一組(標(biāo)識A,這時只有2),其他牌為另外一組(標(biāo)識B,包括1、5、3、4)。
2、從B組里面從左起選擇第一張牌(位置空出等待填充),也就是1,拿這張牌與A組里面從右往左挨個對比,當(dāng)遇到比這張牌還小時就在這個位置停留下來(如果A組全部比這張牌都大那就在A組最前面停留下來,如果A組里沒有比這張牌大的就在當(dāng)前位置停留)。
3、然后將A組里比這張牌(也就是1)大的牌逐個往右移動1位,原B組空出位置被填充,此時剛才停留的位置空出,將1這張牌插入在這里。這時候A組增加一個數(shù)字,變?yōu)椋?、2,B組減少1個,變?yōu)椋?、3、4。
4、移動指針,繼續(xù)指向B組的第一個,也就是5。用5這張牌重復(fù)第二部,即拿5去跟A組自右往左逐個比較,然后插入到A組。此時A組:1、2、5,B組:3、4。
5、將B組里數(shù)字按照第二部重復(fù)操作,直到B組為空時整個循環(huán)結(jié)束。此時A組為:1、2、3、4、5。
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。