雜記【2】常見排序演算法-JavaScript
阿新 • • 發佈:2018-12-09
文章目錄
直接插入排序法
// 直接插入排序法
function InsertSort(array){
var len = array.length;
array.unshift(0); //左側哨兵,防止越界
for(var i=2; i<len+1; i++){
array[0] = array[i];
var j;
for (j=i; array[j-1]>array[0]; j--){
array[j] = array[j-1];
}
array[j] = array[0];
}
array.shift(); //除掉臨時變數
}
var a = [256,13,42,7,1,99,130,22,314,25,2,87,64,12,57];
InsertSort(a);
console.log(a);
希爾排序法
希爾排序法是對直接插入排序法的優化
function ShellSort(array){
var len = array.length;
var d = Math.floor(len/2); //獲取分組間距
array.unshift(0); //在陣列開頭補多一個臨時變數
while(d>0){
for(var i=d+1; i<len+1; i++ ){
array[0] = array[i];
var j;
for(j=i; j>0 && array[j-d]>array[0]; j-=d){
array[j] = array[ j-d];
}
array[j] = array[0];
}
d = Math.floor(d/2);
}
array.shift(); //去除臨時變數
}
var a = [256,13,42,7,1,99,130,22,314,25,2,87,64,12,57];
ShellSort(a);
console.log(a);
氣泡排序法
最簡單的排序法
function bubbleSort(array){
var len = array.length;
var temp = 0;
for(var i=len-1; i>0; i--){
for(var j=0; j<i; j++){
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
}
var a = [256,13,42,7,1,99,130,22,314,25,2,87,64,12,57];
bubbleSort(a);
console.log(a);
快速排序法
快速排序法相當於對氣泡排序的改進
//掃描函式
function partition(array, first, end){
var pivot = 0, temp = 0;
var p = first, q = end;
while(p<q){
while(p<q && array[p]<=array[q]) q--; //從右向左掃描
if(p<q){
temp = array[p];
array[p] = array[q];
array[q] = temp;
}
while(p<q && array[p]<=array[q]) p++; //從左向右掃描
if(p<q){
temp = array[p];
array[p] = array[q];
array[q] = temp;
}
}
pivot = p;
return pivot;
}
//快排函式
function QuickSort(array, first, end){
if(first>=end) return;
else{
//進行一輪掃描,返回一箇中間值,將比中間值小的數放在中間值左側,比中間值大的數放在中間值右側
var pivot = partition(array, first, end);
QuickSort(array, first, pivot-1); //對左側無序區進行快排
QuickSort(array, pivot+1, end); //對右側無序區進行快排
}
}
var a = [256,13,42,7,1,99,130,22,314,25,2,87,64,12,57];
QuickSort(a, 0, a.length-1);
console.log(a);
選擇排序法
從無序區間選擇最小/最大值放到有序區間
function selectSort(array){
var len = array.length;
for(var i=0; i<len; i++){
var min = i;
for(var j=i+1; j<len; j++){
if(array[j]<array[min]){
min = j;
}
}
if(array[i] != array[min]){
var temp = array[i];
array[i] = array[min];
array[min] = temp;
}
}
}
var a = [256,13,42,7,1,99,130,22,314,25,2,87,64,12,57];
selectSort(a);
console.log(a);
堆排序
選擇排序的優化版,先建堆(大根堆/小根堆),再抽出根結點放入有序區間,然後調整堆
//堆調整函式,此處使用大根堆
function sift(array, iFrom, iTo){
var i,j,temp;
i = iFrom; j = 2*i;
while(j <= iTo){
if(j < iTo && array[j] < array[j+1]) j++; //比較左右孩子,讓j指向較大者
if(array[i] > array[j]) break; //根節點比左右子結點都大時,無需調整
else{
//將根節點和較大的子節點交換
temp = array[i];
array[i] = array[j];
array[j] = temp;
//進入下一層調整
i = j; j = j * 2;
}
}
}
function HeapSort(array){
var len = array.length;
var temp = 0;
var i = Math.floor(len/2);
array.unshift(0);
//初始建堆
for(; i >= 1; i--){
sift(array, i, len);
}
for(i=1; i<len; i++){
temp = array[1]; array[1]=array[len-i+1]; array[len-i+1]=temp;
sift(array, 1, len-i);
}
array.shift();
}
var a = [256,13,42,7,1,99,130,22,314,25,2,87,64,12,57];
HeapSort(a);
console.log(a);
二路歸併排序(遞迴版)
//合併兩個相鄰有序的子序列,即 array[iFrom]~array[iMiddle] 與 array[iMiddle+1]~array[iTo]
function Merge(array, iFrom, iMiddle, iTo){
var assist = new Array(array.length); //合併時用的輔助儲存空間
var i = iFrom; var j = iMiddle + 1; var k = iFrom;
while(i <= iMiddle && j <= iTo){
if(array[i] < array[j]) assist[k++] = array[i++]; //取array[i]和array[j]中較小者存入assist[k]
else assist[k++] = array[j++];
}
while(i <= iMiddle )
assist[k++] = array[i++];
while(j <= iTo )
assist[k++] = array[j++];
for(i = iFrom; i<= iTo; i++){
array[i] = assist[i];
}
}
//iFrom和iTo指定了排序區間
function MergeSort1(array, iFrom, iTo){
if(iFrom == iTo) return;
var iMiddle = Math.floor((iFrom+iTo)/2);
MergeSort1(array, iFrom, iMiddle);
MergeSort1(array, iMiddle+1, iTo);
Merge(array, iFrom, iMiddle, iTo);
}
var a = [256,13,42,7,1,99,130,22,314,25,2,87,64,12,57];
MergeSort1(a, 0, a.length-1);
console.log(a);