常見(jiàn)的排序算法有哪些?如何實(shí)現(xiàn)這些算法?

1.背景介紹


在計(jì)算機(jī)科學(xué)與數(shù)學(xué)中,一個(gè)排序算法是一種能將一串資料依照特定排序方式進(jìn)行排列的一種算法。 最常用到的排序方式是數(shù)值順序以及字典順序。 排序算法用在處理文字資料以及產(chǎn)生人類可讀的輸出結(jié)果。 基本上,排序算法的輸出必須遵守下列兩個(gè)原則:

  • 輸出結(jié)果為遞增序列(遞增是針對(duì)所需的排序順序而言)
  • 輸出結(jié)果是原輸入的一種排列、或是重組
  • 雖然排序算法是一個(gè)簡(jiǎn)單的問(wèn)題,但是從計(jì)算機(jī)科學(xué)發(fā)展以來(lái),在此問(wèn)題上已經(jīng)有大量的研究。 更多的新算法仍在不斷的被發(fā)明。

    2.知識(shí)剖析

    查找和排序算法是算法的入門知識(shí),其經(jīng)典思想可以用于很多算法當(dāng)中。因?yàn)槠鋵?shí)現(xiàn)代碼較短,應(yīng)用較常見(jiàn)。 所以在面試中經(jīng)常會(huì)問(wèn)到排序算法及其相關(guān)的問(wèn)題。但萬(wàn)變不離其宗,只要熟悉了思想,靈活運(yùn)用也不是難事。 一般在面試中最常考的是快速排序和歸并排序,并且經(jīng)常有面試官要求現(xiàn)場(chǎng)寫(xiě)出這兩種排序的代碼。 對(duì)這兩種排序的代碼一定要信手拈來(lái)才行。還有插入排序、冒泡排序、堆排序、基數(shù)排序、桶排序等。

    • 冒泡算法
    • 選擇排序
    • 插入排序
    • 快速排序
    • 3.常見(jiàn)問(wèn)題

      問(wèn)題:如何用JavaScript 如何實(shí)現(xiàn)?

      4.解決方案

      冒泡排序

      冒泡排序是一種簡(jiǎn)單的排序算法。它重復(fù)地走訪過(guò)要排序的數(shù)列,一次比較兩個(gè)元素, 如果他們的順序錯(cuò)誤就把他們交換過(guò)來(lái)。走訪數(shù)列的工作是重復(fù)地進(jìn)行直到?jīng)]有元素再需要交換, 也就是說(shuō)該數(shù)列已經(jīng)排序完成。

      冒泡排序演算法的運(yùn)作如下:

      1. 比較相鄰的元素。如果第一個(gè)比第二個(gè)大,就交換他們兩個(gè)。
      2. 對(duì)每一對(duì)相鄰元素作同樣的工作,從開(kāi)始第一對(duì)到結(jié)尾的最后一對(duì)。這步做完后,最后的元素會(huì)是最大的數(shù)。
      3. 針對(duì)所有的元素重復(fù)以上的步驟,除了最后一個(gè)。
      4. 持續(xù)每次對(duì)越來(lái)越少的元素重復(fù)上面的步驟,直到?jīng)]有任何一對(duì)數(shù)字需要比較。
      5. 冒泡排序

        var examplearr=[8,94,15,88,55,76,21,39];

        function sortarr(arr){

        for(i=0;i

        for(j=0;j

        if(arr[j]>arr[j+1]){

        var temp=arr[j];

        arr[j]=arr[j+1];

        arr[j+1]=temp;

        }

        }

        }

        return arr;

        }

        sortarr(examplearr);

        console.log(examplearr);

        冒泡排序

        基本思路:1.依次比較相鄰的兩個(gè)數(shù),如果第一個(gè)比第二個(gè)小,不變。如果第一個(gè)比第二個(gè)大,調(diào)換順序。一輪下來(lái),最后一個(gè)是最大的數(shù)

        2.對(duì)除了最后一個(gè)之外的數(shù)重復(fù)第一步,直到只剩一個(gè)數(shù)

        選擇排序(Selection sort)是一種簡(jiǎn)單直觀的排序算法。它的工作原理如下。 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再?gòu)氖S辔磁判蛟刂欣^續(xù)尋找最小(大)元素, 然后放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

        選擇排序的思想其實(shí)和冒泡排序有點(diǎn)類似,都是在一次排序后把最小的元素放到最前面。但是過(guò)程不同, 冒泡排序是通過(guò)相鄰的比較和交換。而選擇排序是通過(guò)對(duì)整體的選擇。

        選擇排序

        Array.prototype.selectionSort = function() {

        var i, j, min;

        var temp;

        for (i = 0; i < this.length - 1; i++) {

        min = i;

        for (j = i + 1; j < this.length; j++)

        if (this[min] > this[j])

        min = j;

        temp = this[min];

        this[min] = this[i];

        this[i] = temp;

        }

        return this;

        };

        var num = [22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70]; //定義一個(gè)數(shù)組

        num.selectionSort(); //數(shù)組定義選擇排序算法

        選擇排序

        1.找出最小的數(shù),和第一個(gè)交換位置

        2.在剩下的數(shù)中,找出最二小的數(shù),放在第二個(gè)

        3.依次類推,排出順序

        插入排序也是一個(gè)簡(jiǎn)單直觀的排序算法。它的 工作原理是通過(guò)構(gòu)建有序序列,對(duì)于未排序數(shù)據(jù), 在已排序序列中從后向前掃描,找到相應(yīng)位置并插入。插入排序在實(shí)現(xiàn)上,通常采用in-place排序 (即只需用到O(1)的額外空間的排序),因而在從后向前掃描過(guò)程中,需要反復(fù)把已排序元素逐步向后挪位, 為最新元素提供插入空間。

        1. 從第一個(gè)元素開(kāi)始,該元素可以認(rèn)為已經(jīng)被排序
        2. 取出下一個(gè)元素,在已經(jīng)排序的元素序列中從后向前掃描
        3. 如果該元素(已排序)大于新元素,將該元素移到下一位置
        4. 將新元素插入到該位置后
        5. 重復(fù)步驟2~5
        6. 插入排序

          Array.prototype.insertionSort = function () {

          for (var i = 1; i < this.length; i++) {

          var temp = this[i];

          var j = i - 1;

          //如果將賦值放到下一行的for循環(huán)內(nèi), 會(huì)導(dǎo)致在第13行出現(xiàn)j未聲明的錯(cuò)誤

          for (; j >= 0 && this[j] > temp; j--) {

          this[j + 1] = this[j];

          }

          this[j + 1] = temp;

          }

          return this;

          }

          var num = [22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70]; //定義一個(gè)數(shù)組

          num.insertionSort(); //數(shù)組調(diào)用插入排序算法

          插入排序

          基本思路:1.把數(shù)組分為[已排序]和[未排序]兩部分,第一個(gè)數(shù)為[已排序],其余為[未排序]

          2.從[未排序]抽出第一個(gè)數(shù),和[已排序]部分比較,插入到合適的位置

          快速排序

          步驟為:

          1. 從數(shù)列中挑出一個(gè)元素,稱為"基準(zhǔn)"(pivot),
          2. 重新排序數(shù)列,所有比基準(zhǔn)值小的元素?cái)[放在基準(zhǔn)前面,所有比基準(zhǔn)值大的元素?cái)[在基準(zhǔn)后面(相同的數(shù)可以到任一邊)。在這個(gè)分割結(jié)束之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個(gè)稱為分割(partition)操作。
          3. 遞歸地(recursively)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。
          4. 遞歸到最底部時(shí),數(shù)列的大小是零或一,也就是已經(jīng)排序好了。這個(gè)演算法一定會(huì)結(jié)束,因?yàn)樵诿看蔚牡╥teration)中,它至少會(huì)把一個(gè)元素?cái)[到它最后的位置去。

            Array.prototype.quickSort = function() {

            var len = this.length;

            if (len <= 1)

            return this.slice(0);

            var left = [];

            var right = [];

            var mid = [this[0]];

            for (var i = 1; i < len; i++)

            if (this[i] < mid[0])

            left.push(this[i]);

            else

            right.push(this[i]);

            return left.quickSort().concat(mid.concat(right.quickSort()));

            };

            var arr = [5, 3, 7, 4, 1, 9, 8, 6, 2];

            arr = arr.quickSort();

            快速排序

            1.以一個(gè)數(shù)為基準(zhǔn)(中間的數(shù)),比基準(zhǔn)小的放到左邊,比基準(zhǔn)大的放到右邊

            2.再按此方法對(duì)這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序(遞歸進(jìn)行

            3.不能再分后退出遞歸,并重新將數(shù)組合并

            5.編碼實(shí)戰(zhàn)

            6.擴(kuò)展思考

            如何評(píng)價(jià)算法的好壞

            正確性

            算法能滿足具體問(wèn)題的需求,即對(duì)任何合法的輸入算法都會(huì)得出正確的結(jié)果。

            可讀性

            算法創(chuàng)建后由人來(lái)閱讀、理解、使用以及修改。所以可讀性的好壞直接影響到算法的好壞。如果一個(gè)算法涉及的想法很多,就會(huì)給閱讀的人造成困難,那么這個(gè)算法就不能得到更好的交流和推廣,更不便于對(duì)算法進(jìn)行修改、擴(kuò)展和維護(hù)。所以要提高算法的可讀性,就要做到簡(jiǎn)明易懂。

            健壯性

            一個(gè)程序完成后,運(yùn)行該程序的用戶對(duì)程序的理解各有不同,并不能保證每一個(gè)人都能按照要求進(jìn)行輸入,健壯性就是指對(duì)非法輸入的抵抗能力,當(dāng)輸入的數(shù)據(jù)非法時(shí),算法能識(shí)別并做出處理,而不會(huì)因?yàn)檩斎氲腻e(cuò)誤產(chǎn)生錯(cuò)誤動(dòng)作或造成癱瘓

            時(shí)間復(fù)雜度與空間復(fù)雜度

            時(shí)間復(fù)雜度簡(jiǎn)單地說(shuō)就是算法運(yùn)行所需要的時(shí)間。不同的算法具有不同的時(shí)間復(fù)雜度,當(dāng)一個(gè)程序較小時(shí)感覺(jué)不到時(shí)間復(fù)雜度的重要性,當(dāng)一個(gè)程序特別大時(shí)便會(huì)察覺(jué)到時(shí)間復(fù)雜度的重要性。所以如何寫(xiě)出更高速的算法一直是算法不斷改進(jìn)的目標(biāo)。空間復(fù)雜度是指算法運(yùn)行所需的存儲(chǔ)空間,隨著計(jì)算機(jī)硬件的發(fā)展,空間復(fù)雜度已經(jīng)顯得不再那么重要

            7.參考文獻(xiàn)

            參考二:常見(jiàn)排序算法之JavaScript實(shí)現(xiàn)

            參考一:JavaScript 排序算法匯總

            最后編輯于
            ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
            平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

            • 又是一個(gè)周末,時(shí)間飛快,轉(zhuǎn)眼一個(gè)月又將過(guò)去。 心想已經(jīng)一個(gè)多月沒(méi)有給家里打電話了,心中思緒萬(wàn)千,混亂絞痛夾著一絲絲...
              簡(jiǎn)默Trina閱讀 189評(píng)論 0 1
            • 8.9-8.25 17個(gè)日夜,我在東莞度過(guò)。我不是去東莞度假,不是去玩樂(lè)。而是進(jìn)了一家名為富強(qiáng)的電子廠,沒(méi)錯(cuò),在高...
              iiiiich閱讀 192評(píng)論 0 0
            • 【作者 0han 本篇代碼來(lái)源于實(shí)驗(yàn)樓shiyanlou.com】 這一篇沒(méi)有太多介紹原理 因?yàn)槭窃趯W(xué)習(xí)pytho...
              0han閱讀 2,451評(píng)論 0 1
            • 3月末 春天總算是來(lái)了 還帶了點(diǎn)兒夏的氣息 風(fēng)吹地人 有些暖暖的 還有些懶懶的 吹地我 想起了3月的故鄉(xiāng) 還有那長(zhǎng)...
              goldfisher閱讀 220評(píng)論 0 0
            • 上一次見(jiàn)到小七的時(shí)候,是高考前幾個(gè)星期。我們站在圓形回廊上,她望著我,突然就說(shuō)了一句:“前段時(shí)間他生日,我送了個(gè)畫(huà)...
              待君淺笑閱讀 172評(píng)論 6 5