這裏用JavaScript實現冒泡排序、選擇排序、插入排序、歸併排序以及快速排序這些常見的排序算法算法
首先咱們給本文約定一個實現的框架:定義一個ArrayList類裏面包含排序數組聲明、數組元素添加、排序算法實現以及數組輸出的方法。數組
代碼框架:框架
function ArrayList(){ var array=[]; this.inputArraymember=function(){ //將10個大小在1~15的隨機數添加到數組中 var ins=0; for(var i=0;i<10;i++){ ins=Math.floor(Math.random()*15+1); array.push(ins); } }; this.相應的排序算法=function(){...算法的具體實現代碼...}; //代碼塊替換部分 this.toString=function(separator){ //將數組按指定分隔符生成字符串方便輸出 return array.join(separator); }; } var a = new ArrayList(); a.inputArraymember(); console.log("隨機生成的原始數組爲:"+a.toString('-')); a.bubbleSort(); console.log("排序後數組爲:"+a.toString('-'));
用兩層循環,第一層用來記錄剩餘的還未排序的數的個數,第二層用來在剩下的未排序的數中找到最大的數並將其放到未排序數的最後面(冒泡)。dom
代碼實現:函數
this.bubbleSort=function(){ var length=array.length; for(var i=0;i<length;i++){ for(var j=0;j<length-1-i;j++){ if(array[j]>array[j+1]){ var t=array[j]; array[j]=array[j+1];array[j+1]=t; } } } };
冒泡排序的時間複雜度是O(n²)。將以上代碼替換文章開始約定的代碼框架中的「代碼塊替換部分」便可用於在調試工具中運行查看代碼運行結果。工具
思路很簡單,每次都找出未排序的數當中最小的數並放在開頭,直到全部數的位置肯定下來。說清楚點就是從全部序列中先找到最小的,而後放到第一個位置。以後再看剩餘元素中最小的,放到第二個位置……以此類推。ui
代碼實現:this
this.selectsort=function(){ var length=array.length,currentMin; for(var i=0;i<length-1;i++){ //每循環一趟就會有一個數獲得排序 currentMin=i; //用來記錄最小數的下標,默認爲最開始的未排序的元素下標 for(var j=i;j<length;j++){ if(array[currentMin]>array[j]){ currentMin=j; } } if(i!==currentMin){ //若下標不是未排序的最開始的那個元素的下標,則將二者的值交換 var t=array[currentMin]; array[currentMin]=array[i]; array[i]=t; } } };
可看出,選擇排序也用了兩個嵌套着的循環,因此時間複雜度也是O(n²),是一種原址排序。調試
從第二個數開始(由於第一個數只有一個,前面沒得比。),與前面的數挨個比較,直到找到前一個數比當前值小,後一個數比當前值大的位置,讓後將當前值置於此處,以此類推。code
代碼實現:
this.insertsort=function(){ var length=array.length, j,temp; for(var i=1;i<length;i++){ j=i; temp=array[i]; //先存儲待比較的數 while(j>0&&array[j-1]>temp){ //若是這個數比上一個數小,則讓上一個數佔據如今這個數的位置(右移每一個比當前數小的數) array[j]=array[j-1]; j-- } array[j]=temp; //直到這個數不比上一個數小的時候,將這個數放在當前的位置 } };
時間複雜度爲O(nlogn)。歸併用的是分治的思想,將原始數組切分紅較小的數組,直到每一個小數組只有一個位置,接着講小數組歸併成較大的數組,直到最後只有一個排序完畢的大數組。
代碼實現:
this.mergeSort=function() { array = mergeSortRec(array); }; //建堆函數,將數組一直拆分紅兩部分,直到各部分數組長度都爲1的時候中止,而後進行merge操做 var mergeSortRec = function(array){ var length = array.length; if (length === 1) { return array; } var mid = Math.floor(length / 2), left = array.slice(0, mid),//slice() 方法可從已有的數組中返回選定的元素,語法 arrayObject.slice(start,end) right = array.slice(mid, length); return merge(mergeSortRec(left), mergeSortRec(right)); }; //將各部分進行歸併 var merge = function(left, right) { var result = [], il = 0, ir = 0; while(il < left.length && ir < right.length) { if (left[il] < right[ir]) { result.push(left[il++]); } else { result.push(right[ir++]); } } //若是il數組還有剩餘,則將其剩餘部分添加到結果數組中 while (il < left.length) { result.push(left[il++]); } //若是ir數組還有剩餘,則將其剩餘部分添加到結果數組中 while (ir < right.length) { result.push(right[ir++]); } return result; };
時間複雜度爲O(logn)。用的是分治的思想。
代碼實現:
this.quickSort = function(){ quick(array, 0, array.length - 1); }; var partition = function(array, left, right) { //劃分過程 //主元的選擇方法最好是隨機選擇一個數組想或是選擇中間項,這裏選擇中間項 var pivot = array[Math.floor((right + left) / 2)], i = left, j = right; console.log('pivot is ' + pivot + '; left is ' + left + '; right is ' + right); while (i <= j) { while (array[i] < pivot) { i++; console.log('i = ' + i); } while (array[j] > pivot) { j--; console.log('j = ' + j); } if (i <= j) { console.log('swap ' + array[i] + ' with ' + array[j]); swapQuickStort(array, i, j); i++; j--; } } return i; }; var swapQuickStort = function(array, index1, index2){ var aux = array[index1]; array[index1] = array[index2]; array[index2] = aux; }; var quick = function(array, left, right){//將子數組分離爲較小值數組和較大值數組 var index; if (array.length > 1) { index = partition(array, left, right); if (left < index - 1) { quick(array, left, index - 1); } if (index < right) { quick(array, index, right); } } return array; };