標籤:尋找 希爾 art splay 冒泡排序 images archive 也有 第一個
沒有系統地總結過js演算法,雖然在項目中陸陸續續的也用過好多演算法,有一次去一家公司面試的時候,面試官說想談談演算法,有點懵了,所以接下來的面試中談的也有點被動,避免下次再碰到這種情況,今天決定好好的總結下js的各種演算法。
1.插入排序
看到一篇直接插入排序講的很好的文章,將插入排序與抽撲克牌進行對比,一直動態地添加撲克牌,添加時進行排序,等牌抽完了,手裡的牌也整理好了。
轉換成演算法就是從第二個資料開始,依次與前面的資料進行比對,如果小於該資料,就將二者位置互換,這就是插入排序的原理。
function insertSort(array) { var len = array.length, i, j, tmp, result; result = array.slice(0); for(i=1; i < len; i++){ tmp = result[i]; j = i - 1; while(j>=0 && tmp < result[j]){ result[j+1] = result[j]; j--; } result[j+1] = tmp; } return result;}View Code
2.二分插入排序
二分插入排序是在插入排序的基礎上進行最佳化。
它的基本思想是將原序列分為有序區與無序區,從無序區取出一個元素,與有序區中間位置的元素進行比較,如果大於中間位置的元素,將該元素與有序區後半部分的元素進行比較,直至找到該元素的位置。同時將有序區原位置以後的所有元素後移。重複該操作,直至無序區全部添加至有序區。
function midSort(array) { var len = array.length, i, j, tmp, low, high, mid, result; result = array.slice(0); for(i = 1; i < len; i++){ tmp = result[i]; low = 0; high = i - 1; while(low <= high){ mid = parseInt((low + high)/2, 10); if(tmp < result[mid]) high = mid - 1; else low = mid + 1; } for(j = i - 1; j >= high+1; j--){ result[j+1] = result[j]; } result[j+1] = tmp; } return result;}View Code
3.希爾排序
希爾(Shell)排序又稱為縮小增量排序,它是一種插入排序。它是直接插入排序演算法的一種威力加強版。
該方法因DL.Shell於1959年提出而得名。
希爾排序的基本思想是:
把記錄按步長 gap 分組,對每組記錄採用直接插入排序方法進行排序。
隨著步長逐漸減小,所分成的組包含的記錄越來越多,當步長的值減小到 1 時,整個資料合成為一組,構成一組有序記錄,則完成排序。
我們來通過示範圖,更深入的理解一下這個過程。
function shellSort(array){ var len = array.length, gap = parseInt(len/2), i, j, tmp, result; result = array.slice(0); while(gap > 0){ for(i = gap; i < len; i++){ tmp = result[i]; j = i - gap; while(j>=0 && tmp < result[j]){ result[j + gap] = result[j]; j = j - gap; } result[j + gap] = tmp; } gap = parseInt(gap/2); } return result;}View Code
4.冒泡排序
冒泡排序是最經典的演算法之一,他的原理是對數組進行若干次排序,每次排序對數組元素的相鄰元素進行比較,每趟排序都需要找到第i個最小的元素。
function bubbleSort(arr){ var len = arr.length; var result = arr.slice(0); //外層控制輪數 for(var i=0;i<len;i++){ //標誌某一趟排序過程中是否有資料交換 var mark = true; //內層對數組元素進行冒泡選擇 for(var j=0;j<len-1-i;j++){ //判斷當較小的元素位於下面時,冒泡 if(result[j] > result[j+1]){ mark = false; var temp = result[j]; result[j] = result[j+1]; result[j+1] = temp; } } if(mark){ //當某一趟排序時並沒有進行資料交換,則說明所有資料已經有序 return result; } } }View Code
5.選擇排序
選擇排序的原理是每次從待排序的無序列表中找到最小的資料,放在已排序的有序數組的最尾部。
簡單排序流程:
(1)從待排序序列中,找到關鍵字最小的元素;
(2)如果最小元素不是待排序序列的第一個元素,將其和第一個元素互換;
(3)從餘下的 N - 1 個元素中,找出關鍵字最小的元素,重複(1)、(2)步,直到排序結束。
function selectionSort(arr) { var len = arr.length-1,res=arr.splice(0),i; var minIndex, temp; for (i = 0; i < len; i++) { minIndex = i; for (var j = i + 1; j < len; j++) { if (res[j] < res[minIndex]) { //尋找最小的數 minIndex = j; //將最小數的索引儲存 } } tmp = res[i]; res[i] = res[minIndex]; res[minIndex] =tmp; } return res;}View Code
6.快速排序
快速排序是一種交換排序。
快速排序的基本思想是:
(1)將待排序的數組根據中間點分成兩部分。
(2)將比該基準資料大的放在右邊的數組,比基準資料小的放在左邊的數組。
(3)對左右兩個數組不斷重複第一步和第二步,合并數組。
function quickSort(arr){ if(arr.length < 2){ return arr; } var tmp = arr.splice(Math.floor(arr.length/2), 1)[0], arrLeft = [], arrRight = []; for(var i = 0; i < arr.length; i++){ if(arr[i] >= tmp){ arrRight.push(arr[i]); }else{ arrLeft.push(arr[i]); } } return arguments.callee(arrLeft).concat(tmp,arguments.callee(arrRight)); }View Code
前三種為插入排序,查的很多資料中講各種排序演算法時都提到了時間複雜度的概念,有時間學習下。
參考頁面:
1.排序演算法——插入排序
2.最佳化的直接插入排序(二分尋找插入排序,希爾排序)
3.程式員的內功——資料結構和演算法系列
4.排序四 希爾排序
5.十大經典排序演算法
幾種常見演算法js