排序算法 JS实现

原文引用自这里,这里只是我自己的学习的补充以及笔记

插入排序

时间复杂度,O(N2

  • 插入排序: 在已经排好序的序列中从后向前扫描
  • 思路:插入排序在比较的时候有两种情况,下一个数更大,下一数更小或相等当下一个数更大的时候,就把下一个数在数组内的索引向后移动一位,相当于是给Temp腾出位置, 继续比较,因为在Tmep之前的数其实都是排好顺序的,所以,当遇到下一位数更小的时候,就可以break出当前循环,并且把Temp赋值给arr[j]
  • 其实再说的简单一点,每一次比较都相当于是互换位置或者不换,只是我们这里用Tmep把比较的数存储起来了 所以只是进行了 互换位置的第一步,向后移动,没有把Temp真正的互换,当遇到了不需要互换的时候,就在进行互换的第二步
  • for循环外层控制未排序元素,内层遍历控制已排序元素
var arr = [5, 6, 3, 1, 8, 7, 2, 4];

function insertSort(arr) {
  for (var i = 1; i < arr.length; i++) {
    var Temp = arr[i];
    for (var j = i; j >= 0; j--) {
      if (arr[j - 1] > Temp) {
        // 如果前面的数比Temp大,那么他们需要后退一位用来给Temp让出一个位置
        arr[j] = arr[j - 1];
      } else {
        // 因为前面已经排好序了所以就直接赋值
        arr[j] = Temp;
        break;
      }
    }
  }
  return arr;
}
console.log(insertSort(arr));

选择排序

时间复杂度,O(N2

  • 选择排序:在没有排好序的序列中选择最小的放入到排好序的序列的后方
  • 思路:整个数组分为两个部分已经排好序的前部分a,未排好序的后部分b, 每次循环从b的第一个数字开始,选择出最小的数字,交换b的第一个数字和最小的数字,依次推进,直到b部分的长度为0
  • 外循环为b的第一个数字,内循环进行比较
  • minValue为最小数字,minIndex为最小数字的索引用于后面交换,temp交换数字时暂时存储
var arr = [5, 1, 6, 3, 1, 8, 7, 2, 4];

function selectSort(arr) {
var minValue, minIndex, temp;
  for (var i = 0; i < arr.length - 1; i++) {
    minIndex = i; // 每次要进行重置,否则如果当b的第一个数字就是最小的值的时候,minIndex不会进行操作,会保留上次循环的值,造成错误
    minValue = arr[i];
    for (var j = i + 1; j < arr.length; j++) {
      if (arr[j] < minValue) {
        minIndex = j;
        minValue = arr[minIndex];
      }
    }
    // 当b的第一个数字不是最小的值的时候,才进行交换
    if (minIndex !== i) {
      temp = arr[i];
      arr[i] = minValue;
      arr[minIndex] = temp;
    }
  }
  return arr;
}
console.log('选择排序' + selectSort(arr2));

归并排序

时间复杂度,O(nlogn)

  • 选择排序,把数组细分到最小化,排序后再组合在排序,从n个数字→n/2个组合→n个数字
  • 思路:由于要不停的拆分数组在比较拆分在比较,可以感觉到,应该是有大量重复的工作的,所以,根据答案可知运用了递归方法,通过两个函数划分功能
  • mergeSort把数组拆分开,并且递归调用自己,直到数组被划分为最完全状态。每一次的拆分调用merge方法,进行排序,merge对拆分出的两个数组排序比较,通过依次比较两个数组中的数字排序,最后concat两个数组并返回
  • merge依次比较,从两个数组的0号元素开始比较,每得到一个结果push进一个新的数组中,并把这个元素从原数组中shift掉,继续比较“0”号元素
function merge(arrLeft, arrRight) {
  var newArr = [];

  while (arrLeft.length && arrRight.length) {
    if (arrLeft[0] > arrRight[0]) {
      newArr.push(arrRight.shift());
    } else {
      newArr.push(arrLeft.shift());
    }
  }
  // 当left和right中其中有一个率先排序完成,剩余的还未push进newArr的数组就直接连接到temp中
  return newArr.concat(arrLeft, arrRight);
}
// 拆分  
function mergeSort(arr) {
  // 递归结束条件
  if (arr.length === 1) {
    return arr;
  }

  var mid = Math.floor(arr.length / 2), // 平均分配两个数组,使用floor是因为保证前一个数组都是偶数,假如有奇数个数字,只会留在最后
    left = arr.slice(0, mid),
    right = arr.slice(mid);

  return merge(mergeSort(left), mergeSort(right));
}
console.log('归并排序' + mergeSort(arr3));

冒泡排序

时间复杂度,O(N2

  • 冒泡排序:遍历数组,每次循环,把最小的数放到开头
  • 思路:每进行一次循环就把最大的数放到末尾,所以每次比较相邻的两个数字,交换或者不交换
  • 循环的次数每次减少一次,比如第一次排序完成后,最后一个数就不参与排序了
 var arr4 = [5, 1, 6, 3, 1, 8, 7, 2, 4];
// 冒泡排序
function bubbleSort(arr) {
  var temp;

  for (var i = 0; i < arr.length-1; i++) {
    for (var j = arr.length-1; j > i; j--) {
      if (arr[j] < arr[j - 1]) {
        temp = arr[j];
        arr[j] = arr[j - 1];
        arr[j - 1] = temp;
      }
    }
  }
  return arr;
}
console.log('冒泡排序' + bubbleSort(arr4));

快速排序

时间复杂度,O(nlogn)

  • 快速排序,选择比较标准值,比标准值大的放在右边,小的放在左边
  • 思路:每次排序,选择一个标准值,以及一段比较值,比如从arr[0]到arr[9],每次循环把这一段值分为比标准值大比标准值小,多次递归排序,最后得到结果。关键在于选择递归拆分点,也就是每次要得到标准值在数组中的位置index。初始的时候,标准值为最右侧的值,index为最左侧,当每次比较的时候,有arr[i]比标准值小,就交换arr[i]和arr[index],并且此时可以知道,index需要+1, 通俗来说就是,现在至少有一个值比标准值小了,所以标准值最后存放的位置至少+1,循环完了以后,在把标准值放入到arr[index]中,就完成了一次操作
var arr5 = [5, 1, 6, 3, 1, 8, 7, 6, 2, 4];
// 快速排序
function quickSort(arr) {
  function swap(arr, index, i) {
    var temp = arr[index];
    arr[index] = arr[i];
    arr[i] = temp;
  }

  function partition(arr, left, right) {
    var index = left;
    var pointValue = arr[right];

    for (var i = left; i < right; i++) {
      if (arr[i] < pointValue) {
        swap(arr, index, i);
        index++;
      }
    }
    // 找到标准值最后的位置之后,把标准值放置过来
    swap(arr, index, right);
    return index;
  }

  function sort(arr, left, right) {
    if (left > right) {
      return;
    }
    var index = partition(arr, left, right);
    sort(arr, left, index - 1);
    sort(arr, index + 1, right);
  }

  sort(arr, 0, arr.length - 1);
  return arr;
}
console.log('快速排序' + quickSort(arr5));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值