排序算法的评价指标

  • 时间效率:排序算法的时间复杂度
  • 空间效率:排序算法需要的辅助内存
  • 稳定性:相等元素在完成排序后的相对顺序是否发生改变
  • 自适应性:排序算法能否利用输入数据的已有顺序来减少计算量

选择排序

从未排序区间选择最下小的元素,将其放到已排序区间的末尾。时间复杂度 $O(n^2)$ , 空间复杂度 $O(1)$,不稳定排序

void selectionSort(vector<int>& nums) {
  int n = nums.size();
  for (int i = 0; i < n - 1; ++i) {
    int k = i;
    for (int j = i + 1; j < n; ++j) {
      if (nums[j] < nums[k]) {
        k = j;
      }
    }
    
    swap(nums[k], nums[i]);
  }
}

image-20260728171719938

image-20260728171727728

冒泡排序

遍历数组,每次将最大的元素移动到最右端。时间复杂度 $O(n^2)$ , 空间复杂度 $O(1)$,稳定排序

void bubbleSort(vecotr<int>& nums) {
  for (int i = nums.size() - 1; i > 0; --i) {
    bool flag = false;
    for (int j = 0; j < i; ++j) {
      if (nums[j] > nums[j + 1]) {
        swap(nums[j], nums[j + 1]);
        flag = true;
      }
    }
    
    if (!flag) {
      break;
    }
  }
}

image-20260728172434558

插入排序

在未排序区间选择一个基准元素(一般选最左侧),将元素与左侧排序区间的元素比较,并将其排序到指定位置。时间复杂度 $O(n^2)$ , 空间复杂度 $O(1)$,稳定排序

void insertionSort(vecotr<int>& nums) {
  for (int i = 1; i < nums.size(); ++i) {
    int base = nums[i], j = i - 1;
    while ( j >= 0 && nums[j] > base) {
      nums[j + 1] = nums[j];
      --j;
    }
    
    nums[j + 1] = base;
  }
}

image-20260728173845794

快速排序

选取数组最左侧元素作为哨兵,i和j分别从两端向中间靠拢,将大数移到右边,小数移到左边,循环直到 i j相遇。时间复杂度 $O(n\log n)$ , 空间复杂度 $O(n)$,非稳定排序

int partition(vector<int>& nums, int left, int right) {
  int i = left, j = right;
  while(i < j) {
    while ( i < j && nums[i] >= nums[left]) --j;
    while ( i < j && nums[i] <= nums[left]) ++i;
    swap(nums[i], nums[j]);
  }
  return i;
}

void quickSort(vector<int>& nums, int left, int right) {
  if (left >= right) return;
  int pivot = partition(nums, left, right);
  quickSort(nums, left, pivot - 1);
  quickSort(nums, pivot + 1, right);
}

image-20260728174546330

image-20260728174600998

归并排序

计算数组中点mid,递归划分子数组,直到子数组长度为1,然后自底向顶将子数组合并。时间复杂度 $O(n\log n)$ , 空间复杂度 $O(n)$,稳定排序

image-20260728175259032

void merge(vector<int>& nums, int left, int mid, int right) {
  vector<int> tmp(right - left + 1);
  int i = left, j = mid + 1, k = 0;
  while (i <= mid && j <= right) {
    if (nums[i] <= nums[j])
      tmp[k++] = nums[i++];
    else
      tmp[k++] = nums[j++];
  }
  
  while (i <= mid) tmp[k++] = nums[i++];
  while (j <= right) tmp[k++] = nums[j++];
  
  for (k = 0; k < tmp.size(); ++k) {
    nums[left + k] = tmp[k];
  }
}

void mergeSort(vector<int>& nums, int left, int right) {
  if (left >= right) return;
  
  int mid = left + (right - left)/2;
  mergeSort(nums, left, mid);
  mergeSort(nums, mid + 1, right);
  
  merge(nums, left, mid, right);
}

image-20260728175311286

堆排序

桶排序

计数排序

基数排序