持續更新我對算法理解

一、冒泡排序:兩兩比較,大的放後面,小的放前面;使用兩個for循環,一個數就不用比了,所以第一個for循環遍歷次數n-1次,第二個for比較次數n 

// 冒泡排序:思路=》兩兩交換,大的放後面,小的放前面,第一次排序後最大值已在數組末尾
// 代碼實現:兩個for循環,外層循環控制排序的趟數,內層循環控制比較次數。每趟過後比較次數都應該減一
function sort (arr,n){
    let temp
    for(let i=0;i<n-1;i++){
        for (let j=0;j<n-i-1;j++) {
            if(arr[j]>arr[j+1]){
                temp = arr[j+1]
                arr[j+1] = arr[j]
                arr[j] = temp
            }
        }
    }
    return arr
}
let arr = [3,2,5,7,9,4,1,6]
let n = arr.length
console.log(sort(arr,n));
// [1, 2, 3, 4, 5, 6, 7, 9]
function sort (arr,n){
    let temp
    for(let i=0;i<n-1;i++){
        for (let j=i+1;j<n;j++) {
            if(arr[i]<arr[j]){
                temp = arr[j]
                arr[j] = arr[i]
                arr[i] = temp
            }
        }
    }
    return arr
}
let arr = [3,2,5,7,9,4,1,6]
let n = arr.length
console.log(sort(arr,n));
// [9, 7, 6, 5, 4, 3, 2, 1]

二、選擇排序

// 選擇排序:找到數組中最大的元素,與數組最後一位元素交換。當只有一個數時,則不需要選擇了,所以需要n-1趟排序
// 思路:兩個for循環,外層循環控制排序的趟數,內層循環找到當前趟數的最大值,隨後與當前趟數數組最後的一位元素交換
function sort (arr,n){
    let temp
    let max=0
    for(let i=0;i<n-1;i++){
        for (let j=0;j<n-i;j++) {
            if(arr[j]>arr[max]){
               max=j 
            }
        }
        temp=arr[max]
        arr[max] = arr[n-1-i]
        arr[n-1-i]=temp
    }
    return arr
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
console.log(sort(arr1,n1));
//[1, 2, 3, 4, 5, 6, 7, 8, 9]

三、快速排序 :取一個數作爲基準值[以中間項爲基準值],小於這個基準數的放在左邊,大於基準值的放在右邊,遞歸

三種實現的方式,參考如下

/*
大致分三步:

1、找基準(一般是以中間項爲基準)

2、遍歷數組,小於基準的放在left,大於基準的放在right

3、遞歸
*/ 
function quickSort(arr){
    //如果數組<=1,則直接返回
    if(arr.length<=1){
        return arr
    }
    let pointIndex = Math.floor(arr.length/2) //基準值
    let left = []
    let right = []
    let point = arr.splice(pointIndex,1)[0]  //把基準從原來的數組中刪除
    for(let i=0;i<arr.length;i++){
        // 小於基準的放在左邊
        if(arr[i]<=point){
            left.push(arr[i])
        }else{ //大於基準的放右邊
            right.push(arr[i])
        }
    }
    //遞歸
    return quickSort(left).concat([point],quickSort(right));
}
let arr = [3,2,5,7,9,4,1,6]
console.log(quickSort(arr));
// 快速排序:取一個數作爲基準值[以中間項爲基準值],小於這個基準數的放在左邊,大於基準值的放在右邊,遞歸
function sort (arr,l,r){
    let i = l
    let j =r
    let c = Math.floor((l+r)/2)  //取中間值作爲指點,比較
    console.log('c==='+c);
    let temp
    // 左右兩端進行掃描,只要兩端還沒有交替,就一直掃描
    while(i<=j){
        // 尋找直到比支點大的數
        while(arr[i]<arr[c]){
            i++
            console.log('i====='+i);  
        }
        // 尋找直到比支點小的數
        while(arr[c]<arr[j]){
            j--
            console.log('j===='+j);
        }
        // 此時找到了比支點小的數(右邊),比支點大的數(左邊),將他們交換位置
        if(i<=j){
            temp = arr[i]
            arr[i] = arr[j]
            arr[j] = temp
            i++
            j--
        }
        console.log(arr);
    }
    // “左邊”再做排序,直到左邊剩下一個數(遞歸出口)
    if(l<j){
        sort(arr,l,j)
    }
    // "右邊"再做排序,直到右邊剩下一個數(遞歸出口)
    if(i<r){
        sort(arr,i,r)
    }
    console.log(arr);
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
sort(arr1,0,n1-1)
function quickSort(arr, left, right) {
    /*
     * len爲數組的長度;
     * left爲需要數組中參與排序的起始點;right爲數組中參與排序的終止點;
     * left如果有傳數字那麼就爲left,沒有傳參則爲0;
     * right如果有傳參那麼就爲right,沒有傳參則爲len-1;
     * 有傳參可能會部分排序可能不會排序,沒傳參默認排序整個數組;
     * partitionIndex爲分組界限;
     */
    var len = arr.length,
        partitionIndex,
        left = typeof left !== 'number' ? 0 : left,
        right = typeof right !== 'number' ? len - 1 : right;

    // 如果需要排序的起始索引小於終止索引則執行排序;遞歸的終止條件;
    if (left < right) {

        // partition的返回值作爲partitionIndex來分隔數組;
        // 索引partitionIndex左邊的元素均小於arr[partitionIndex];
        // 右邊的元素均大於arr[partitionIndex];
        partitionIndex = partition(arr, left, right);

// 數組中小於arr[partitionIndex]的部分(索引left到partitionIndex-1)再次使用quickSort排序;
        quickSort(arr, left, partitionIndex - 1);

// 數組中大於arr[partitionIndex]的部分(索引partitionIndex+1到right)再次使用quickSort排序;
        quickSort(arr, partitionIndex + 1, right);
    }
    // 遞歸執行直到不滿足left<right;返回本身;
    return arr;
}

function partition(arr, left, right) {
    /*
     * 這部分是具體實現排序的部分;
     * 將left賦值給pivot,作爲參照物,因爲left在最左邊,只需要從左到右比較一遍即可判斷整個數組;
     * index索引是arr中待交換位置;
     */
    var pivot = left,
        index = pivot + 1;
    // for循環從參照物arr[pivot]下一個元素arr[pivot+1]開始一直比較到子數組結束arr[right];
    for (var i = index; i <= right; i++) {

  // 循環中如果有任何小於參照物的,就將他交換到index的位置,然後index向右移動到下一個位置;
        if (arr[i] < arr[pivot]) {
            swap(arr, i, index);
            index++;
        }
    }
    /*
     * 因爲每次都是交換完後index移動到下一個位置,所以在循環結束時,index仍爲待交換的位置;
     * 此時索引pivot+1到index-1的元素都小於參照物arr[pivot];
     */

    // 交換pivot和index-1索引的值之後index-1索引左邊全都是小於arr[index-1]的元素;
    swap(arr, pivot, index - 1);

    // 返回index-1作爲拆分子數組的分界線;
    return index - 1;
}
/*
 * 普通的交換,將a[i]和a[j]的數值交換;
 */
function swap(arr, i, j) {
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
console.log(quickSort(arr1,0,n1-1));

插入排序

歸併排序

堆排序

希爾排序

基數排序

遞歸

 

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