• 前端对普通数字数组排序示例


    1. arr.sort(fn)

    1. // 升序排序
    2. arr.sort((a, b) => a - b);
    3. // 降序排序
    4. arr.sort((a, b) => b - a);

    2. 冒泡排序

    冒泡排序-升序原理:

    eg: [1, 6, 7, 9, 10, 3, 4, 5, 2]

    1) 先遍历第一遍数组, 前一个数字大于后一个数字, 就交换位置, 最后最大值10放在数组的最后, 此时是 [1, 6, 7, 9, 3, 4, 5, 2, 10];

    for (let j = 0; j < arr.length-1; j++) {
                preNum = arr[j];
                const nextNum = arr[j + 1];
                if (preNum > nextNum) { // 左边的数字大于右边的数字,交换位置
                    // 数字小的往前挪, 数字大的往后挪
                    arr[j] = nextNum;
                    arr[j + 1] = preNum;
                }
            }

    2) 第二遍就是: 前一个数字大于后一个数字, 就交换位置, 最后第二大的值放在数组的倒数第二位, 此时是 [1, 6, 7, 3, 4, 5, 2, 910];

    for (let j = 0; j < arr.length-2; j++) {
                preNum = arr[j];
                const nextNum = arr[j + 1];
                if (preNum > nextNum) { // 左边的数字大于右边的数字,交换位置
                    // 数字小的往前挪, 数字大的往后挪
                    arr[j] = nextNum;
                    arr[j + 1] = preNum;
                }
            }

    3) 第三遍就是: 前一个数字大于后一个数字, 就交换位置, 最后第三大的值放在数组的倒数第三位, 此时是 [1, 6, 3, 4, 5, 2, 7, 9, 10];

    for (let j = 0; j < arr.length-3; j++) {...}

    以此类推...

    4) 最后一遍: 前一个数字大于后一个数字, 就交换位置, 最后第2小的值放在数组的第2位, 此时是 [1, 2, 3, 4, 5, 6, 7, 9, 10]

    for (let j = 0; j < 1; j++) {...}

    5) 因为for (let j = 0; j < x; j++) {...}; 推导可知x的值范围是(0, arr.length-1];

    所以:

    for (let j = arr.length - 1; i > 0; i--) {

            for (let j = 0; j < i; j++) {...}

    }

    

    排序.js:14 第1次计算:

    1. (9) [1, 6, 7, 9, 3, 4, 5, 2, 10]

    排序.js:14 第2次计算:

    1. (9) [1, 6, 7, 3, 4, 5, 2, 9, 10]

    排序.js:14 第3次计算:

    1. (9) [1, 6, 3, 4, 5, 2, 7, 9, 10]

    排序.js:14 第4次计算:

    1. (9) [1, 3, 4, 5, 2, 6, 7, 9, 10]

    排序.js:14 第5次计算:

    1. (9) [1, 3, 4, 2, 5, 6, 7, 9, 10]

    排序.js:14 第6次计算:

    1. (9) [1, 3, 2, 4, 5, 6, 7, 9, 10]

    排序.js:14 第7次计算:

    1. (9) [1, 2, 3, 4, 5, 6, 7, 9, 10]

    排序.js:14 第8次计算:

    1. (9) [1, 2, 3, 4, 5, 6, 7, 9, 10]

    最后一次不用计算了, 最小值就是1

    [1, 2, 3, 4, 5, 6, 7, 9, 10]

    冒泡排序--普通双层遍历循环版本:

    1. // 冒泡排序-升序
    2. const bubleSort = (arr) => {
    3. let preNum = null;
    4. // 之所以i>0, 因为排序交互位置到最后两个的时候, 只需要比较一次就行了, 最后那个数字不必比较了
    5. for (let i = arr.length - 1; i > 0; i--) {
    6. for (let j = 0; j < i; j++) {
    7. preNum = arr[j];
    8. const nextNum = arr[j + 1];
    9. if (preNum > nextNum) { // 左边的数字大于右边的数字,交换位置
    10. // 数字小的往前挪, 数字大的往后挪
    11. arr[j] = nextNum;
    12. arr[j + 1] = preNum;
    13. }
    14. }
    15. }
    16. return arr;
    17. }
    18. // 冒泡排序-降序
    19. const bubleSort = (arr) => {
    20. let preNum = null;
    21. // 之所以i>0, 因为排序交互位置到最后两个的时候, 只需要比较一次就行了, 最后那个数字不必比较了
    22. for (let i = arr.length - 1; i > 0; i--) {
    23. for (let j = 0; j < i; j++) {
    24. preNum = arr[j];
    25. const nextNum = arr[j + 1];
    26. if (preNum < nextNum) { // 左边的数字小于右边的数字,交换位置
    27. // 数字大的往前挪, 数字小的往后挪
    28. arr[j] = nextNum;
    29. arr[j + 1] = preNum;
    30. }
    31. }
    32. }
    33. return arr;
    34. }

    冒泡排序-升序-递归

    1. // 冒泡排序-升序
    2. const bubleSort0 = (arr, i = arr.length - 1) => {
    3. let preNum = null;
    4. // 之所以i>0, 因为排序交互位置到最后两个的时候, 只需要比较一次就行了, 最后那个数字不必比较了
    5. for (let j = 0; j < i; j++) {
    6. preNum = arr[j];
    7. const nextNum = arr[j + 1];
    8. if (preNum > nextNum) { // 左边的数字大于右边的数字,交换位置
    9. // 数字小的往前挪, 数字大的往后挪
    10. arr[j] = nextNum;
    11. arr[j + 1] = preNum;
    12. }
    13. }
    14. i--;
    15. if (i > 0) return bubleSort0(arr, i);
    16. return arr
    17. }
    18. // 冒泡(升序排序)
    19. var arr = bubleSort0([1, 6, 7, 9, 10, 3, 4, 5, 2])
    20. console.log(arr, '冒泡排序-升序-递归');
    21. // 冒泡排序-降序
    22. const bubleSort0 = (arr, i = arr.length - 1) => {
    23. let preNum = null;
    24. // 之所以i>0, 因为排序交互位置到最后两个的时候, 只需要比较一次就行了, 最后那个数字不必比较了
    25. for (let j = 0; j < i; j++) {
    26. preNum = arr[j];
    27. const nextNum = arr[j + 1];
    28. if (preNum < nextNum) { // 左边的数字小于右边的数字,交换位置
    29. // 数字大的往前挪, 数字小的往后挪
    30. arr[j] = nextNum;
    31. arr[j + 1] = preNum;
    32. }
    33. }
    34. i--;
    35. if (i > 0) return bubleSort0(arr, i);
    36. return arr
    37. }
    38. // 冒泡(降序排序)
    39. var arr = bubleSort0([1, 6, 7, 9, 10, 3, 4, 5, 2])
    40. console.log(arr, '冒泡排序-升序-递归');

    3.  选择排序

    eg: [6, 7, 9, 10, 3, 4, 5, 2, 1]

    当i等于0时:

    1) min=第一个元素6, 和数组其余的元素比较, 原本的第一位元素6在if (nextNum < preNum){...}中6和第一个比6小的元素3交换了位置,此时是[3, 7, 9, 10, 6, 4, 5, 2, 1];

    2) min变成3,  比3小的第一个元素是2, 此时是[2, 7, 9, 10, 6, 4, 5, 3, 1];

    3) min变成2, 比2小的元素是1, 所以交换位置, 此时是[1, 7, 9, 10, 6, 4, 5, 3, 2];

    5) 往右数没有比1小的元素了, 结束

    当i等于1时:

    1)  min=数组第二个元素7, 和第三个及之后的元素比较, 第一个比7小的元素是6, 交换位置, 此时是: [1, 6, 9, 10, 7, 4, 5, 3, 2];

    2) min变成6, 比6小的第一个元素是4, 此时是[1, 4, 9, 10, 7, 6, 5, 3, 2];

    3) min变成4, 比4小的第一个元素是3, 此时是[1, 3, 9, 10, 7, 6, 5, 4, 2];

    4) min变成3, 比3小的第一个元素是2, 此时是[1, 2, 9, 10, 7, 6, 5, 4, 3];

    5) 往右数没有比2小的元素了, 结束

    当i等于2时:

    1) min等于数组第三个元素9, 和第四个及之后的元素比较, 第一个比9小的元素是7, 此时是[1, 2, 7, 10, 9, 6, 5, 4, 3];

    2) min变成7, 比7小的第一个元素是6, 此时是[1, 2, 6, 10, 9, 7, 5, 4, 3];

    3) min变成6, 比7小的第一个元素是5, 此时是[1, 2, 5, 10, 9, 7, 6, 4, 3];

    4) min变成5, 比7小的第一个元素是4, 此时是[1, 2, 4, 10, 9, 7, 6, 5, 3];

    5) min变成4, 比4小的第一个元素是3, 此时是[1, 2, 3, 10, 9, 7, 6, 5, 4];

    5) 往右数没有比3小的元素了, 结束

    以此类推...

    所以:

    // 小的越来越靠左, 以此类推

    /**

    * 选择排序:

    原理: 给每个位置选择当前元素最小的;

    * 比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,

    * 直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。

    * 选择排序的本质: 每一次大循环就是选出最小的那个值,在选最小值的过程你可以通过下标记录

    * 也可以每次交换值都可以

    */

    选择排序-双层遍历版本:

    1. // 选择排序-升序
    2. const selectSort = arr => {
    3. const len = arr.length;
    4. for (let i = 0; i < len; i++) {
    5. let min = arr[i];
    6. for (let j = i + 1; j < len; j++) {
    7. const nextNum = arr[j];
    8. const preNum = min;
    9. // 如果当前的值比记录的最小值还要小, 就交换这2个数字的位置
    10. if (nextNum < preNum) {
    11. arr[j] = preNum;
    12. min = nextNum; // min被赋值为比较出来的较小值
    13. continue;
    14. }
    15. }
    16. arr[i] = min; // 因为min在内循环被修改了, 所以arr[i]的值应该在跳出内循环后在它自身循环体被修改
    17. }
    18. return arr
    19. }
    20. // 选择(升序排序)
    21. var arr = selectSort([6, 7, 9, 10, 3, 4, 5, 2, 1])
    22. console.log(arr, '选择排序-升序');

    选择排序-递归+for循环

    1. // 选择排序
    2. const selectSort0 = (arr, i=0) => {
    3. const len = arr.length;
    4. let min = arr[i];
    5. for (let j = i + 1; j < len; j++) {
    6. const nextNum = arr[j];
    7. const preNum = min;
    8. console.log(preNum, 'preNum=====')
    9. // 如果当前的值比记录的最小值还要小, 就交换这2个数字的位置
    10. if (nextNum < preNum) {
    11. arr[j] = preNum;
    12. min = nextNum; // min被赋值为比较出来的较小值
    13. continue;
    14. }
    15. }
    16. arr[i] = min; // 因为min在内循环被修改了, 所以arr[i]的值应该在跳出内循环后在它自身循环体被修改
    17. i++;
    18. if(i<=2) selectSort0(arr, i);
    19. return arr
    20. }
    21. // 选择(升序排序)
    22. var arr = selectSort0([6, 7, 9, 10, 3, 4, 5, 2, 1])
    23. console.log(arr, '选择排序-升序00000');

    4. 快速排序:

    如果数组的元素个数小于2个, 返回原数组;

    如果数组元素个数大于等于2个:

    1) flag = 一个标尺元素(一般是第一个元素); left=flag左边的元素组成的数组(初始化); right=flag右边的元素组成的数组(初始化);

    2) 遍历arr, 比flag小的push进left数组, 比flag大的push进right数组

    3) 将left和right数组执行上述(1)和(2)步骤

    4) 使用concat拼接left数组, flag, right数组

    快速排序-for循环+递归+concat

    1. // 快速排序
    2. const quickSort = (arr) => {
    3. const len = arr.length;
    4. if (len < 2) {
    5. return arr;
    6. }
    7. // 选择标尺元素
    8. let flag = arr[0];
    9. let left = [];
    10. let right = [];
    11. let preNum = null;
    12. // 因为flag取的是下标0的元素, 所以遍历从下标1开始
    13. for (let i = 1; i < len; i++) {
    14. preNum = arr[i];
    15. if (preNum < flag) {
    16. // 比flag小的放左边
    17. left.push(preNum);
    18. }
    19. else {
    20. // 比flag大的放右边
    21. right.push(preNum);
    22. }
    23. }
    24. // 进行递归
    25. return quickSort(left).concat(flag, quickSort(right));
    26. }

    快速排序-划分交换in-place

    1. // 快速排列in-place(交换)--划分交换排序:
    2. const quickInPlaceSort = (arr) => {
    3. // 数组指定两个位置进行值交换
    4. let exchange = (arr, i, j) => {
    5. const preNum = arr[i];
    6. const nextNum = arr[j];
    7. arr[i] = nextNum;
    8. arr[j] = preNum;
    9. }
    10. // 完成一次划分交换
    11. let findCenter = (arr, leftIdx, rightIdx) => {
    12. let flag = arr[leftIdx];
    13. let centerIdx = leftIdx + 1;
    14. for (let i = centerIdx; i <= rightIdx; i++) {
    15. if (arr[i] < flag) {
    16. exchange(arr, centerIdx, i); // 交换位置
    17. centerIdx++; // 交换的下标+1
    18. }
    19. }
    20. exchange(arr, leftIdx, centerIdx - 1);
    21. return centerIdx;
    22. }
    23. // 递归排序
    24. let sort = (arr, leftIdx, rightIdx) => {
    25. if (leftIdx < rightIdx) {
    26. let center = findCenter(arr, leftIdx, rightIdx);
    27. sort(arr, leftIdx, center - 1);
    28. sort(arr, center, rightIdx);
    29. }
    30. }
    31. sort(arr, 0, arr.length - 1);
    32. return arr;
    33. }
    34. var arr = quickInPlaceSort([1, 6, 7, 9, 10, 3, 4, 5, 2]);
    35. console.log(arr, '快速排序-升序-划分交换'); // [1, 2, 3, 4, 5, 6, 7, 9, 10] '快速排序-升序-划分交换'
    36. console.log('-----------------------------------------');

  • 相关阅读:
    Pytorch 下 TensorboardX 使用
    【C语言】利用数组处理批量数据(一维数组和二维数组)
    HTML+CSS+JS网页设计期末课程大作业—— 艺术官网17页(包含登陆注册)
    【C++初阶】小白入门C++
    AVL树的底层实现
    2022年应届毕业生就业率惨淡怎么办?不要错过多金的数据科学行业
    Sentinel使用教程
    Spring Boot+Vue3前后端分离实战wiki知识库系统之前后端交互整合
    day04_java基础
    JSP SSH毕业论文管理统myeclipse开发mysql数据库MVC模式java编程网页设计
  • 原文地址:https://blog.csdn.net/qq_42750608/article/details/134019466