排序算法总结及JS实现

冒泡排序
冒泡排序比较任何两个相邻的项,如果第一个比第二个大,则交换它们。元素项向上移动至正确的顺序。

function bubbleSort(arr){
    var len = arr.length;
    for(var i=0;i<len;i++){
        for(var j=0;j<len-1-i;j++){      //内循环减去外循环中已跑过的次数,可以避免内循环中所有不必要的比较
            if(arr[j]>arr[j+1]){
                [arr[j], arr[j+1]] = [arr[j+1], arr[j]];
            }
        }
    }
    console.log(arr);
}

测试:

bubbleSort([9,8,7,6,5,4,3,2,1]);      //[1,2,3,4,5,6,7,8,9]

时间复杂度:O(n²)

选择排序
选择排序算法是一种原址比较算法。选择排序的思路是:找到数据结构中最小值并将其放置在第一位,接着找到第二小的值将其放在第二位,依此类推。

function selectionSort(arr){
    var len = arr.length;
    var index = null;
    for(var i = 0; i< len - 1;i++){
        index = i;
        for(var j = i;j<len;j++){
            if(arr[index] > arr[j]){
                index = j;
            }
        }
        if(i != index){
            [arr[i], arr[index]] = [arr[index], arr[i]];
        }
    }
    console.log(arr);
}

测试:

selectionSort([2,1,3,5,8,6,7,3]);       //[ 1, 2, 3, 3, 5, 6, 7, 8 ]

时间复杂度:O(n²)

插入排序
插入排序每次排一个数组项,以此方式构建最后的排序数组。假如第一项已经排序好了,接着,它和第二项进行比较,第二项是应该呆在原位置,还是插入到第一项之前呢?这样前两项就已正确排序,接着和第三项比较,依此类推。

function insertSort(arr){
    var len = arr.length,
    j,
    temp;
    for(var i = 1; i<len;i++){
        j = i;
        temp = arr[i];
        while(j>0&&arr[j-1] > temp){
            arr[j] = arr[j-1];
            j--;
        }
        arr[j] = temp;
    }
    console.log(arr);
}

测试:

insertSort([1,3,2,7,5,9,2]);      //[ 1, 2, 2, 3, 5, 7, 9 ]

时间复杂度:O(n²)
插入排序在排序小型数组时,比选择排序和冒泡排序的性能要好

归并排序
归并排序是一种分治算法。其思想是将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完成的大数组。

function mergeSort(arr){
    mergeSortRec(arr)
}
function mergeSortRec(arr){
    var len = arr.length;
    if(len === 1){           //递归终止条件
        return arr;
    }
    var mid = Math.floor(len / 2);
    var left = arr.slice(0, mid);
    var right = arr.slice(mid, len);
    return merge(mergeSortRec(left), mergeSortRec(right));
}
function merge(left, right){
    var res = [];
    var le = 0;
    var re = 0;
    while(le<left.length && re<right.length){
        if(left[le] < right[re]){
            res.push(left[le++]);
        }
        else{
            res.push(right[re++]);
        }
    }
    while(le < left.length){
        res.push(left[le++]);
    }
    while(re < right.length){
        res.push(right[re++]);
    }
    console.log(res);
    return res;
}

测试:

var array = [1,3,2,6,4,8,5];
mergeSort(array);

输出:
在这里插入图片描述
时间复杂度:O(nlogn)

快速排序
和归并排序一样,快速排序也使用分治的方法,将原始数组分为较小的数组。
(1)首先,从数组中选择中间一项作为主元;
(2)创建两个指针,左边一个指向数组的第一项,右边一个指向数组的最后一项。移动左指针直到我们找到一个比主元大的元素,接着,移动右指针直到找到一个比主元小的元素。然后交换它们,重复这个过程,直到左指针超过了右指针。这个过程将使得比主元小的值都排在主元之前,比主元大的值都排在主元之后。这一步叫做划分操作。
(3)接着,算法对划分后的小数组重复之前的两个步骤,直至数组已完全排序。

function quickSort(arr){
    quick(arr, 0, arr.length-1);
    console.log(arr);
}
function quick(arr, left, right){
    var index;
    if(arr.length > 1){
        index = partition(arr, left, right);
        if(left < index-1){
            quick(arr, left, index-1);
        }
        if(index < right){
            quick(arr, index, right);
        }
    }
}
function partition(arr, left, right){
    var p = arr[Math.floor((left+right) / 2)],
    i = left,
    j = right;
    while(i <= j){
        while(arr[i] < p){
            i++;
        }
        while(arr[j] > p){
            j--;
        }
        if(i <= j){
            [arr[i], arr[j]] = [arr[j], arr[i]];
            i++;
            j--;
        }
    }
    return i;
}

时间复杂度:O(nlogn)

堆排序
堆排序也是一种很高效的算法,它把数组当作二叉树来排序。它将数组当作二叉树来管理:
(1)索引0是树的根节点
(2)除根节点外,任意节点N的父节点是N/2
(3)节点L的左子节点是2L
(4)节点R的右子节点是2
R+1

function heapSort(arr){
    var heapSize = arr.length;
    buildHeap(arr);
    while(heapSize > 1){
        heapSize--;
        [arr[0], arr[heapSize]] = [arr[heapSize], arr[0]];
        heapify(arr, heapSize, 0);
    }
    console.log(arr);
}
function buildHeap(arr){
    var heapSize = arr.length;
    for(var i = Math.floor(arr.length / 2); i >= 0; i--){
        heapify(arr, heapSize, i);
    }
}
function heapify(arr, heapSize, i){
    var left = i*2 + 1,
    right = i*2 + 2,
    largest = i;
    if(left < heapSize && arr[left] > arr[largest]){
        largest = left;
    }
    if(right < heapSize && arr[right] > arr[largest]){
        largest = right;
    }
    if(largest !== i){
        [arr[i], arr[largest]] = [arr[largest], arr[i]];
        heapify(arr, heapSize, largest);
    }
};

测试:

heapSort([2,4,1,3]);    //[ 1, 2, 3, 4 ]

时间复杂度:O(nlogn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值