排序

冒泡排序

  • 思路
    • 比较所以相邻元素,如果第一个比第二个大,则交换他们
    • 一轮下来,可以保证最后一个数是最大的
    • 执行n-1轮,就可以完成排序
  • 时间复杂度O(n^2)
  1. Array.prototype.bubbleSort = function (config) {
  2. const swap = (j) => {
  3. const tmp = this[j]
  4. this[j] = this[j + 1]
  5. this[j + 1] = tmp
  6. }
  7. const forEach = (i) => {
  8. if (!config || config === 'up') {
  9. // 升序
  10. for (let j = 0; j < this.length - 1 - i; j++) {
  11. if (this[j] > this[j + 1]) swap(j)
  12. }
  13. } else if (config === 'down') {
  14. // 降序
  15. for (let j = this.length - 1 - i; j >= 0; j--) {
  16. if (this[j] < this[j + 1]) swap(j)
  17. }
  18. }
  19. }
  20. for (let i = 0; i < this.length - 1; i++) {
  21. forEach(i);
  22. }
  23. }
  24. const arr = [5, 6, 3, 2, 8];
  25. arr.bubbleSort('down');

选择排序

  • 思路
    • 找到数组中的最小值,选中它并将其放置在第一位
    • 接着找到第二小的值,选中它并将其放置在第二位
    • 以此类推执行n-1
  • 时间复杂度O(n^2) ```javascript Array.prototype.selectionSort = function () { // 升序 let indexMini = 0; for (let i = 0; i < this.length - 1; i++) { for (let j = i; j < this.length; j++) {
    1. if (this[j] < this[indexMini]) {
    2. indexMini = j;
    3. }
    } if (i !== indexMini) {
    1. const tmp = this[i];
    2. this[i] = this[indexMini];
    3. this[indexMini] = tmp;
    } }

}

const arr = [5, 6, 3, 2, 8]; arr.selectionSort();

  1. <a name="zPRVq"></a>
  2. ## 插入排序
  3. - 思路
  4. - 从第二个数**往前比**
  5. - 比它大的就**往后排**
  6. - 依次类推,进行到最后一个数
  7. - 时间复杂度`O(n^2)`
  8. ```javascript
  9. Array.prototype.insertionSort = function () {
  10. // 升序
  11. for (let i = 1; i < this.length; i++) {
  12. const tmp = this[i];
  13. let j = i;
  14. while (j > 0) {
  15. if (this[j - 1] > tmp) {
  16. this[j] = this[j - 1];
  17. } else {
  18. break;
  19. }
  20. j--;
  21. }
  22. this[j] = tmp;
  23. }
  24. }
  25. const arr = [5, 6, 3, 2, 8];
  26. arr.insertionSort();

归并排序

  • 思路
    • 分:把数组劈成两半,再递归地对子数组进行“分”操作,直到分成一个个单独的数
    • 合:把两个数合并成有序数组,再对有序数组进行合并,直到全部的子数组合并成一个完整的数组
      • 新建一个空数组res,用于存放最终排序后的数组
      • 比较两个有序数组的头部,较小者出队并推入res中
      • 如果两个数组还有值,就重复第二步
  • 时间复杂度O(nlogn)
  1. Array.prototype.mergeSort = function () {
  2. // 递归
  3. const dfs = (arr) => {
  4. // 分
  5. if (arr.length === 1) return arr;
  6. const mid = Math.floor(arr.length / 2);
  7. const left = arr.slice(0, mid);
  8. const right = arr.slice(mid, arr.length);
  9. const orderLeft = dfs(left);
  10. const orderRight = dfs(right);
  11. const res = []; // 存放结果
  12. // 合
  13. while (orderLeft.length || orderRight.length) {
  14. if (orderLeft.length && orderRight.length) {
  15. res.push(orderLeft[0] < orderRight[0] ? orderLeft.shift() : orderRight.shift());
  16. } else if (orderLeft.length) {
  17. res.push(orderLeft.shift())
  18. } else {
  19. res.push(orderRight.shift())
  20. }
  21. }
  22. return res;
  23. }
  24. const res = dfs(this);
  25. res.forEach((num, i) => { this[i] = num });
  26. }
  27. const arr = [5, 6, 3, 2, 8];
  28. arr.mergeSort();

快速排序

  • 思路
    • 分区:从数组中任意选择一个“基准”,所有比基准小的元素放在基准前面,比基准大的元素放在基准后面
  • 时间复杂度O(n*logn)
    • 递归的时间复杂度O(logn)
    • 分区操作的时间复杂度O(n)

搜索

顺序搜索

  • 思路
    • 遍历数组
    • 找到目标值相等的元素,就返回它的坐标
    • 遍历结束后,如果没有搜索到目标值,就返回-1
  • 时间复杂度O(n) ```javascript Array.prototype.sequantialSearch = function (item) { for(let i = 0; i < this.length; i++) { if(this[i] === item) {
    1. return i
    } } return -1; }

const res = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].sequantialSearch(3); console.log(res);

  1. <a name="zgqaL"></a>
  2. ## 二分搜索
  3. - 思路——前提数组有序
  4. - 在数组的中间元素开始,如果中间元素正好是目标值,则搜索结束
  5. - 如果目标值大于或小于中间元素,则在大于或小于中间元素的那一半数组中搜索
  6. - 直到找到目标值,没找到返回-1
  7. - 时间复杂度`O(logn)`
  8. ```javascript
  9. Array.prototype.binarySearch = function (item) {
  10. let low = 0;
  11. let high = this.length - 1;
  12. while (low <= high) {
  13. const mid = (low + high) >> 1;
  14. if (this[mid] < item) {
  15. low = mid + 1;
  16. } else if (this[mid] > item) {
  17. high = mid - 1;
  18. } else {
  19. return mid;
  20. }
  21. }
  22. return -1;
  23. }
  24. const res = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].binarySearch(3);
  25. console.log(res);