冒泡排序

  1. function buttleSort(arr) {
  2. const len = arr.length;
  3. if (len <= 1) return arr;
  4. for(let i = 0; i < len; i++) {
  5. let flag = true;
  6. // 从前往后冒泡,所以已经处理的数据不用再访问
  7. // 由于每次遍历都会访问 j + 1项;等于提前遍历了后一项
  8. // 所以终止条件是 len - i - 1;
  9. for(let j = 0; j < len - i - 1; j++) {
  10. if (arr[j] > arr[j + 1]) {
  11. [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
  12. flag = false;
  13. }
  14. }
  15. // 当前循环排序没有改变,flag=true,数组排序完成;
  16. if (flag) return arr;
  17. }
  18. return arr;
  19. }

快排

  1. /**
  2. *
  3. * @param arr Number[] 待排序数组
  4. */
  5. function quickSort(arr) {
  6. _quick(arr, 0, arr.length - 1);
  7. console.log(arr);
  8. }
  9. /**
  10. *
  11. * @param arr Number[]
  12. * @param left Number 左边界
  13. * @param right Number 右边界
  14. * 对 arr[l...r] 部分进行快速排序
  15. */
  16. function _quick(arr, left, right) {
  17. if (left >= right) {
  18. return;
  19. }
  20. let index = partition(arr, left, right);
  21. _quick(arr, left, index - 1);
  22. _quick(arr, index + 1, right);
  23. }
  24. /**
  25. *
  26. * @param arr Number[]
  27. * @param left Number 左边界
  28. * @param right Number 右边界
  29. * @returns Number 索引值p,使得arr[left...p] < arr[p] < arr[p+1...right]
  30. * 对 arr[l...r] 部分进行快速排序
  31. */
  32. function partition(arr, left, right) {
  33. let index = left;
  34. let target = arr[left];
  35. for(let i = left + 1; i <= right; i++) {
  36. if (arr[i] < target) {
  37. // 如果当前值小于基准值的话,就交换到index + 1的位置去
  38. swap(arr, i, index + 1);
  39. index++;
  40. }
  41. }
  42. // 把基准值交换至所有小于基准值的后边 既 index
  43. swap(arr, left, index);
  44. return index;
  45. }
  46. function swap(arr, i, j) {
  47. const temp = arr[i];
  48. arr[i] = arr[j];
  49. arr[j] = temp;
  50. }

快排-三路

  1. /**
  2. * 三路快排,将arr[l...r] 分为 < v; === v; > v 三部分
  3. * 之后递归的对 < v, > v 两部分三路快排
  4. * @param arr Number[]
  5. */
  6. function quickSort(arr) {
  7. _quick(arr, 0, arr.length);
  8. return arr;
  9. }
  10. /**
  11. * @param arr Number[]
  12. * @param left Number 左边界
  13. * @param right Number 右边界
  14. * 对 arr[l...r] 部分进行快速排序
  15. */
  16. function _quick(arr, l, r) {
  17. if (l >= r) return;
  18. let [lb, rb] = partition(arr, l, r);
  19. _quick(arr, l, lb);
  20. _quick(arr,rb, r);
  21. }
  22. /**
  23. * @param arr Number[]
  24. * @param left Number 左边界
  25. * @param right Number 右边界
  26. * @returns [lb, rb] Number[], 返回索引值[lb, rb],使得arr[l...lb] < arr[lb] < arr[rb...r]
  27. * 对 arr[l...r] 部分进行快速排序
  28. */
  29. function partition(arr, left, right) {
  30. let leftBound = left; // arr[left + 1...leftBound] < target
  31. let rigthBound = right + 1; // arr[rigthBound...r] > target
  32. let index = left + 1;
  33. let target = arr[left];
  34. while(index < rigthBound) {
  35. if (arr[index] < target) {
  36. swap(arr, index, leftBound + 1);
  37. leftBound++;
  38. index++
  39. } else if (arr[index] > target) {
  40. swap(arr, index, rigthBound - 1);
  41. rigthBound--;
  42. } else {
  43. index++
  44. }
  45. }
  46. swap(arr, left, leftBound);
  47. return [leftBound - 1, rigthBound];
  48. }
  49. function swap(arr, i, j) {
  50. const temp = arr[i];
  51. arr[i] = arr[j];
  52. arr[j] = temp;
  53. }

快排-空间

  1. function quickSort(arr) {
  2. const len = arr.length;
  3. if (len <= 1) return arr;
  4. const left = [];
  5. const right = [];
  6. const tag = arr[0];
  7. for(let i = 1; i < len; i++) {
  8. if (arr[i] < tag) {
  9. left.push(arr[i])
  10. } else {
  11. right.push(arr[i])
  12. }
  13. }
  14. return [...quickSort(left), tag, ...quickSort(right)]
  15. }

选择排序

  1. /**
  2. * 选择排序:每一次从待排序数组中,选择最小(大)的元素作为首元素,直到排完
  3. * @param arr number[] 待排序数组
  4. *
  5. * 1、有 n 个元素,由于内循环每次获取 i+1 的元素,因此外循环 n-1 次;
  6. * 2、选择最小(大)的元素,放到每次循环的第一位;
  7. * 3、重复过程至 n-1位
  8. */
  9. function selectSort(arr: number[]) {
  10. const len = arr.length;
  11. if (len <= 1) return arr;
  12. for (let i = 0; i < len - 1; i++) {
  13. let temp = i;
  14. for (let j = i + 1; j < len; j++) {
  15. if (arr[j] < arr[temp]) {
  16. temp = j;
  17. }
  18. }
  19. if (temp !== i) {
  20. sawp(arr, temp, i);
  21. }
  22. }
  23. return arr;
  24. }

插入排序

  1. /**
  2. * 插入排序:通过构建有序数组、对于未排序的数据,在已排序的数组中从后往前比较,找到合适的位置插入;
  3. * @param arr number[] 待排序数组
  4. *
  5. * 1、从第一个元素开始,此元素被认定为已被排序;
  6. * 2、从第二个元素开始,在已排序的数组中从后往前比较;
  7. * 3、如果内循环 while 的 arr[pre] 元素大于外循环 for 的 arr[i] 元素,将该元素移至 pre+1;
  8. * 4、while循环内重复步骤3,直至找到 pre < 0 或 arr[pre] <= arr[i];
  9. * 5、for循环;
  10. */
  11. function insertSort(arr: number[]) {
  12. const len = arr.length;
  13. if (len <= 1) return arr;
  14. for (let i = 0; i < len; i++) {
  15. const cur = arr[i];
  16. let pre = i - 1;
  17. while (pre >= 0 && arr[pre] > cur) {
  18. sawp(arr, pre + 1, pre);
  19. pre--;
  20. }
  21. // 由于跳出 while 循环的条件为:pre < 0 或 arr[pre] <= cur
  22. // 所以当前循环的 arr[i] 应该插入至 pre + 1;
  23. // arr[pre + 1] = cur;
  24. // 因为 while 是在有序数组内进行循环,所以初始 arr[pre+1] 就是 cur
  25. }
  26. return arr;
  27. }

归并排序

  1. function mergeSort(arr: number[]) {
  2. const len = arr.length;
  3. if (len <= 1) return arr;
  4. const mid = Math.ceil(len / 2);
  5. const left = arr.splice(0, mid);
  6. const right = arr.splice(mid);
  7. const leftA = mergeSort(left);
  8. const rightA = mergeSort(right);
  9. return merge(leftA, rightA);
  10. }
  11. function merge(left: number[], right: number[]) {
  12. const res: any[] = [];
  13. while (left.length && right.length) {
  14. if (left[0] <= right[0]) {
  15. res.push(left.shift());
  16. } else {
  17. res.push(right.shift());
  18. }
  19. }
  20. while (left.length) {
  21. res.push(left.shift());
  22. }
  23. while (right.length) {
  24. res.push(right.shift());
  25. }
  26. return res;
  27. }