排序算法

一扼倘、排序算法說明

  • 排序的定義:對一序列對象根據(jù)某個關(guān)鍵字進行排序顶考。
    輸入:n個數(shù):a1,a2,a3,...,an 輸出:n個數(shù)的排列:a1',a2',a3',...,an'钥勋,使得a1'<=a2'<=a3'<=...<=an'
  • 對于評述算法優(yōu)劣術(shù)語的說明
  • 穩(wěn)定:如果a原本在b前面惊科,而a=b属韧,排序之后a仍然在b的前面;
  • 不穩(wěn)定:如果a原本在b的前面盏求,而a=b抖锥,排序之后a可能會出現(xiàn)在b的后面;
  • 內(nèi)排序:所有排序操作都在內(nèi)存中完成碎罚;
  • 外排序:由于數(shù)據(jù)太大磅废,因此把數(shù)據(jù)放在磁盤中,而排序通過磁盤和內(nèi)存的數(shù)據(jù)傳輸才能進行荆烈;
  • 時間復雜度: 一個算法執(zhí)行所耗費的時間拯勉。
  • 空間復雜度: 運行完一個程序所需內(nèi)存的大小。
  • 總結(jié)
  • 對比



    In-place: 占用常數(shù)內(nèi)存憔购,不占用額外內(nèi)存 Out-place: 占用額外內(nèi)存宫峦。

  • 分類


二、詳解

1.冒泡排序(Bubble Sort)
冒泡排序是一種簡單的排序算法玫鸟。它重復地走訪過要排序的數(shù)列导绷,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來鞋邑。重復地進行直到?jīng)]有再需要交換诵次,也就是說該數(shù)列已經(jīng)排序完成。

  • 算法描述
    <1>.比較相鄰的元素枚碗。如果第一個比第二個大逾一,就交換它們兩個;
    <2>.對每一對相鄰元素作同樣的工作肮雨,從開始第一對到結(jié)尾的最后一對遵堵,這樣在最后的元素應(yīng)該會是最大的數(shù);
    <3>.針對所有的元素重復以上的步驟怨规,除了最后一個陌宿;
    <4>.重復步驟1~3,直到排序完成波丰。
  • 算法實現(xiàn)
function bubbleSort(arr) {
    let length = arr.length;
    for(let i = 0;i < length-1;i++) {
        for(let j = 0;j < length-1-i;j++) {
            if(arr[j] > arr[j + 1]) { // 相鄰元素對比
                let temp = arr[j + 1]; // 交換位置
                arr[j + 1] = arr[j]; 
                arr[j] =temp; 
            }
        }
    }
    return arr;
}
let arr = [2, 1, 19, 30, 27];
console.log(bubbleSort(arr))
  • 算法分析
  • 最佳情況
    T(n) = O(n)(數(shù)據(jù)正序)
  • 最差情況
    T(n) = O(n2)(數(shù)據(jù)反序)
  • 平均
    T(n) = O(n2)

2.選擇排序(Selection Sort)
選擇排序(Selection-sort)是一種簡單直觀的排序算法壳坪。它的工作原理:首先在未排序序列中找到最小(大)元素掰烟,存放到排序序列的起始位置爽蝴,然后沐批,再從剩余未排序元素中繼續(xù)尋找最小(大)元素蝎亚,然后放到已排序序列的末尾九孩。以此類推,直到所有元素均排序完畢发框。

  • 算法描述
  • <1>.初始狀態(tài):無序區(qū)為R[1..n]躺彬,有序區(qū)為空;
  • <2>.第i趟排序(i=1,2,3...n-1)開始時梅惯,當前有序區(qū)和無序區(qū)分別為R[1..i-1]和R(i..n)宪拥。排序開始時從無序區(qū)的第一個開始,對比后面的个唧,如果遇到比這個小的江解,就記錄下位置设预。該趟排序從當前無序區(qū)中選出最小的記錄R[k]徙歼,將它與無序區(qū)的第1個記錄R交換,使R[1..i]和R[i+1..n)分別變?yōu)橛涗泜€數(shù)增加1個的新有序區(qū)和記錄個數(shù)減少1個的新無序區(qū)鳖枕;
  • <3>.n-1趟結(jié)束魄梯,數(shù)組有序化了。
  • 算法實現(xiàn)
function selectionSort(arr) {
    let len = arr.length;
    let minIndex, temp;
    for(let i = 0;i < len;i++) {
        minIndex = i;
        for(let j = i + 1;j < len; j++) {
            if(arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    console.timeEnd('選擇排序耗時');
    return arr;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(selectionSort(arr));
  • 算法分析
  • 最佳情況:T(n) = O(n2)
  • 最差情況:T(n) = O(n2)
  • 平均情況:T(n) = O(n2)

3.插入排序(Insertion-Sort)
插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法宾符。它的工作原理是通過構(gòu)建有序序列酿秸,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描魏烫,找到相應(yīng)位置并插入辣苏。

  • 算法描述

  • <1>.從第一個元素開始,該元素可以認為已經(jīng)被排序哄褒;

  • <2>.取出下一個元素稀蟋,在已經(jīng)排序的元素序列中從后向前掃描;

  • <3>.如果該元素(已排序)大于新元素呐赡,將該元素移到下一位置退客;

  • <4>.重復步驟3,直到找到已排序的元素小于或者等于新元素的位置链嘀;

  • <5>.將新元素插入到該位置后萌狂;

  • <6>.重復步驟2~5。

  • 算法實現(xiàn)

function insertionSort (array) {
    if(Object.prototype.toString.call(array).slice(8, -1) == 'Array') {
        console.time('插入排序耗時');
        for (let i = 1;i < array.length; i++) {
            let key = array[i];
            let j = i - 1;
            while(j >= 0 && array[j] > key) {
                array[j + 1] = array[j]; //與前面排好序的對比
                j--;
            }
            array[j + 1] = key; // 插入到最后對比的那個數(shù)后面
        }
        console.timeEnd('插入排序耗時:');
        return array;
    } else {
        return 'array is not an Array!';
    }
}
  • 算法分析
  • 最佳情況:輸入數(shù)組按升序排列怀泊。T(n) = O(n)
  • 最壞情況:輸入數(shù)組按降序排列茫藏。T(n) = O(n2)
  • 平均情況:T(n) = O(n2)

4.歸并排序(Merge Sort)
和選擇排序一樣,歸并排序的性能不受輸入數(shù)據(jù)的影響霹琼,但表現(xiàn)比選擇排序好的多务傲,因為始終都是O(n log n)的時間復雜度冤留。代價是需要額外的內(nèi)存空間。
歸并排序是建立在歸并操作上的一種有效的排序算法树灶。該算法是采用分治法(Divide and Conquer)的一個非常典型的應(yīng)用纤怒。歸并排序是一種穩(wěn)定的排序方法。將已有序的子序列合并天通,得到完全有序的序列泊窘;即先使每個子序列有序,再使子序列段間有序像寒。若將兩個有序表合并成一個有序表烘豹,稱為2-路歸并。

  • 算法描述
  • <1>.把長度為n的輸入序列分成兩個長度為n/2的子序列诺祸;
  • <2>.對這兩個子序列分別采用歸并排序携悯;
  • <3>.將兩個排序好的子序列合并成一個最終的排序序列。
  • 算法實現(xiàn)
function mergeSort(arr) {  //采用自上而下的遞歸方法
    var len = arr.length;
    if(len < 2) {
        return arr;
    }
    var middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right)
{
    var result = [];
    console.time('歸并排序耗時');
    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
    while (left.length)
        result.push(left.shift());
    while (right.length)
        result.push(right.shift());
    console.timeEnd('歸并排序耗時');
    return result;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(mergeSort(arr));
  • 算法分析
  • 最佳情況:T(n) = O(n)
  • 最差情況:T(n) = O(nlogn)
  • 平均情況:T(n) = O(nlogn)

5.快速排序(Quick Sort)
快速排序快筷笨,而且效率高憔鬼!它是處理大數(shù)據(jù)最快的排序算法之一。
快速排序的基本思想:通過一趟排序?qū)⒋庞涗浄指舫瑟毩⒌膬刹糠治赶模渲幸徊糠钟涗浀年P(guān)鍵字均比另一部分的關(guān)鍵字小轴或,則可分別對這兩部分記錄繼續(xù)進行排序,以達到整個序列有序仰禀。

  • 算法描述
  • <1>.從數(shù)列中挑出一個元素照雁,稱為 "基準"(pivot);
  • <2>.重新排序數(shù)列答恶,所有元素比基準值小的擺放在基準前面饺蚊,所有元素比基準值大的擺在基準的后面(相同的數(shù)可以到任一邊)。在這個分區(qū)退出之后悬嗓,該基準就處于數(shù)列的中間位置污呼。這個稱為分區(qū)(partition)操作;
  • <3>.遞歸地(recursive)把小于基準值元素的子數(shù)列和大于基準值元素的子數(shù)列排序烫扼。
  • 算法實現(xiàn)
let quickSort = function (arr) {
    console.time('快速排序耗時');
    if(arr.length <= 1) {return arr;}
    let pivotIndex = Math.floor(arr.length / 2);
    let pivot = arr.splice(pivotIndex, 1) [0];
    let left = [];
    let right = [];
    for (let i = 0; i < arr.length; i++) {
        if(arr[i] < pivot) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }
    }
    console.timeEnd('快速排序耗時');
  return quickSort(left).concat([pivot], quickSort(right));
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(quickSort(arr));
  • 算法分析
  • 最佳情況:T(n) = O(nlogn)
  • 最差情況:T(n) = O(n2)
  • 平均情況:T(n) = O(nlogn)

6.計數(shù)排序
計數(shù)排序(Counting sort)是一種穩(wěn)定的排序算法曙求。計數(shù)排序使用一個額外的數(shù)組C,其中第i個元素是待排序數(shù)組A中值等于i的元素的個數(shù)映企。然后根據(jù)數(shù)組C來將A中的元素排到正確的位置悟狱。它只能對整數(shù)進行排序。

  • 算法描述
  • <1>. 找出待排序的數(shù)組中最大和最小的元素堰氓;
  • <2>. 統(tǒng)計數(shù)組中每個值為i的元素出現(xiàn)的次數(shù)挤渐,存入數(shù)組C的第i項;
  • <3>. 對所有的計數(shù)累加(從C中的第一個元素開始双絮,每一項和前一項相加)浴麻;
  • <4>. 反向填充目標數(shù)組:將每個元素i放在新數(shù)組的第C(i)項得问,每放一個元素就將C(i)減去1。
  • 算法實現(xiàn)
function countingSort(array) {
    var len = array.length,
        B = [],
        C = [],
        min = max = array[0];
    console.time('計數(shù)排序耗時');
    for (var i = 0; i < len; i++) {
        min = min <= array[i] ? min : array[i];
        max = max >= array[i] ? max : array[i];
        C[array[i]] = C[array[i]] ? C[array[i]] + 1 : 1;
    }
    for (var j = min; j < max; j++) {
        C[j + 1] = (C[j + 1] || 0) + (C[j] || 0);
    }
    for (var k = len - 1; k >= 0; k--) {
        B[C[array[k]] - 1] = array[k];
        C[array[k]]--;
    }
    console.timeEnd('計數(shù)排序耗時');
    return B;
}
var arr = [2, 2, 3, 8, 7, 1, 2, 2, 2, 7, 3, 9, 8, 2, 1, 4, 2, 4, 6, 9, 2];
console.log(countingSort(arr)); 
  • 算法分析
  • 最佳情況:T(n) = O(n+k)
  • 最差情況:T(n) = O(n+k)
  • 平均情況:T(n) = O(n+k)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末软免,一起剝皮案震驚了整個濱河市宫纬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌膏萧,老刑警劉巖漓骚,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異榛泛,居然都是意外死亡蝌蹂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門曹锨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孤个,“玉大人,你說我怎么就攤上這事沛简∑肜穑” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵覆享,是天一觀的道長佳遂。 經(jīng)常有香客問我营袜,道長撒顿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任荚板,我火速辦了婚禮凤壁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘跪另。我一直安慰自己拧抖,他們只是感情好,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布免绿。 她就那樣靜靜地躺著唧席,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘲驾。 梳的紋絲不亂的頭發(fā)上淌哟,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機與錄音辽故,去河邊找鬼徒仓。 笑死,一個胖子當著我的面吹牛誊垢,可吹牛的內(nèi)容都是我干的掉弛。 我是一名探鬼主播症见,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼殃饿!你這毒婦竟也來了谋作?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤乎芳,失蹤者是張志新(化名)和其女友劉穎瓷们,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秒咐,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡谬晕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了携取。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攒钳。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖雷滋,靈堂內(nèi)的尸體忽然破棺而出不撑,到底是詐尸還是另有隱情,我是刑警寧澤晤斩,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布焕檬,位于F島的核電站,受9級特大地震影響澳泵,放射性物質(zhì)發(fā)生泄漏实愚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一兔辅、第九天 我趴在偏房一處隱蔽的房頂上張望腊敲。 院中可真熱鬧,春花似錦维苔、人聲如沸碰辅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽没宾。三九已至,卻和暖如春沸柔,著一層夾襖步出監(jiān)牢的瞬間循衰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工勉失, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留羹蚣,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓乱凿,卻偏偏與公主長得像顽素,于是被迫代替她去往敵國和親咽弦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

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

  • Ba la la la ~ 讀者朋友們胁出,你們好啊型型,又到了冷鋒時間,話不多說全蝶,發(fā)車闹蒜! 1.冒泡排序(Bub...
    王飽飽閱讀 1,801評論 0 7
  • 總結(jié)一下常見的排序算法。 排序分內(nèi)排序和外排序抑淫。內(nèi)排序:指在排序期間數(shù)據(jù)對象全部存放在內(nèi)存的排序绷落。外排序:指在排序...
    jiangliang閱讀 1,350評論 0 1
  • 前些天同學告訴我要去體檢催式,問我一起去不去函喉,欣然接受了他的建議,但是他那里有點事要我先去他家正好我們也有段時間...
    清風湖水橋閱讀 317評論 2 2
  • 算法思想 算法流程 算法步驟 算法實現(xiàn) python 算法應(yīng)用
    伊凡vnir閱讀 856評論 0 0
  • 聽老師的話荣月,嘗試用自己的語言開始記錄點什么管呵。不知道從什么時候開始,心里有過這么一個念頭哺窄,但一直沒有真正的付出...
    知邱一頁閱讀 307評論 0 1