JavaScript實現(xiàn)排序算法【施工中】

快速排序

非常有名的排序扣墩,顧名思義,快速排序突出一個快闰挡,方法:
1.選取數(shù)組中的一個元素作為【基準點】
2.比基準點大的举娩,換到基準點右邊析校,比它小的放到左邊
3.再對基準點兩邊的部分重復1、2铜涉,直到所有元素有序為止

/**
 * 快速排序(遞歸法)
 * Average Time Complexity: O(nlog2n)
 * Stable: false
 * @param origin
 * @returns {Array}
 */
function quickSortRecursive (origin) {
    function swap (arr,i,j) {
      let t = arr[i]
      arr[i] = arr[j]
      arr[j] = t
    }
    let arr = [...origin]
    partition(arr,0,arr.length-1)
    function partition ( arr, start, end) {
        if (start >= end) {
            return
        }
        let mid = arr[end];
        let left = start, right = end - 1
        while (left < right) {
            while (arr[left] < mid && left < right)
                left++
            while (arr[right] >= mid && left < right)
                right--
            swap(arr, left, right)
        }
        if (arr[left] >= arr[end]){
            swap(arr, left, end)
        } else {
            left++
        }
        if (left) {
            partition(arr, start, left - 1)
        }
        partition(arr, left + 1, end)
    }
    return arr
}

缺點:
1.分治法需要開辟大量的空間存放分割數(shù)組智玻,遞歸法限制于函數(shù)調用棧的最大空間
2.當數(shù)組基本有序或者數(shù)組為倒序時,效率非常低

冒泡排序

這個大概是最好理解的排序方法了芙代,從左往右起比對吊奢,如果后一個元素小于前一個,則交換兩者位置纹烹,每一趟都會把最大的元素排到最后

/**
 * Average Time Complexity: O(n^2)
 * Stable: true
 * @param origin
 * @returns { Array }
 */
function bubbleSort ( origin ) {
    let arr = [...origin]
    for ( let i = 0, len = arr.length; i < len; i++) {
        for (let j = 0; j < arr.length-i-1; j++) {
            if ( arr[j] > arr[j+1] ) {
                [ arr[j], arr[j+1] ] = [ arr[j+1], arr[j] ]
            }
        }
    }
    return arr
}

選擇排序

從左往右起页滚,每趟從未排序的區(qū)間選擇最大/最小值換到左邊召边,排到上一趟排好的元素后面

/**
 * Average Time Complexity:
 * Stable: false
 * @param origin
 * @returns { Array }
 */
function selectSort ( origin ) {
    let arr = [...origin];
    let len = arr.length;
    for (let i = 0; i < len; i++ ) {
        let minIndex = i;
        for ( let j = i+1; j < len; j++) {
            if ( arr[j] < arr[minIndex] ) {
                minIndex = j;
            }
        }
        [ arr[i], arr[minIndex] ] = [ arr[minIndex], arr[i] ]
    }
    return arr
}

插入排序

我們平常打撲克整牌的時候非常類似于插入排序
從左往右起,每次選取一個元素插入左邊有序區(qū)間裹驰,如果該元素比前一個大且比后一個小隧熙,則插入這兩者之間

/**
 * 直接插入排序
 * Stable: true
 * @param origin
 * @returns { Array }
 */
function insertSort ( origin ) {
    let arr = [...origin]
    let len = arr.length;
    for ( let i = 1; i < len; i++ ) {
        let temp = arr[i];
        let j = i - 1;
        while ( j >= 0 && arr[j] > temp ) {
            arr[j+1] = arr[j];
            j--;
        }
        if ( j !== i - 1 ) {
            arr[j+1] = temp;
        }
    }
    return arr;
}

希爾排序

分治型的插入排序
1.定義增量(以折半增量為例),首先定義數(shù)組長度一半(向下取整)為增量 gap
2.從0開始邦马,每隔一個gap取數(shù)組下標贱鼻,形成新的分數(shù)組,以一個長度10的數(shù)組為例滋将,gap=5,將數(shù)組下標(不是元素本身)為 [0,5] [1,6] [2,7] [3,8] [4,9] 的元素組成5個分數(shù)組
3.對這些分數(shù)組進行插入排序
4.開始下一趟:將增量減半(向下取整),gap = 2症昏,則分成下標[0,2,4,6,8],[1,3,5,7,9]的分數(shù)組随闽,重復3,4直到gap為1為止
5.當gap為1時肝谭,直接進行最后的插入排序

/**
 * 希爾排序
 * @param origin
 * Stable: false
 */
function shellSort ( origin ) {
    let arr = [...origin]
    let len = arr.length
    for (let gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {
        for (let i = gap; i < len; i++) {
            for (let j = i - gap; j >= 0 && arr[j] > arr[gap + j]; j -= gap) {
                let temp = arr[j];
                arr[j] = arr[gap + j];
                arr[gap + j] = temp;
            }
        }
    }

}

堆排序

利用“堆”這個數(shù)據(jù)結構掘宪,構建最大/最小堆,再從堆中取走元素的排序法

/**
 * Heapsort 最大堆排序
 * @param origin
 * @returns { Array }
 */
function maxHeapSort ( origin ) {
    let arr = [...origin]
    //交換數(shù)組元素
    function swap(arr, i, j) {
        let tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    //將元素與父節(jié)點比對并交換位置攘烛,滿足最大堆性質為止
    function maxHeapify(start, end) {
        let dad = start;
        let son = dad * 2 + 1;
        if (son >= end){
            return;
        }
        if (son + 1 < end && arr[son] < arr[son + 1]){
            son++;
        }
        if (arr[dad] <= arr[son]) {
            swap(arr, dad, son);
            maxHeapify(son, end);
        }
    }

    let len = arr.length;
    for (let i = Math.floor(len / 2) - 1; i >= 0; i--)
        maxHeapify(i, len);
    for (let i = len - 1; i > 0; i--) {
        swap(arr,0, i);
        maxHeapify(0, i);
    }

    return arr;
}

基數(shù)排序

本例使用LSD魏滚,即從低位到高位排序
從個位開始,將數(shù)字按當前位數(shù)裝入一個{0,1,2,3,4,5,6,7,8,9}的桶中坟漱,然后按桶的下標倒出鼠次,再進行下一位數(shù)的裝桶操作
如果存在如 24 110這樣位數(shù)不一樣的數(shù),不足的數(shù)字需要在位數(shù)前補0

/**
 * Radix Sort基數(shù)排序
 * 從個位開始芋齿,將數(shù)字按當前位數(shù)排入一個{0,1,2,3,4,5,6,7,8,9}的桶中腥寇;
 * @param origin 原數(shù)組
 * @returns { Array } 輸出新數(shù)組
 */
function radixSort ( origin ) {
    let arr = [...origin]
    let digit = ( Math.max(...arr) + '').length
    let bucket = {};
    // 初始化桶
    for ( let i = 0; i < 10; i++) {
        bucket[i] = []
    }

    // 從各位到高位排序
    for ( let bit = 1; bit < 10**digit; bit*=10) {
        /**
         * 將元素按照位數(shù)作為下標裝入桶中
         * example 456:
         * 第一輪 bit = 1 -> 456個位數(shù)6,將456裝進bucket[6]
         * 第二輪 bit = 10 -> 456十位數(shù)5觅捆,將456裝進bucket[5]
         */
        for (let i = 0, len = arr.length; i < len; i++) {
            if ( arr[i]/bit < 1 ) {
                bucket[0].push(arr[i])
            } else {
                //獲取當前位數(shù)的數(shù)字赦役,如當前位數(shù)100,則取這個數(shù)的百位數(shù)
                let bitNum = Math.floor(arr[i]%(bit*10)/bit);
                bucket[bitNum].push(arr[i])
            }
        }
        arr = []; //清空數(shù)組

        //將元素從桶內倒出來
        for( let i in Object.keys(bucket) ) {
            while( bucket[i].length ) {
                arr.push( bucket[i].shift() )
            }
        }
    }
    return arr;
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末栅炒,一起剝皮案震驚了整個濱河市掂摔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赢赊,老刑警劉巖乙漓,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異域携,居然都是意外死亡簇秒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門秀鞭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來趋观,“玉大人扛禽,你說我怎么就攤上這事≈逄常” “怎么了编曼?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長剩辟。 經(jīng)常有香客問我掐场,道長,這世上最難降的妖魔是什么贩猎? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任熊户,我火速辦了婚禮,結果婚禮上吭服,老公的妹妹穿的比我還像新娘嚷堡。我一直安慰自己,他們只是感情好艇棕,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布蝌戒。 她就那樣靜靜地躺著,像睡著了一般沼琉。 火紅的嫁衣襯著肌膚如雪北苟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天打瘪,我揣著相機與錄音友鼻,去河邊找鬼。 笑死瑟慈,一個胖子當著我的面吹牛桃移,可吹牛的內容都是我干的。 我是一名探鬼主播葛碧,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼借杰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了进泼?” 一聲冷哼從身側響起蔗衡,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乳绕,沒想到半個月后绞惦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡洋措,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年济蝉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡王滤,死狀恐怖贺嫂,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情雁乡,我是刑警寧澤第喳,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站踱稍,受9級特大地震影響曲饱,放射性物質發(fā)生泄漏。R本人自食惡果不足惜珠月,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一扩淀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桥温,春花似錦引矩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氛谜。三九已至掏觉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間值漫,已是汗流浹背澳腹。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留杨何,地道東北人酱塔。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像危虱,于是被迫代替她去往敵國和親羊娃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內容

  • 總結一下常見的排序算法埃跷。 排序分內排序和外排序蕊玷。內排序:指在排序期間數(shù)據(jù)對象全部存放在內存的排序。外排序:指在排序...
    jiangliang閱讀 1,346評論 0 1
  • 概述 排序有內部排序和外部排序弥雹,內部排序是數(shù)據(jù)記錄在內存中進行排序垃帅,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,186評論 0 52
  • 排序算法幾種分類方式: 1剪勿,穩(wěn)定排序和不穩(wěn)定排序 如果a==b贸诚, 當排序之前a在b的前面,排序后,a仍然在b...
    fly_ever閱讀 418評論 0 0
  • 午覺被奇怪噩夢里驚醒酱固,睡在辦公桌上械念,椅子跟桌子有些不協(xié)調。睡著后手腳發(fā)麻的厲害媒怯。新的環(huán)境新的面孔新的領域订讼,有點像誤...
    潛水工閱讀 209評論 0 1
  • 叁品姐姐每天分享一段愛情感悟鳖敷,幸覆彼眨可以很簡單,點擊右上角關注哦定踱。 Love the wrong people, e...
    三品姐姐閱讀 642評論 0 0