几种排序算法

111 阅读1分钟

快速排序

基本思想:(分治)

  • 先从数列中取出一个数作为key值,用来比较
  • 将比这个数小的数全部放在它的左边,大于它的数全部放在它的右边
  • 对左右的两个小数列重复第二步的操作,直到各区间只剩一个数
let quickSort = arr => {
  if(arr.length <= 1){ return arr }
  let pivotIndex =Math.floor(arr.length / 2)
  let pivot = arr.splice(pivotIndex,1)[0]
  let left = [],right = []
  for(let i = 0 ; i < arr.length ; i++){
    if(arr[i] < pivot) { 
      left.push(arr[i])
    }else{
      right.push(arr[i])
    }
  }
  return quickSort(left).concat([pivot],quickSort(right))
}

计数排序

基本思路

  • 用一个哈希表作记录
  • 发现数字N就记N:1,如果再一次发现就加1
  • 最后把哈希表的key全部打印出来,假如N:M,那么N需要打印M次
let countSort = arr => {
  let hashTable = {} , max = 0 , result = []
  for(let i = 0; i < arr.length; i++){
    if(!(arr[i] in hashTable)){ // in 判断hashTable中是否含有arr[i]
      hashTable[arr[i]] = 1
    }else{
      hashTable[arr[i]]+=1
    }
    if(arr[i] > max){ max = arr[i] }
  }
  for(let j = 0;j <= max ;j++ ){
    if(j in hashTable){
      for(let i =0 ; i < hashTable[j]; i++){
        result.push(j)
      }
    }
  }
  return result
}

冒泡排序

基本思想:相邻的两个数比大小,较大的数下沉,较小的数冒起来

let bubbleSort = arr => {
  for(let i = 0;i < arr.length-1; i++ ){
    for(let j = 0;j < arr.length-i; j++){
      if(arr[j] > arr[j+1]){
        arr[j] ^= arr[j+1]
        arr[j+1] ^= arr[j]
        arr[j] ^= arr[j+1]
      }
    }
  }
  return arr
}

选择排序

基本思想

  • 在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
  • 第二次遍历n-2个数,找到最小的数值与第二个元素交换;
  • ......
  • 第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。
let minIndex = (numbers) => {
  let index = 0
  for(let i = 1;i<numbers.length;i++){
    if(numbers[i] < numbers[index]){
      index = i
    }
  }
  return index
}
let swap = (array,i,j) => {
  array[i] ^= array[j]
  array[j] ^= array[i]
  array[i] ^= array[j]
}

let selctionSort = numbers => {
  for(let i = 0;i < numbers.length-1; i++){
    let index = minIndex(numbers.slice(i)) + i 
    if(index !== i){swap(numbers,index,i)}
  }
  return numbers
}

插入排序

基本思路:在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

let insertSort = arr => {
  let index = 0
  for(let i = 1; i < arr.length ; i++){
    index = i
    for(let j = i - 1; j >= 0; j--){
      if(arr[i] < arr[j] ){
        index = j
      }
    }
    arr.splice(index,0,arr[i]);  //插入arr[i]
    arr.splice(i+1,1);  // 由于数组变了,所以原先arr[i]的值到arr[i+1]去了,删掉它
  }
  return arr
}

归并排序

基本思路: 首先考虑下如何将2个有序数列合并。这个非常简单,只要从比较2个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

let mergeSort =  arr => {
  let k = arr.length
  if(k === 1){ return arr }
  let left = arr.slice(0,Math.floor(k/2))
  let right = arr.slice(Math.floor(k/2))
  return merge(mergeSort(left),mergeSort(right))
}
let merge = (a,b) => {
  if(a.length === 0){ return b }
  if(b.length === 0){ return a }
  return a[0] > b[0] ? [b[0]].concat(merge(a,b.slice(1))) : [a[0]].concat(merge(a.slice(1),b))
}