JavaScript實(shí)現(xiàn)常見6種排序

在學(xué)習(xí)了極客時間的數(shù)據(jù)結(jié)構(gòu)之后巍耗,根據(jù)排序的原理秋麸,我用JS重新實(shí)現(xiàn)了一遍,配圖來自極客時間的配圖炬太,因?yàn)槲覍?shí)在找不出比他寫的更好的了灸蟆。

學(xué)習(xí)方法:

講排序之前,先說一下學(xué)習(xí)方法,那就是debug模式,在JS中噩死,直接在循環(huán)里添加debugger,打開F12斋枢,F(xiàn)5刷新一下,就可以看到數(shù)組的變化情況了知给,對學(xué)習(xí)非常有幫助瓤帚,我就是這樣學(xué)的,在Java中涩赢,則是Eclipse進(jìn)入Debug模式戈次,我還是喜歡JS,因?yàn)楦庇^筒扒。


學(xué)習(xí)方法

冒泡排序

原理:
冒泡排序是最簡單的怯邪,只需要通過兩次遍歷,兩兩交換花墩,就可以實(shí)現(xiàn)排序悬秉。


冒泡排序

代碼:

                let arr = [145, 248, 31, 45, 9, 11, 145, 300];
                //冒泡排序
                function arrSort(arr) {
                    for (let i = 0; i < arr.length - 1; i++) {//遍歷澄步,這里,arr.length-1搂捧,是因?yàn)樽詈笠淮尾挥醚h(huán)了驮俗。
                        for (let j = 0; j < arr.length - i ; j++) {//雙重遍歷懂缕,遍歷i之后的數(shù)允跑,例如有8個元素,i在第一項(xiàng)搪柑,那么遍歷后面7項(xiàng)聋丝。
                            if(arr[j] < arr[j-1]){//如果右邊,小于左邊工碾,那么交換位置弱睦。
                                let temp = arr[j];
                                arr[j] = arr[j-1];
                                arr[j-1] = temp;
                            }
                        }
                    }
                    return arr;
                }
                console.log(arrSort(arr));

空間復(fù)雜度:因?yàn)橹簧婕暗浇粨Q,只需要常量級的臨時空間渊额,所以空間復(fù)雜度為O(1)
時間復(fù)雜度:最好O(n)况木,最壞O(n2),平均O(n2)
使用場景:數(shù)據(jù)量小于1000
穩(wěn)定性:穩(wěn)定

插入排序

原理:
1旬迹、從第二個元素開始火惊,遍歷它之前的元素。
2奔垦、如果他之前的元素屹耐,大于他,那么交換椿猎。并繼續(xù)往前遍歷之前比它大的元素惶岭。


插入排序原理圖

代碼實(shí)現(xiàn):

                //插入排序
                let arr = [145, 248, 31, 45, 9, 11, 145, 300];
                function arrSort(array) {
                    for(let i = 1; i < array.length; i++) {//遍歷一波數(shù)組,從數(shù)組第二項(xiàng)開始遍歷
                        let key = array[i];//這里必須要定義,因?yàn)檠h(huán)結(jié)束犯眠,會用到按灶。
                        let j = i - 1;//定義j為i-1,在第一次遍歷,是從數(shù)組第一項(xiàng)開始
                        while(j >= 0 && array[j] > key) {//如果j的值大于i的值筐咧,也就是左邊的大于右邊的鸯旁,j>=0,防止j--變負(fù)數(shù)嗜浮。
                            array[j + 1] = array[j];//例如第二項(xiàng)和第三項(xiàng)248和31羡亩,那么變成,248危融,248
                            j--;//如果248>31執(zhí)行成功了畏铆,變成了248,248,那么依次判斷左邊,是否有小于 的吉殃。
                        }
                        array[j + 1] = key;//把第一項(xiàng)賦值成最小的那個辞居。
                    }
                    return array;
                }
                console.log(arrSort(arr));

空間復(fù)雜度:因?yàn)椴恍枰~外的存儲空間楷怒,所以空間復(fù)雜度為O(1)
時間復(fù)雜度:最好O(n),最壞O(n2)瓦灶,平均O(n2)
使用場景:數(shù)據(jù)量小于1000
穩(wěn)定性:穩(wěn)定

選擇排序

原理:跟冒泡排序差不多鸠删,也是兩兩交換,不過這兩兩交換贼陶,是第一位和第五位交換刃泡,而不是第四位和第五位。


選擇排序

代碼:

                //選擇排序
                let arr = [145, 248, 31, 45, 9, 11, 145, 300];
                function arrSort(arr){
                    for(let i = 0; i < arr.length - 1; i++){//遍歷數(shù)組
                        let min = arr[i];//防止arr[i]發(fā)生變化
                        for(let j = i + 1; j < arr.length; j++){//雙重遍歷碉怔,查找最小的數(shù)進(jìn)行交換烘贴,跟冒泡不一樣的地方在于,選擇排序撮胧,假如第4位更小桨踪,則是1,4位交換芹啥,不是3锻离,4位交換
                            if(min > arr[j]){
                                let temp = min;
                                min = arr[j];
                                arr[j] = temp;
                            }
                        }
                        arr[i] = min;
                    }
                    return arr;
                }
                console.log(arrSort(arr));

空間復(fù)雜度:空間復(fù)雜度為O(1)
時間復(fù)雜度:最好O(n2),最壞O(n2)墓怀,平均O(n2)
使用場景:數(shù)據(jù)量小于1000
穩(wěn)定性:不穩(wěn)定汽纠,因?yàn)闀龅街貜?fù)的數(shù)。

歸并排序

原理:歸并排序使用了非常好的分治思想捺疼,把一個數(shù)組疏虫,分成兩部分,排序之后啤呼,較小的那個值取出來放在第一個位置卧秘,再合并。


歸并排序

代碼:

                //分治排序
                let arr = [145, 248, 31, 45, 9, 11, 145, 300];
                function merge(left, right) {
                    let result = [];
                    while(left.length > 0 && right.length > 0) {//如果兩邊數(shù)組都有值
                        if(left[0] < right[0]) {//左邊小于右邊
                            result.push(left.shift());//給result數(shù)組添加值官扣,并在left刪掉值
                        }
                        else {
                            result.push(right.shift());//給result數(shù)組添加值翅敌,并在right刪掉值
                        }
                    }
                    /* 當(dāng)左右數(shù)組長度不等.將比較完后剩下的數(shù)組項(xiàng)鏈接起來即可 */
                    return [...result,...left,...right];//這里用es6的語法,只是一個簡寫惕蹄,百度一眼就會蚯涮。...left...right是因?yàn)槿f一長度不相等,會少數(shù)卖陵,所以會加這兩個遭顶。
                }
                function mergeSort(arr){
                    if(arr.length==1){//如果數(shù)組長度為1則返回?cái)?shù)組
                        return arr
                    };
                    let mid=Math.floor(arr.length/2);//分成兩部分
                    let left_arr=arr.slice(0,mid);//數(shù)組分成兩份后,塞進(jìn)去泪蔫。假如說數(shù)組有8個元素棒旗,分成兩部分,左邊(0,4)
                    let right_arr=arr.slice(mid);//右邊(4到后面所有)
                    return merge(mergeSort(left_arr),mergeSort(right_arr));//遞歸
                }
                console.log(mergeSort(arr));

空間復(fù)雜度:因?yàn)椴皇窃嘏判蛄萌伲枰渌目臻g铣揉,所以空間復(fù)雜度為O(n)
時間復(fù)雜度:最好O(nlogn)饶深,最壞O(nlogn),平均O(nlogn)
使用場景:數(shù)據(jù)量大于1000
穩(wěn)定性:穩(wěn)定逛拱。

快速排序

原理:和歸并排序一樣敌厘,也是利用了分治思想,但是快排是選擇一個中間數(shù)朽合,然后比它小的放左邊俱两,比它大的放右邊。


快速排序

代碼:

                //快速排序
                let arr = [145, 248, 31, 45, 9, 11, 145, 300];
                function arrSort(arr){
                    if (arr.length <= 1){
                        return arr
                    };
                    var pivotIndex = Math.floor(arr.length / 2);
                    var pivot = arr.splice(pivotIndex,1)[0];//取出中間的數(shù)字旁舰,比如第一次就取出9
                    var left = [];
                    var right = [];
                    for (var i = 0; i < arr.length; i++){
                        if(arr[i] < pivot) {//第一次運(yùn)算锋华,如果小于9就進(jìn)入左數(shù)組嗡官,大于就進(jìn)入右數(shù)組
                            left.push(arr[i]);
                        }else{
                            right.push(arr[i]);
                        }
                    }
                    return arrSort(left).concat([pivot],arrSort(right));//遞歸箭窜,再把左數(shù)組分成兩半進(jìn)行排序,右數(shù)組同理衍腥。
                }
                console.log(arrSort(arr));

空間復(fù)雜度:最好O(logn) 最差O(n)
時間復(fù)雜度:最好O(nlogn)磺樱,最壞O(n2) ,平均O(nlogn)
使用場景:數(shù)據(jù)量大于1000
穩(wěn)定性:不穩(wěn)定婆咸。
我們用快排比歸并用的多竹捉,原因就在于歸并他不是原地排序,空間復(fù)雜度比較高尚骄。

希爾排序

原理:
希爾排序是根據(jù)增量(中間隔一段距離)块差,實(shí)現(xiàn)跳躍式的移動,使得排序的效率提高倔丈。在最后一輪中憨闰,增量必須等于1,另外需五,由于是跳躍式的移動鹉动,希爾排序并不是一種穩(wěn)定的排序算法。
舉一個小小的例子:
一個數(shù)組有8個元素宏邮,8%2==4泽示,第一輪中間隔4個,4%2==2蜜氨,第二輪中間隔2個……
第一輪械筛,第一項(xiàng)和第五項(xiàng),第二項(xiàng)和第六項(xiàng)飒炎,第三項(xiàng)和第七項(xiàng)埋哟,第四項(xiàng)和第八項(xiàng)。
第二輪厌丑,第一項(xiàng)和第三項(xiàng)定欧,第二項(xiàng)和第四項(xiàng)渔呵,第三項(xiàng)和第五項(xiàng),第四項(xiàng)和第六項(xiàng)砍鸠,第五項(xiàng)和第七項(xiàng)……

希爾排序扩氢,PPT工程師登場
                //希爾排序
                let arr = [145, 248, 31, 45, 9, 11, 145, 300];
                function arrSort(arr){
                    let gap =Math.floor(arr.length/2);
                    while(gap>=1){
                        for(let i = gap;i<arr.length;i++){
                            let j,temp=arr[i];
                            for(j=i-gap;j>=0&&temp<arr[j];j=j-gap){
                                arr[j+gap]=arr[j];
                            }
                            arr[j+gap]=temp;
                        }
                        gap=Math.floor(gap/2);
                    }
                    return arr;
                }
                console.log(arrSort(arr)); 

空間復(fù)雜度:O(1)
時間復(fù)雜度:最好O(nlog2n),最壞O(nlog2n)爷辱,平均O(nlogn)
使用場景:數(shù)據(jù)量大于1000
穩(wěn)定性:不穩(wěn)定录豺。

此外,還有桶排序饭弓,計(jì)數(shù)排序双饥,堆排序,基數(shù)排序等弟断,作者還在研究當(dāng)中咏花。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市阀趴,隨后出現(xiàn)的幾起案子昏翰,更是在濱河造成了極大的恐慌,老刑警劉巖刘急,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棚菊,死亡現(xiàn)場離奇詭異,居然都是意外死亡叔汁,警方通過查閱死者的電腦和手機(jī)统求,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來据块,“玉大人码邻,你說我怎么就攤上這事」迮ィ” “怎么了冒滩?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浪谴。 經(jīng)常有香客問我开睡,道長,這世上最難降的妖魔是什么苟耻? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任篇恒,我火速辦了婚禮,結(jié)果婚禮上凶杖,老公的妹妹穿的比我還像新娘胁艰。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布腾么。 她就那樣靜靜地躺著奈梳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪解虱。 梳的紋絲不亂的頭發(fā)上攘须,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天,我揣著相機(jī)與錄音殴泰,去河邊找鬼于宙。 笑死,一個胖子當(dāng)著我的面吹牛悍汛,可吹牛的內(nèi)容都是我干的捞魁。 我是一名探鬼主播,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼离咐,長吁一口氣:“原來是場噩夢啊……” “哼谱俭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起健霹,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤旺上,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后糖埋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窃这,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年瞳别,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杭攻。...
    茶點(diǎn)故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡祟敛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兆解,到底是詐尸還是另有隱情馆铁,我是刑警寧澤,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布锅睛,位于F島的核電站埠巨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏现拒。R本人自食惡果不足惜辣垒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望印蔬。 院中可真熱鬧勋桶,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鹃锈,卻和暖如春奥帘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仪召。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工寨蹋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扔茅。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓已旧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親召娜。 傳聞我的和親對象是個殘疾皇子运褪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,595評論 2 350

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