雜記【2】常見排序算法-JavaScript

直接插入排序法

// 直接插入排序法
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);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章