JS手写六种排序算法

388 阅读2分钟
  • 冒泡排序

    在未排序区域中,从前向后不断对比相邻数据,将较大值不断向后移动,直至移动到未排序区域的最后一位。

    function bubbleSort(arr) {
    
        for(let i = 0; i < arr.length - 1; i++) {
    
            for(let j = 0; j < arr.length - 1 - i; j++) {
    
                if(arr[j] > arr[j + 1]) {
    
                    let temp = arr[j];
    
                    arr[j] = arr[j + 1];
    
                    arr[j + 1] = temp;
    
                 }
    
             }
    
        }
    
    }
    
  • 插入排序

    将第一个数据视为已排序区域,取第一个未排序区域中的数据,从它前一个位置依次向前寻找,直至找到第一个小于等于它的数据,或超出数组范围(已排序区域中没有比它小的值),则将它从未排序区域移除,插入到第一个小于等于它的位置后,或第一位。直至全部排序结束。

    function insetSort(arr) {
    
        for(let i = 1; i < arr.length; i++) {
    
            let index = i;
    
            let temp = arr[i];
    
            while(index > 0 && arr[index - 1] > temp) {
    
                index--;
    
            }
    
            arr.splice(i, 1);
    
            arr.splice(index, 0, temp);
    
        }
    
    }
    
  • 归并排序

    通过递归将数组不断一分为二,直至每个数组只有一个元素,这时数组即为有序的。在合并时因为两个数组都是有序的,只需比较两个有序数组中的第一个元素,将较小的放入合并后的数组中,即可合并出一个有序数组。

    function mergeSort(arr) {
    
        if(arr.length < 2) {
    
            return arr
    
        }
    
        let mid = Math.floor(arr.length / 2);
    
        let leftArr = arr.slice(0, mid);
    
        let rightArr = arr.slice(mid);
    
        return merge(mergeSort(leftArr), mergeSort(rightArr))
    
    }
    
    function merge(leftArr, rightArr) {
    
        let res = [];
    
        while(leftArr.length > 0 && rightArr.length > 0) {
    
            if(leftArr[0] < rightArr[0]) {
    
                res.push(leftArr.shift())
    
            }else {
    
                res.push(rightArr.shift())
    
            }
    
        }
    
        if(leftArr.length != 0) {
    
            res.push(...leftArr)
    
        }
    
        if(rightArr.length != 0) {
    
            res.push(...rightArr)
    
        }
    
        return res
    
    }
    
  • 选择排序

    遍历未排序区域,通过对比相邻数据,记录较小值的下标,每遍历一遍就能找出未排序区域中最小的数据,将记录的未排序区域的最小值与未排序区域的第一个元素交换位置,该位为有序,未排序区域长度减一,直至完成排序。

    function changeSort(arr) {
    
        for(let i = 0; i < arr.length - 1; i++) {
    
            let index = i;
    
            for(let j = i + 1; j < arr.length; j++) {
    
                if(arr[j] < arr[index]) {
    
                    index = j;
    
                }
    
            }
    
            let temp = arr[i];
    
            arr[i] = arr[index];
    
            arr[index] = temp;
    
        }
    
    }
    
  • 希尔排序

    优化的插入排序。并不直接对整个数组进行插入排序,而是将数组切分为 arr.length/2 组至一组,对每组进行插入排序,当切分为一组时完成排序。

    function shellSort(arr) {
    
        for(let gap = Math.floor(arr.length / 2); gap > 0; gap = Math.floor(gap / 2)) {
    
            for(let i = gap; i < arr.length; i ++) {
    
                let index = i;
    
                let temp = arr[i];
    
                while(index > 0 && arr[index - gap] > temp) {
    
                    index -=gap;
    
                }
    
                arr.splice(i, 1);
    
                arr.splice(index, 0, temp);
    
            }
    
        }
    
    }
    
  • 快速排序

    从未排序区域中取一个值视为基准值(通常取最中间位置的值),将剩余数据中,小于该值的数据放入leftArr中,将大于等于该值的数据放入rightArr中,此时基准值即为有序。再不断对leftArr和rightArr分别重复该步骤,直至数组中只有一个元素(数组中只有一个元素时为有序数组),将leftArr、基准值、rightArr按顺序合并成一个数组,该数组即为有序。

    function quickSort(arr) {
    
        if(arr.length < 2) {
    
            return arr
    
        }
    
        let index = Math.floor(arr.length / 2);
    
        let temp = arr.splice(index, 1)[0];
    
        let leftArr = [];
    
        let rightArr = [];
    
        for(let i = 0; i < arr.length; i++) {
    
            if(arr[i] < temp) {
    
                leftArr.push(arr[i]);
    
            }else {
    
                rightArr.push(arr[i]);
    
            }
    
        }
    
        return [...quickSort(leftArr), temp, ...quickSort(rightArr)]
    
    }