写一个方法实现“交换排序算法”,并解释下时间复杂度和空间复杂度

/**
 * 交换排序(冒泡排序)
 *
 * @param {Array<number>} arr 待排序的数组
 * @returns {Array<number>} 排序后的数组
 */
function exchangeSort(arr) {
  const n = arr.length;
  let swapped; // 优化:如果一趟没有交换,说明已经有序

  for (let i = 0; i < n - 1; i++) {
    swapped = false; // 每趟开始前重置 swapped
    for (let j = 0; j < n - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        // 交换元素
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // ES6 解构赋值
        swapped = true;
      }
    }
    if (!swapped) {
      // 如果没有交换,说明已经有序,提前退出
      break;
    }
  }

  return arr;
}


// 示例用法:
const unsortedArray = [5, 2, 9, 1, 5, 6];
const sortedArray = exchangeSort(unsortedArray);
console.log(sortedArray); // 输出: [1, 2, 5, 5, 6, 9]


/**
 *  时间复杂度和空间复杂度分析:
 *
 *  时间复杂度:
 *    - 最好情况:O(n)  当输入数组已经排好序时,只需遍历一次,没有交换操作。因为添加了 swapped 标记,一趟下来没有交换就提前退出。
 *    - 平均情况:O(n^2)  需要遍历 n-1 趟,每趟平均比较 n/2 次。
 *    - 最坏情况:O(n^2)  当输入数组是逆序时,需要进行最多的比较和交换操作。
 *
 *  空间复杂度:O(1)  算法只使用了常数个额外变量(n, swapped, i, j),与输入数组的大小无关,因此空间复杂度为常数级别。
 *  属于原地排序算法。
 */

代码解释:

  1. exchangeSort(arr) 函数: 接收一个数字数组 arr 作为输入。
  2. 外层循环 for (let i = 0; i < n - 1; i++): 控制排序的趟数,一共需要 n-1 趟。
  3. swapped 标记: 用于优化,如果一趟循环中没有发生交换,说明数组已经有序,可以提前结束排序。
  4. 内层循环 for (let j = 0; j < n - 1 - i; j++): 在每一趟中,比较相邻元素并交换它们的位置,使得最大的元素“冒泡”到数组的末尾。 每一趟过后,最大的元素都会被放到正确的位置,因此内层循环的范围逐渐减小。
  5. [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];: 使用 ES6 解构赋值简洁地交换两个元素的值。
  6. if (!swapped): 检查是否进行了交换,如果没有,说明数组已经有序,提前退出循环。
  7. return arr;: 返回排序后的数组。

关键点:

  • 冒泡排序: 交换排序也称为冒泡排序,因为它像气泡一样,较大的元素会逐渐“冒泡”到数组的末尾。
  • 原地排序: 冒泡排序是原地排序算法,因为它直接在原始数组上进行操作,不需要额外的空间来存储数组的副本。
  • 稳定性: 冒泡排序是稳定的排序算法,这意味着如果数组中存在相等的元素,它们的相对顺序在排序后不会改变。

这个改进的版本通过 swapped 标记进行优化,在最好情况下(数组已经有序)时间复杂度可以达到 O(n)。 这使得它在处理部分有序的数组时效率更高.

希望这个解释能够帮助你理解交换排序算法(冒泡排序)的实现、时间复杂度和空间复杂度。

posted @   王铁柱6  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示