八大排序算法

一、排序算法总览表

排序算法 平均时间 最好 最坏 空间 稳定性
直接插入 O(n²) O(n) O(n²) O(1) 稳定
希尔排序 O(nlogn) O(n) O(n²) O(1) 不稳定
直接选择 O(n²) O(n²) O(n²) O(1) 不稳定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定
冒泡排序 O(n²) O(n) O(n²) O(1) 稳定
快速排序 O(nlogn) O(nlogn) O(n²) O(logn) 不稳定
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定
基数排序 O(d*n) O(d*n) O(d*n) O(n) 稳定

二、插入排序系列

1. 直接插入排序(InsertSort)

思想 :把数组分为有序区 + 无序区 ,每次从无序区取一个数,插入到有序区的正确位置

特点

  • 越接近有序,速度越快
  • 小规模数据效率极高
  • 稳定

代码

cpp 复制代码
void InsertSort(int arr[], int n)
{
    for (int i = 1; i < n; i++)
    {
        int val = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > val)
        {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = val;
    }
}

2. 希尔排序(ShellSort)

思想 :分组插入排序 → 逐步缩小增量 → 最后整体直接插入。突破 O (n²) 的第一种高效排序

特点

  • 效率比直接插入高很多
  • 不稳定

代码

cpp 复制代码
void ShellSort(int arr[], int n)
{
    int gap = n / 2;
    while (gap > 0)
    {
        for (int i = gap; i < n; i++)
        {
            int val = arr[i];
            int j = i - gap;
            while (j >= 0 && arr[j] > val)
            {
                arr[j + gap] = arr[j];
                j -= gap;
            }
            arr[j + gap] = val;
        }
        gap /= 2;
    }
}

三、选择排序系列

3. 直接选择排序(SelectSort)

思想 :每次在无序区选最小的,放到有序区末尾。

特点

  • 数据移动次数少

  • 无论什么数据都是 O(n²)

  • 不稳定

代码

cpp 复制代码
void SelectSort(int arr[], int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		int min = i;
		for (int j = i + 1; j < len; j++)
		{
			if (arr[min] > arr[j])
			{
				min = j;
			}
		}
		if (min != i)
		{
			int tmp = arr[min];
			arr[min] = arr[i];
			arr[i] = tmp;
		}
	}
}

4. 堆排序(HeapSort)

思想 :利用大顶堆 / 小顶堆,每次取堆顶最大值,然后调整堆。

特点

  • 最好最坏都是 O(nlogn)
  • 空间 O(1)
  • 不稳定
  • 大数据量效率极高

代码

cpp 复制代码
// 核心函数1:堆调整(大顶堆)
// 参数:arr-待调整数组,n-堆的大小,i-当前需要调整的节点下标
void heapify(int arr[], int n, int i) {
	int largest = i;          // 初始化最大值为当前节点(父节点)
	int left = 2 * i + 1;     // 左子节点下标
	int right = 2 * i + 2;    // 右子节点下标

	// 1. 找出父节点、左子节点、右子节点中的最大值
	if (left < n && arr[left] > arr[largest]) {
		largest = left;       // 左子节点更大,更新最大值下标
	}
	if (right < n && arr[right] > arr[largest]) {
		largest = right;      // 右子节点更大,更新最大值下标
	}

	// 2. 如果最大值不是当前父节点,交换,并递归调整子堆
	if (largest != i) {
		swap(arr[i], arr[largest]); // 交换父节点和最大值节点
		// 递归调整被交换的子节点(确保子堆也是大顶堆)
		heapify(arr, n, largest);
	}
}

// 核心函数2:堆排序主函数
void heapSort(int arr[], int n) {

	// 步骤1:构建大顶堆(从最后一个非叶子节点开始,向前调整)
	for (int i = (n - 2) / 2; i >= 0; i--) {
		heapify(arr, n, i);
	}

	// 步骤2:交换堆顶与末尾元素 + 调整堆(重复n-1次)
	for (int i = n - 1; i > 0; i--) {
		swap(arr[0], arr[i]);       // 交换堆顶(最大值)和当前末尾元素
		heapify(arr, i, 0);         // 调整剩余i个元素为大顶堆(i是当前堆的大小)
	}

}

四、交换排序系列

5. 冒泡排序(BubbleSort)

思想 :两两比较,大的往后冒,每轮确定一个最大值。

特点

  • 最简单

  • 稳定

  • 效率低

代码

cpp 复制代码
void BubbleSort(int arr[], int n)
{
    for (int i = 0; i < n - 1; i++)
    {
        bool flag = false;
        for (int j = 0; j < n - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                //swap(arr[j], arr[j + 1]);
                tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
                flag = true;
            }
        }
        if (!flag) break;
    }
}

6. 快速排序(QuickSort)

思想 :选基准 → 比基准小的放左边,大的放右边 → 递归左右。目前综合性能最好的内部排序

特点

  • 平均最快
  • 不稳定
  • 数据量大优势明显

代码

cpp 复制代码
// 左右指针划分(标准划分)
int Partion(int* ar, int left, int right)
{
    assert(ar != nullptr);
    int i = left;
    int j = right;
    // 基准选左边第一个
    int tmp = ar[i];
    
    while (i < j)
    {
        // 从右往左找,小于基准的数
        while (i < j && tmp < ar[j]) 
            --j;
        ar[i] = ar[j]; // 填坑
        
        // 从左往右找,大于等于基准的数
        while (i < j && tmp >= ar[i]) 
            ++i;
        ar[j] = ar[i]; // 填坑
    }
    ar[i] = tmp; // 基准归位
    return i;    // 返回基准下标
}
void QuickSort(int arr[], int left, int right)
{
    if (left >= right) return;
    int pivot = Partion(arr, left, right);
    QuickSort(arr, left, pivot - 1);
    QuickSort(arr, pivot + 1, right);
}

五、归并与基数排序

7. 归并排序(MergeSort)

思想:分治法 → 拆分到单个元素 → 两两合并成有序序列。

特点

  • 稳定
  • 非递归也能实现
  • 外部排序常用

代码

cpp 复制代码
void Merge(int arr[], int tmp[], int left, int mid, int right)
{
    int i = left;
    int j = mid + 1;
    int k = left;

    while (i <= mid && j <= right)
    {
        if (arr[i] <= arr[j])
            tmp[k++] = arr[i++];
        else
            tmp[k++] = arr[j++];
    }
    while (i <= mid) tmp[k++] = arr[i++];
    while (j <= right) tmp[k++] = arr[j++];

    for (i = left; i <= right; i++)
        arr[i] = tmp[i];
}

void MergeSort(int arr[], int tmp[], int left, int right)
{
    if (left >= right) return;
    int mid = (left + right) / 2;
    MergeSort(arr, tmp, left, mid);
    MergeSort(arr, tmp, mid + 1, right);
    Merge(arr, tmp, left, mid, right);
}

8. 基数排序(RadixSort)

思想 :按个位、十位、百位 依次分配、收集。不比较大小,只按位分配

特点

  • 稳定
  • 适合整数、字符串
  • 空间消耗大

六、高频试题

  1. 最快的通用排序?

快速排序

  1. 最好最坏都是 O (nlogn)?

堆排序、归并排序

  1. 哪种排序不需要比较?

基数排序

  1. 稳定的排序有哪些?

插入、冒泡、归并、基数。

  1. 快速排序最差情况是什么?

原本有序或逆序 → O (n²)

  1. 归并排序缺点是什么?

空间复杂度 O (n)

  1. 哪种排序越有序越快?

直接插入、冒泡

  1. 哪种排序和数据初始状态无关?

直接选择、堆排序、归并、基数

相关推荐
会编程的土豆2 小时前
【数据结构与算法】哈希表
数据结构·散列表
无敌昊哥战神2 小时前
【算法与数据结构】深入浅出回溯算法:理论基础与核心模板(C/C++与Python三语解析)
c语言·数据结构·c++·笔记·python·算法
zore_c2 小时前
【C++】基础语法(命名空间、引用、缺省以及输入输出)
c语言·开发语言·数据结构·c++·经验分享·笔记
akarinnnn2 小时前
【DAY16】字符函数和字符串函数
c语言·数据结构·算法
草莓熊Lotso2 小时前
Linux 线程深度剖析:线程 ID 本质、地址空间布局与 pthread 源码全解
android·linux·运维·服务器·数据库·c++
沐雪轻挽萤2 小时前
2. C++17新特性-结构化绑定 (Structured Bindings)
java·开发语言·c++
Robot_Nav2 小时前
ThetaStar全局规划算法纯C++控制器详解
开发语言·c++·lazy_theta_star
草莓熊Lotso3 小时前
MySQL 从入门到实战:视图特性 + 用户权限管理全解
linux·运维·服务器·数据库·c++·mysql
Q741_1473 小时前
每日一题 力扣 1848. 到目标元素的最小距离 模拟 C++题解
c++·算法·leetcode·模拟