常见的排序算法

742 阅读3分钟

前言

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战”。

常见的几种排序算法。

自我学习,仅供参考。

冒泡排序

bubbleSort.gif 算法步骤

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。

  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

代码实现

var arr = [4,1,6,9,3,2,8,7];

function compare(a, b) {   //比较函数
    if(a < b) return false   //前面的小于后面的,不排序
    else return true   //前面的大于后面的,需要排序
}

function exchange(arr, a, b) {    //交换函数
    var temp = arr[a]
    arr[a] = arr[b]
    arr[b] = temp
}

function bubbleSort(arr) {     //排序函数
    for(var i = 0; i < arr.length; i++) {
        for(var j = 0; j < arr.length - 1 - i; j++){  //j取最后一个 j+1就不存在了 每循环一圈,就不用和后面的大数相比了所以 -i
            if(compare(arr[j], arr[j + 1])) {
                exchange(arr, j, j + 1)
            }
        }
    }
}

sort(arr)
console.log(arr)     //[1, 2, 3, 4, 6, 7, 8, 9]

冒泡排序.png

选择排序

selectionSort.gif 算法步骤

  1. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

  2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

  3. 重复第二步,直到所有元素均排序完毕。 代码实现

var arr = [4,1,6,9,3,2,8,7]

function exchange(arr, a, b) { //交换函数
   var temp = arr[a]
   arr[a] = arr[b]
   arr[b] = temp
}

function selectSort(arr) {    //排序函数
   let len = arr.length  //保存数组长度
   for (let i = 0; i < len - 1; i++) {
      let minIndex = i  //假设最小的是第一个,已排序
      for(let j = i + 1; j < len; j++){  //第一个元素已排序,从第二个元素开始
         if(arr[j] < arr[minIndex]) { // 找最小的数
            minIndex = j            // 保存最小数的索引
         }
      }
      if(i !== minIndex) {
         exchange(arr, i, minIndex)
      }
   }
   return arr
}

console.log(selectSort(arr));     //[1, 2, 3, 4, 6, 7, 8, 9]

选择排序.png

插入排序

类似于玩扑克牌 insertionSort.gif

算法步骤

  1. 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

  2. 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。) 代码实现

var arr = [4,1,6,9,3,2,8,7]

function insertSort(arr) {
   for( var i = 1; i < arr.length; i++) {     //假设第一个元素已经排好,从第二个元素开始
      let curValue = arr[i];       //保存当前元素(值)
      let j = i - 1;        //和当前元素的前一个比较(j是索引)
      while(j >= 0 && curValue < arr[j]) {       // j最小为0 并且 当前元素小于前面元素
         arr[j + 1] = arr[j];       //满足条件 把前面所有比当前元素大的后移一位
         j--;        //终止循环的条件
      }
      arr[j + 1] = curValue ;     //当前元素放在 大于前面元素的后面一位
   }
   return arr
}

console.log(insertSort(arr))     //[1, 2, 3, 4, 6, 7, 8, 9]

插入排序.png

快速排序

quickSort.gif 算法步骤

  1. 从数列中挑出一个元素,称为 "基准"(pivot);

  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序; 总结来说,取一个元素作为leader,遍历数组,小于leader的放入一个数组,大于leader的放入另一个数组。

代码实现

var arr = [4,6,1,9,3,2,8,7];

function quickSort(arr) {
    if(arr == null || arr.length === 0) return [];
    var leader = arr[0];
    var left = [],
        right = [];
    for(var i = 0; i < arr.length; i++) {
        if(arr[i] < leader) left.push(arr[i]);
        else right.push(arr[i])
    }
    left = quickSort(left);
    right = quickSort(right);

    return left.concat(leader,right)
}
console.log(quickSort(arr))     //[1, 2, 3, 4, 6, 7, 8, 9]

快速排序.png

归并排序

算法步骤

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;

  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

  4. 重复步骤 3 直到某一指针达到序列尾;

  5. 将另一序列剩下的所有元素直接复制到合并序列尾。

代码实现

var arr = [4,6,1,9,3,2,8,7];

function mergeSort(arr) {
   let len = arr.length
   if(len < 2) return arr

   let middle = Math.floor(len / 2)     //中间数
   let left = arr.slice(0, middle)         //分成左右两个数组
   let right = arr.slice(middle)
   return merge(mergeSort(left), mergeSort(right))
}

function merge(left, right) {
   let result = []

   while(left.length && right.length) {
      if(left[0] < right[0]) {
         result.push(left.shift())
      } else {
         result.push(right.shift())
      }
   }

   while(left.length) result.push(left.shift())
   while(right.length) result.push(right.shift())

   return result
}

console.log(mergeSort(arr));

归并排序.png

参考

菜鸟教程