Skip to content

Latest commit

 

History

History
265 lines (216 loc) · 6.23 KB

排序.md

File metadata and controls

265 lines (216 loc) · 6.23 KB

排序算法小结

需掌握的排序算法

排序算法(冒泡排序、选择排序、计数排序、快速排序、插入排序、归并排序)
二分查找法
翻转二叉树

imgs imgs

排序算法的稳定性

若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的

冒泡排序(O(n^2))

将最大数置底

function swap(myArray, p1, p2){
  var temp = myArray[p1];
  myArray[p1] = myArray[p2];
  myArray[p2] = temp;
}
function bubbleSort(myArray){
  var len = myArray.length;
  var i;
  var j;
  var stop;

  for (i = 0; i < len - 1; i++){
    for (j = 0, stop = len - 1 - i; j < stop; j++){
      if (myArray[j] > myArray[j + 1]){
        swap(myArray, j, j + 1);
      }
    }
  }

  return myArray;
}
bubbleSort([1,3,4,2,5,6])

选择排序

将第一个元素和其他元素进行比较,检查完所有元素后,最小的元素会被放到数组的第一个位置

function selectionSort(arr) {
  let min
  let temp
  let length = arr.length
  // 因为到倒数第二个的时候,全部数组就已经排好序了
  for(let i = 0; i < length - 2; i++) {
    min = arr[i]
    for(let j = i + 1; j < length - 1; j++) {
      if(arr[j] < min) {
        min = arr[j]
        swap(arr, j, i)
      }
    }
  }
  return arr
}
selectionSort([1,3,4,2,5,6])

插入排序

插入未排序数到已排序的结果数组

相比于冒泡排序,如果数组已经有序,则时间复杂度为O(n)

function insertionSort(arr) {
  let sortedArrIndex
  let tempValue
  let length = arr.length
  for(let i = 1; i < length - 1; i++) {
    sortedArrIndex = i
    tempValue = arr[i]
    while(sortedArrIndex > 0 && (arr[sortedArrIndex - 1] > tempValue)) {
      // 插入
      arr[sortedArrIndex] = arr[sortedArrIndex - 1]
      sortedArrIndex--
    }
    arr[sortedArrIndex] = tempValue
  }
  return arr
}
console.log(insertionSort([1,3,4,2,5,6]))

归并排序(辅助空间O(n))

把一系列排好序的子序列,合并成一个大的完整有序序列

但是需要较大的空间存储数据,数据较大时容易溢出,是一个自底向上的过程

function merge(left, right) {
  let temp = []
  while(left.length && right.length) {
    if(left[0] > right[0]) {
      temp.push(right.shift())
    } else {
      temp.push(left.shift())
    }
  }
  return temp.concat(left, right)
}

function mergeSort(arr) {
  let length = arr.length
  if(length < 2) {
    return arr
  }
  let mid = Math.floor(length / 2)
  let left = arr.slice(0, mid)
  let right = arr.slice(mid)
  return merge(mergeSort(left), mergeSort(right))
}
console.log(mergeSort([1,3,4,2,5,6]))

希尔排序(时间复杂度:O(nlogN))

是插入排序的升级,分组插入排序。 插入排序间隔为gap的元素,逐渐减少gap至1

function shellSort(arr) {
    if (!arr) {
        return
    }
    let len = arr.length
    let gap = 1
    while (gap < len / 3) {
        gap = 3 * gap + 1; //设置间隔
    }

    while (gap >= 1) {
        for (var i = gap; i < len; i++) {
            for (j = i; j >= gap && arr[j] < arr[j - gap]; j -= gap) {
                swap(arr, j, j - gap);
            }
        }
        gap = (gap - 1) / 3;
    }
    return arr
}

快速排序(时间复杂度:O(nlogN) 辅助空间:O(nlogN))

选择基准元素,将大于和小于基准元素的元素分别放到不同的数组,重复知道数组中只有一个元素

function quickSort(arr) {
    // 为空返回
    if(!arr) {
        return
    }
    // 长度小于等于1代表已完成排序
    if(arr.length <= 1) {
        return arr
    }
    // 选取中间元素,划分数组
    const mid = Math.floor(arr.length / 2)
    const midItem = arr.splice(mid, 1)[0]
    let left = []
    let right = []

    arr.forEach(item => {
        if(item < midItem) {
            left.push(item)
        } else {
            right.push(item)
        }
    })

    // 递归调用
    let _left = quickSort(left)
    let _right = quickSort(right)

    return _left.concat(midItem, _right)
}

// 一行代码实现
function quickSort(a) {
  return a.length <= 1 ? a : quickSort(a.slice(1).filter(item => item <= a[0])).concat(a[0], quickSort(a.slice(1).filter(item => item > a[0])));
}

console.log(quickSort([1,2,4,10,2,9,4,1]))

堆排序(辅助空间:O(1))

堆排序是选择排序的升级版

其优点在于当求M个数中的前n个最大数,和最小数的时候性能极好。所以当从海量数据中要找出前m个最大值或最小值,而对其他值没有要求时,使用堆排序法效果很好

var len;    // 因为声明的多个函数都需要数据长度,所以把len设置成为全局变量

function buildMaxHeap(arr) {   // 建立大顶堆
    len = arr.length;
    for (var i = Math.floor(len/2); i >= 0; i--) {
        heapify(arr, i);
    }
}

function heapify(arr, i) {     // 堆调整
    var left = 2 * i + 1,
        right = 2 * i + 2,
        largest = i;

    if (left < len && arr[left] > arr[largest]) {
        largest = left;
    }

    if (right < len && arr[right] > arr[largest]) {
        largest = right;
    }

    if (largest != i) {
        swap(arr, i, largest);
        heapify(arr, largest);
    }
}

function swap(arr, i, j) {
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

function heapSort(arr) {
    buildMaxHeap(arr);

    for (var i = arr.length-1; i > 0; i--) {
        swap(arr, 0, i);
        len--;
        heapify(arr, 0);
    }
    return arr;
}

console.log(heapSort([1, 10, 9, 8, 1, 3, 4]))