常见的排序算法

123 阅读4分钟

排序算法比较

排序算法

  1. 冒泡排序

    最简单最原始的一个个的比较排序,直接上代码

    let arr = [10, -7, 3, 44, 23, 56, 73, 4, 11, 6];
    
    function bubbleSort(arr) {
        let len = arr.length, temp;
        for (let i = 0; i < len; i++) {
            for (let j = i; j < len; j++) {
                if (arr[i] > arr[j]) {
                    temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }
    bubbleSort(arr);
    
  2. 选择排序

    选择排序的技巧在于,每次找最小或最大的数字,将它放到合适的位置上

    function select(arr) {
        let len = arr.length,
            minIndex = 0, temp;
        for (let i = 0; i < len; i++) {
            minIndex = i;
            for (let j = i + 1; j < len; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }
    select(sortArr);
    
  3. 插入排序

    插入排序的技巧在于,数组划分为排序跟未排序的两部分(初始化视数组首位为已排序部分),每次选择未排序的首位在已排序部分寻找合适的位置

    function insert (arr) {
      // 初始化首位视为已排序,所以 index 是 1
      let len = arr.length, prev, index = 1, temp;
      while (index > len) {
        prev = index - 1while (prev >= 0 && arr[prev] > temp) {
          // 如果 跟未排序的数值对比的,比它大,则将它的位置往后移动一位
          arr[prev + 1] = arr[prev];
          prev--;
        }
        // 此时 temp 大于 arr[prev] 但 小于 arr[prev+1]
        // 如 [2,3,5,6],排序是4,那么现在arr[perv]是3,arr[prev+1]是5
        // 所以插到 prev + 1 的位置上
        arr[prev+1] = temp;
      }
      return arr;
    }
    
  4. 希尔排序

    希尔排序,插入排序的改进版本。

    基本思想:先将这个那个待排序的记录序列分割成若干个子序列,分别对子序列进行直接插入排序,待整个序列中的记录基本有序时,再对全体进行一次的插入排序

    由此可知,希尔排序的主要操作有两步:1. 分割 2. 插入排序。

    function shell(arr) {
        let len = arr.length, s = Math.floor(len / 2), index = 0, prev, temp;
        while(s > 0) {
            index = s;
            while(index < len) {
                prev = index;
                temp = arr[index];
                while (prev - s >= 0 && arr[prev - s] > temp) {
                    arr[prev] = arr[prev - s];
                    prev -= s;
                }
                arr[prev] = temp;
                index += s;
            }
            s = Math.floor(s / 2);
        }
    }
    
  5. 归并排序

这张图就是合并排序的思想,步骤方法。

合并排序

// 不断拆分数组,直到数组长度为1,也就是图中的分的阶段
function merge(arr) {
    // console.log(arr);
    let len = arr.length;
    if (len < 2) return arr;
    let middle = Math.floor(arr.length / 2);
    let left = arr.slice(0, middle),
        right = arr.slice(middle);
    return mergeSort(merge(left), merge(right));
}

// 左右数组对比,合并有序数组,也就是图中治的部分
function mergeSort(left, right) {
    let result = [];
    // left跟right其中之一可能有undefined的情况,所以要判断一下
    while(left && right && left.length && right.length) {
        if (left[0] < right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }

    // 当left,right长度不对等时,单独处理各自
    while(left && left.length) {
        result.push(left.shift());
    }

    while(right && right.length) {
        result.push(right.shift());
    }
    
    return result;
}
  1. 快速排序

    选中基准值,确定这个值在数组中的位置。

    具体方法就是左右指针向中间靠拢,右指针从后往前移动,如果遇到右指针值大于基准值,则向前继续移动,直到定位在小于或等于基准值的位置;左指针从前往后移动,如果遇到小于基准值的,继续向后移动,直到定位在大于或等于基准值的位置。想要达到的效果就是,基准值的左边都是小于或等于基准值的,右边都是大于或等于基准值的。

    注意点:

    1. 判断完成的标志 if (l >= r) return arr;
    2. 基准值选中是首位,那么必须先从后往前寻找,一直找到小于基准值的位置,然后从前往后着,一直找到大于基准值的位置,交换两个位置的值
    3. 当找到跟基准值相同的值且还在循环找值时,将该左指针往前挪一位,进行下一轮的判断
    4. 递归便利
    function qSort(arr, l, r) {
    		// 1. 判断完成的标志
        if (l >= r) return arr;
        let i = l, j = r, prev;
      	// 选中基准值
        let current = arr[l];
        while (i !== j) {
          	// 从后往前找
            while (arr[j] > current && i < j) j--;
          	// 从前往后着
            while (arr[i] < current && i < j) i++;
            if (i < j) {
                if (arr[i] !== arr[j]) {
                    prev = arr[j];
                    arr[j] = arr[i];
                    arr[i] = prev;
                } else {
                  	// 若相同,则左指针(从前往后的指针)往后挪一位,即数组的下一个位置
                    i++;
                }
            }
        }
    		// 4. 递归
        qSort(arr, 0, i-1);
        qSort(arr, i+1, r);
    }
    

参考

十大经典排序算法

十大经典排序算法 cnblog