整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          程序員面試必備:動圖演示十大經典排序算法及代碼實現

          注于Java領域優質技術,歡迎關注

          作者:一像素

          0、算法概述

          0.1 算法分類

          十種常見排序算法可以分為兩大類:

          • 比較類排序:通過比較來決定元素間的相對次序,由于其時間復雜度不能突破O(nlogn),因此也稱為非線性時間比較類排序。
          • 非比較類排序:不通過比較來決定元素間的相對次序,它可以突破基于比較排序的時間下界,以線性時間運行,因此也稱為線性時間非比較類排序。

          0.2 算法復雜度

          0.3 相關概念

          • 穩定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
          • 不穩定:如果a原本在b的前面,而a=b,排序之后 a 可能會出現在 b 的后面。
          • 時間復雜度:對排序數據的總的操作次數。反映當n變化時,操作次數呈現什么規律。
          • 空間復雜度:是指算法在計算機

          內執行時所需存儲空間的度量,它也是數據規模n的函數。

          1、冒泡排序(Bubble Sort)

          冒泡排序是一種簡單的排序算法。它重復地走訪過要排序的數列,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。

          1.1 算法描述

          • 比較相鄰的元素。如果第一個比第二個大,就交換它們兩個;
          • 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對,這樣在最后的元素應該會是最大的數;
          • 針對所有的元素重復以上的步驟,除了最后一個;
          • 重復步驟1~3,直到排序完成。

          1.2 動圖演示

          1.3 代碼實現

          2、選擇排序(Selection Sort)

          選擇排序(Selection-sort)是一種簡單直觀的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小(大)元素,然后放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

          2.1 算法描述

          n個記錄的直接選擇排序可經過n-1趟直接選擇排序得到有序結果。具體算法描述如下:

          • 初始狀態:無序區為R[1..n],有序區為空;
          • 第i趟排序(i=1,2,3…n-1)開始時,當前有序區和無序區分別為R[1..i-1]和R(i..n)。該趟排序從當前無序區中-選出關鍵字最小的記錄 R[k],將它與無序區的第1個記錄R交換,使R[1..i]和R[i+1..n)分別變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區;
          • n-1趟結束,數組有序化了。

          2.2 動圖演示

          2.3 代碼實現

          2.4 算法分析

          表現最穩定的排序算法之一,因為無論什么數據進去都是O(n2)的時間復雜度,所以用到它的時候,數據規模越小越好。唯一的好處可能就是不占用額外的內存空間了吧。理論上講,選擇排序可能也是平時排序一般人想到的最多的排序方法了吧。

          3、插入排序(Insertion Sort)

          插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構建有序序列,對于未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入。

          3.1 算法描述

          一般來說,插入排序都采用in-place在數組上實現。具體算法描述如下:

          • 從第一個元素開始,該元素可以認為已經被排序;
          • 取出下一個元素,在已經排序的元素序列中從后向前掃描;
          • 如果該元素(已排序)大于新元素,將該元素移到下一位置;
          • 重復步驟3,直到找到已排序的元素小于或者等于新元素的位置;
          • 將新元素插入到該位置后;
          • 重復步驟2~5。

          3.2 動圖演示

          3.2 代碼實現


          3.4 算法分析

          插入排序在實現上,通常采用in-place排序(即只需用到O(1)的額外空間的排序),因而在從后向前掃描過程中,需要反復把已排序元素逐步向后挪位,為最新元素提供插入空間。

          4、希爾排序(Shell Sort)

          1959年Shell發明,第一個突破O(n2)的排序算法,是簡單插入排序的改進版。它與插入排序的不同之處在于,它會優先比較距離較遠的元素。希爾排序又叫縮小增量排序

          4.1 算法描述

          先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,具體算法描述:

          • 選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
          • 按增量序列個數k,對序列進行k 趟排序;
          • 每趟排序,根據對應的增量ti,將待排序列分割成若干長度為m 的子序列,分別對各子表進行直接插入排序。僅增量因子為1 時,整個序列作為一個表來處理,表長度即為整個序列的長度。

          4.2 動圖演示

          4.3 代碼實現


          4.4 算法分析

          希爾排序的核心在于間隔序列的設定。既可以提前設定好間隔序列,也可以動態的定義間隔序列。動態定義間隔序列的算法是《算法(第4版)》的合著者Robert Sedgewick提出的。

          5、歸并排序(Merge Sort)

          歸并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為2-路歸并。

          5.1 算法描述

          • 把長度為n的輸入序列分成兩個長度為n/2的子序列;
          • 對這兩個子序列分別采用歸并排序;
          • 將兩個排序好的子序列合并成一個最終的排序序列。

          5.2 動圖演示

          5.3 代碼實現


          5.4 算法分析

          歸并排序是一種穩定的排序方法。和選擇排序一樣,歸并排序的性能不受輸入數據的影響,但表現比選擇排序好的多,因為始終都是O(nlogn)的時間復雜度。代價是需要額外的內存空間。

          6、快速排序(Quick Sort)

          快速排序的基本思想:通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。

          6.1 算法描述

          快速排序使用分治法來把一個串(list)分為兩個子串(sub-lists)。具體算法描述如下:

          • 從數列中挑出一個元素,稱為 “基準”(pivot);
          • 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的后面(相同的數可以到任一邊)。在這個分區退出之后,該基準就處于數列的中間位置。這個稱為分區(partition)操作;
          • 遞歸地(recursive)把小于基準值元素的子數列和大于基準值元素的子數列排序。

          6.2 動圖演示

          6.3 代碼實現


          7、堆排序(Heap Sort)

          堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,并同時滿足堆積的性質:即子結點的鍵值或索引總是小于(或者大于)它的父節點。

          7.1 算法描述

          • 將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆為初始的無序區;
          • 將堆頂元素R[1]與最后一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];
          • 由于交換后新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,……Rn-1)調整為新堆,然后再次將R[1]與無序區最后一個元素交換,得到新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重復此過程直到有序區的元素個數為n-1,則整個排序過程完成。

          7.2 動圖演示

          7.3 代碼實現


          8、計數排序(Counting Sort)

          計數排序不是基于比較的排序算法,其核心在于將輸入的數據值轉化為鍵存儲在額外開辟的數組空間中。 作為一種線性時間復雜度的排序,計數排序要求輸入的數據必須是有確定范圍的整數。

          8.1 算法描述

          • 找出待排序的數組中最大和最小的元素;
          • 統計數組中每個值為i的元素出現的次數,存入數組C的第i項;
          • 對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加);
          • 反向填充目標數組:將每個元素i放在新數組的第C(i)項,每放一個元素就將C(i)減去1。

          8.2 動圖演示

          8.3 代碼實現


          8.4 算法分析

          計數排序是一個穩定的排序算法。當輸入的元素是 n 個 0到 k 之間的整數時,時間復雜度是O(n+k),空間復雜度也是O(n+k),其排序速度快于任何比較排序算法。當k不是很大并且序列比較集中時,計數排序是一個很有效的排序算法。

          9、桶排序(Bucket Sort)

          桶排序是計數排序的升級版。它利用了函數的映射關系,高效與否的關鍵就在于這個映射函數的確定。桶排序 (Bucket sort)的工作的原理:假設輸入數據服從均勻分布,將數據分到有限數量的桶里,每個桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續使用桶排序進行排)。

          9.1 算法描述

          • 設置一個定量的數組當作空桶;
          • 遍歷輸入數據,并且把數據一個一個放到對應的桶里去;
          • 對每個不是空的桶進行排序;
          • 從不是空的桶里把排好序的數據拼接起來。

          9.2 圖片演示

          9.3 代碼實現


          9.4 算法分析

          桶排序最好情況下使用線性時間O(n),桶排序的時間復雜度,取決與對各個桶之間數據進行排序的時間復雜度,因為其它部分的時間復雜度都為O(n)。很顯然,桶劃分的越小,各個桶之間的數據越少,排序所用的時間也會越少。但相應的空間消耗就會增大。

          10、基數排序(Radix Sort)

          基數排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次類推,直到最高位。有時候有些屬性是有優先級順序的,先按低優先級排序,再按高優先級排序。最后的次序就是高優先級高的在前,高優先級相同的低優先級高的在前。

          10.1 算法描述

          • 取得數組中的最大數,并取得位數;
          • arr為原始數組,從最低位開始取每個位組成radix數組;
          • 對radix進行計數排序(利用計數排序適用于小范圍數的特點);

          10.2 動圖演示

          10.3 代碼實現

          10.4 算法分析

          基數排序基于分別排序,分別收集,所以是穩定的。但基數排序的性能比桶排序要略差,每一次關鍵字的桶分配都需要O(n)的時間復雜度,而且分配之后得到新的關鍵字序列又需要O(n)的時間復雜度。假如待排數據可以分為d個關鍵字,則基數排序的時間復雜度將是O(d*2n) ,當然d要遠遠小于n,因此基本上還是線性級別的。

          基數排序的空間復雜度為O(n+k),其中k為桶的數量。一般來說n>>k,因此額外空間需要大概n個左右。

          來自:https://www.cnblogs.com/onepixel/articles/7674659.html

          格(行)排序:

          <html>
          <head>
          <meta charset="utf-8">
          <title>無標題文檔</title>
          <script>
          window.onload=function (){
              var oTab=document.getElementById('tab1');
              var oBtn=document.getElementById('btn1');
          
              oBtn.onclick=function (){
              var arr=[];
          
              for(var i=0;i<oTab.tBodies[0].rows.length;i++){
              arr[i]=oTab.tBodies[0].rows[i]; //將表格行元素集合轉換為數組
              }
          
              arr.sort(function (tr1, tr2){ //自定義排序函數
              var n1=parseInt(tr1.cells[0].innerHTML);
              var n2=parseInt(tr2.cells[0].innerHTML);
          
              return n1-n2;
              });
          
              for(var i=0;i<arr.length;i++){
              oTab.tBodies[0].appendChild(arr[i]);
              }
              };
          };
          </script>
          </head>
          <body>
          <input id="btn1" type="button" value="排序" />
          <table id="tab1" border="1" width="500">
          <thead>
          <td>ID</td>
          <td>姓名</td>
          <td>年齡</td>
          <td>操作</td>
          </thead>
          <tbody>
          <tr>
          <td>2</td>
          <td>張三</td>
          <td>23</td>
          <td></td>
          </tr>
          <tr>
          <td>6</td>
          <td>王四</td>
          <td>24</td>
          <td></td>
          </tr>
          <tr>
          <td>1</td>
          <td>Blue</td>
          <td>27</td>
          <td></td>
          </tr>
          <tr>
          <td>5</td>
          <td>張偉</td>
          <td>24</td>
          <td></td>
          </tr>
          <tr>
          <td>3</td>
          <td>李四</td>
          <td>28</td>
          <td></td>
          </tr>
          <tr>
          <td>4</td>
          <td>王五</td>
          <td>25</td>
          <td></td>
          </tr>
          </tbody>
          </table>
          </body>
          </html>

          appendChild()方法理解:

          target.appendChild(newnode)

          1.先把元素從原有父級上刪掉

          2.添加到新的父級

          .冒泡排序:

          比較相鄰的兩個數,如果前一個數大于后一個數,就將這兩個數換位置。每一次遍歷都會將本次遍歷最大的數冒泡到最后。為了將n個數排好序,需要n-1次遍歷。 如果某次遍歷中,沒有調整任何兩個相鄰的數的位置關系,說明此時數組已排好序,可以結束程序。

          1. Array.prototype.bubbleSort = function () {
          2. let i, j;
          3. for (i = 1; i < this.length; i++) { //表示本次是第i次遍歷
          4. let changed = false;
          5. for (j = 0; j < this.length - i; j++) { //訪問序列為arr[0:length-i]
          6. if(this[j] > this[j + 1]){ //發現前一個數大于后一個時,互換位置
          7. [this[j],this[j+1]] = [this[j+1],this[j]];
          8. changed = true;
          9. }
          10. }
          11. if(!changed) { //如果本輪遍歷沒有發現位置調整,結束排序函數
          12. break;
          13. }
          14. }
          15. };
          16. let arr = [43, 21, 10, 5, 9, 15, 32, 57, 35];
          17. arr.bubbleSort();
          18. console.log(arr);

          主站蜘蛛池模板: 亚洲AV永久无码精品一区二区国产 | 一区二区三区影院| 中文字幕AV一区二区三区人妻少妇| 精产国品一区二区三产区| 亚洲国产精品一区二区第一页| 国产免费私拍一区二区三区| 国产精品夜色一区二区三区| 久久精品一区二区免费看| 国模无码一区二区三区不卡| 动漫精品专区一区二区三区不卡| 国产精品一区二区久久精品涩爱| 无码囯产精品一区二区免费| 中文字幕VA一区二区三区| 亚洲av成人一区二区三区在线观看 | 精品福利一区二区三| 中文字幕在线观看一区 | 成人精品一区二区户外勾搭野战| 亚洲熟妇av一区二区三区漫画| 色视频综合无码一区二区三区| 在线观看精品视频一区二区三区| 竹菊影视欧美日韩一区二区三区四区五区 | 日韩电影在线观看第一区| 日本精品一区二区在线播放| 精品免费国产一区二区| 国产综合视频在线观看一区| 精品一区狼人国产在线| 日本精品一区二区三区视频| 国产日韩精品一区二区在线观看 | 国精产品999一区二区三区有限| AA区一区二区三无码精片| 韩国理伦片一区二区三区在线播放| 99久久综合狠狠综合久久一区| 色窝窝无码一区二区三区成人网站| 久久精品亚洲一区二区| 精品一区高潮喷吹在线播放| 久久久久人妻精品一区三寸| 国产成人av一区二区三区在线观看 | 人妻夜夜爽天天爽爽一区| 中文字幕一区二区三区在线观看| 精品国产a∨无码一区二区三区| 精品动漫一区二区无遮挡|