当前位置: 首页 > news >正文

排序算法详细介绍对比及备考建议

文章目录

  • 排序算法对比
  • 算法逐一介绍
    • 1. 冒泡排序(Bubble Sort)
    • 2. 选择排序(Selection Sort)
    • 3. 插入排序(Insertion Sort)
    • 4. 希尔排序(Shell Sort)
    • 5. 归并排序(Merge Sort)
    • 6. 快速排序(Quick Sort)
    • 7. 堆排序(Heap Sort)
    • 8. 计数排序(Counting Sort)
    • 9. 桶排序(Bucket Sort)
    • 10. 基数排序(Radix Sort)
      • 总结
  • 关于备考
    • ✅ 必考 or 高频排序算法
    • 🎯 企业面试中高频考察点
    • 🧠 拓展建议
    • 🎯 排序算法面试核心知识清单
      • ✅ 高频要求手写的排序算法
    • 🔝 面试高频 Leetcode 题目(附关键词)
    • 🧩 排序面试思维框架(你可以这样答)
      • 🌟 经典问题:快速排序的时间复杂度?
      • 🌟 高级问题:为什么说归并适合链表?
      • 🌟 扩展:非比较类排序的适用场景?
    • 🧠 排序算法复习笔记(面试 & 考试专用)
      • 一、排序算法分类
      • 二、常考排序算法精讲
        • 1. 快速排序(Quick Sort)
        • 2. 归并排序(Merge Sort)
        • 3. 堆排序(Heap Sort)
        • 4. 插入排序(Insertion Sort)
        • 5. 计数排序(Counting Sort)
        • 6. 基数排序(Radix Sort)
      • 三、面试高频题推荐
      • 四、应答框架 & 面试建议
      • 五、实战建议

本文将介绍常见排序算法,包括算法思想、代码实现(C++和Python)、时间复杂度对比及不同排序间的比较。


排序算法对比

排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性适用场景是否原地
冒泡排序O(n²)O(n)O(n²)O(1)稳定小数据或基本有序
选择排序O(n²)O(n²)O(n²)O(1)不稳定小数据,交换次数少
插入排序O(n²)O(n)O(n²)O(1)稳定小数据或基本有序
希尔排序O(n log n)O(n log²n)O(n²)O(1)不稳定中等数据量
归并排序O(n log n)O(n log n)O(n log n)O(n)稳定大数据量,稳定排序
快速排序O(n log n)O(n log n)O(n²)O(log n)不稳定通用排序,平均最快
堆排序O(n log n)O(n log n)O(n log n)O(1)不稳定原地排序,避免最坏情况
计数排序O(n +k)O(n +k)O(n +k)O(k)稳定整数,范围小
桶排序O(n +k)O(n +k)O(n²)O(n +k)稳定均匀分布数据
基数排序O(d(n +k))O(d(n +k))O(d(n +k))O(n +k)稳定多位数整数

算法逐一介绍

1. 冒泡排序(Bubble Sort)

  • 思想:相邻元素比较交换,将最大元素逐步“冒泡”到末尾。
  • 时间复杂度
    • 平均/最坏:O(n²)
    • 最好(已有序):O(n)
  • 空间复杂度:O(1)
  • 稳定性:稳定

C++代码

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n-1; i++) {
        bool swapped = false;
        for (int j = 0; j < n-i-1; j++) {
            if (arr[j] > arr[j+1]) {
                swap(arr[j], arr[j+1]);
                swapped = true;
            }
        }
        if (!swapped) break;
    }
}

Python代码

def bubble_sort(arr):
    n = len(arr)
    for i in range(n-1):
        swapped = False
        for j in range(n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
                swapped = True
        if not swapped:
            break
    return arr

2. 选择排序(Selection Sort)

  • 思想:每次选择最小元素放到已排序序列末尾。
  • 时间复杂度
    • 平均/最好/最坏:O(n²)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

C++代码

void selectionSort(int arr[], int n) {
    for (int i = 0; i < n-1; i++) {
        int min_idx = i;
        for (int j = i+1; j < n; j++) {
            if (arr[j] < arr[min_idx]) min_idx = j;
        }
        swap(arr[i], arr[min_idx]);
    }
}

Python代码

def selection_sort(arr):
    n = len(arr)
    for i in range(n-1):
        min_idx = i
        for j in range(i+1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr

3. 插入排序(Insertion Sort)

  • 思想:逐个将元素插入到已排序序列的正确位置。
  • 时间复杂度
    • 平均/最坏:O(n²)
    • 最好(已有序):O(n)
  • 空间复杂度:O(1)
  • 稳定性:稳定

C++代码

void insertionSort(int arr[], int n) {
    for (int i = 1; i < n; i++) {
        int key = arr[i], j = i-1;
        while (j >= 0 && arr[j] > key) {
            arr[j+1] = arr[j];
            j--;
        }
        arr[j+1] = key;
    }
}

Python代码

def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i-1
        while j >=0 and key < arr[j]:
            arr[j+1] = arr[j]
            j -=1
        arr[j+1] = key
    return arr

4. 希尔排序(Shell Sort)

  • 思想:分组插入排序,逐步缩小间隔。
  • 时间复杂度:O(n log n) ~ O(n²)(取决于间隔序列)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

C++代码

void shellSort(int arr[], int n) {
    for (int gap = n/2; gap > 0; gap /= 2) {
        for (int i = gap; i < n; i++) {
            int temp = arr[i], j;
            for (j = i; j >= gap && arr[j-gap] > temp; j -= gap)
                arr[j] = arr[j-gap];
            arr[j] = temp;
        }
    }
}

Python代码

def shell_sort(arr):
    n = len(arr)
    gap = n // 2
    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            while j >= gap and arr[j-gap] > temp:
                arr[j] = arr[j-gap]
                j -= gap
            arr[j] = temp
        gap //= 2
    return arr

5. 归并排序(Merge Sort)

  • 思想:分治法,递归排序后合并。
  • 时间复杂度:O(n log n)
  • 空间复杂度:O(n)
  • 稳定性:稳定

C++代码

void merge(int arr[], int l, int m, int r) {
    int n1 = m - l + 1, n2 = r - m;
    int L[n1], R[n2];
    for (int i = 0; i < n1; i++) L[i] = arr[l+i];
    for (int j = 0; j < n2; j++) R[j] = arr[m+1+j];
    int i = 0, j = 0, k = l;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) arr[k++] = L[i++];
        else arr[k++] = R[j++];
    }
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];
}

void mergeSort(int arr[], int l, int r) {
    if (l >= r) return;
    int m = l + (r - l)/2;
    mergeSort(arr, l, m);
    mergeSort(arr, m+1, r);
    merge(arr, l, m, r);
}

Python代码

def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        L, R = arr[:mid], arr[mid:]
        merge_sort(L)
        merge_sort(R)
        i = j = k = 0
        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                i +=1
            else:
                arr[k] = R[j]
                j +=1
            k +=1
        while i < len(L):
            arr[k] = L[i]
            i +=1; k +=1
        while j < len(R):
            arr[k] = R[j]
            j +=1; k +=1
    return arr

6. 快速排序(Quick Sort)

  • 思想:分治法,选基准分区,递归排序。
  • 时间复杂度
    • 平均/最好:O(n log n)
    • 最坏(已有序):O(n²)
  • 空间复杂度:O(log n)(递归栈)
  • 稳定性:不稳定

C++代码

int partition(int arr[], int low, int high) {
    int pivot = arr[high], i = low-1;
    for (int j = low; j < high; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i+1], arr[high]);
    return i+1;
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi-1);
        quickSort(arr, pi+1, high);
    }
}

Python代码

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[-1]
    left = [x for x in arr[:-1] if x <= pivot]
    right = [x for x in arr[:-1] if x > pivot]
    return quick_sort(left) + [pivot] + quick_sort(right)

7. 堆排序(Heap Sort)

  • 思想:构建最大堆,交换堆顶元素并调整堆。
  • 时间复杂度:O(n log n)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

C++代码

void heapify(int arr[], int n, int i) {
    int largest = i, l = 2*i+1, r = 2*i+2;
    if (l < n && arr[l] > arr[largest]) largest = l;
    if (r < n && arr[r] > arr[largest]) largest = r;
    if (largest != i) {
        swap(arr[i], arr[largest]);
        heapify(arr, n, largest);
    }
}

void heapSort(int arr[], int n) {
    for (int i = n/2-1; i >=0; i--)
        heapify(arr, n, i);
    for (int i = n-1; i >=0; i--) {
        swap(arr[0], arr[i]);
        heapify(arr, i, 0);
    }
}

Python代码

def heapify(arr, n, i):
    largest = i
    l, r = 2*i+1, 2*i+2
    if l < n and arr[l] > arr[largest]:
        largest = l
    if r < n and arr[r] > arr[largest]:
        largest = r
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

def heap_sort(arr):
    n = len(arr)
    for i in range(n//2-1, -1, -1):
        heapify(arr, n, i)
    for i in range(n-1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]
        heapify(arr, i, 0)
    return arr

8. 计数排序(Counting Sort)

  • 思想:统计元素出现次数,按顺序输出。
  • 时间复杂度:O(n + k)(k为数据范围)
  • 空间复杂度:O(k)
  • 稳定性:稳定

C++代码

void countingSort(int arr[], int n, int max_val) {
    int output[n], count[max_val+1] = {0};
    for (int i = 0; i < n; i++) count[arr[i]]++;
    for (int i = 1; i <= max_val; i++) count[i] += count[i-1];
    for (int i = n-1; i >=0; i--) output[--count[arr[i]]] = arr[i];
    for (int i = 0; i < n; i++) arr[i] = output[i];
}

Python代码

def counting_sort(arr):
    max_val = max(arr)
    count = [0] * (max_val + 1)
    for num in arr:
        count[num] +=1
    i = 0
    for num in range(max_val +1):
        while count[num] >0:
            arr[i] = num
            i +=1
            count[num] -=1
    return arr

9. 桶排序(Bucket Sort)

  • 思想:分桶后分别排序,合并结果。
  • 时间复杂度
    • 平均:O(n + k)
    • 最坏:O(n²)
  • 空间复杂度:O(n + k)
  • 稳定性:稳定(取决于桶内排序算法)

C++代码

void bucketSort(float arr[], int n) {
    vector<float> buckets[n];
    for (int i = 0; i < n; i++) {
        int bi = n * arr[i];
        buckets[bi].push_back(arr[i]);
    }
    for (int i = 0; i < n; i++)
        sort(buckets[i].begin(), buckets[i].end());
    int index = 0;
    for (int i = 0; i < n; i++)
        for (float num : buckets[i])
            arr[index++] = num;
}

Python代码

def bucket_sort(arr):
    max_val, min_val = max(arr), min(arr)
    bucket_size = (max_val - min_val) / len(arr)
    buckets = [[] for _ in range(len(arr))]
    for num in arr:
        idx = int((num - min_val) // bucket_size)
        if idx == len(buckets):
            idx -=1
        buckets[idx].append(num)
    sorted_arr = []
    for bucket in buckets:
        sorted_arr.extend(sorted(bucket))
    return sorted_arr

10. 基数排序(Radix Sort)

  • 思想:按位排序,从低位到高位。
  • 时间复杂度:O(d(n + k))(d为位数)
  • 空间复杂度:O(n + k)
  • 稳定性:稳定

C++代码

void countingSortForRadix(int arr[], int n, int exp) {
    int output[n], count[10] = {0};
    for (int i = 0; i < n; i++) count[(arr[i]/exp)%10]++;
    for (int i = 1; i < 10; i++) count[i] += count[i-1];
    for (int i = n-1; i >=0; i--) {
        output[count[(arr[i]/exp)%10]-1] = arr[i];
        count[(arr[i]/exp)%10]--;
    }
    for (int i = 0; i < n; i++) arr[i] = output[i];
}

void radixSort(int arr[], int n) {
    int max_val = *max_element(arr, arr+n);
    for (int exp = 1; max_val/exp >0; exp *=10)
        countingSortForRadix(arr, n, exp);
}

Python代码

def radix_sort(arr):
    max_val = max(arr)
    exp = 1
    while max_val // exp >0:
        counting_sort_by_digit(arr, exp)
        exp *=10
    return arr

def counting_sort_by_digit(arr, exp):
    n = len(arr)
    output = [0]*n
    count = [0]*10
    for i in range(n):
        index = (arr[i] // exp) %10
        count[index] +=1
    for i in range(1,10):
        count[i] += count[i-1]
    for i in range(n-1, -1, -1):
        index = (arr[i] // exp) %10
        output[count[index]-1] = arr[i]
        count[index] -=1
    for i in range(n):
        arr[i] = output[i]

总结

  • 冒泡、选择、插入排序:适用于小规模数据。
  • 希尔排序:中等规模数据,优于插入排序。
  • 归并、快速、堆排序:大规模数据,归并稳定但需额外空间,快速排序平均最快,堆排序原地排序。
  • 计数、桶、基数排序:特定场景下高效(如整数范围小、均匀分布、多位数)。

非常好的问题!在数据结构与算法考试、面试(尤其是大厂)中,虽然排序算法很多,但常考的排序算法主要集中在下面这几种,因为它们代表了不同的思想和场景优化策略:


关于备考

✅ 必考 or 高频排序算法

排序算法说明 / 考察点为什么常考
快速排序分治、原地、非稳定排序最常用的高效通用排序,面试常要求手写
归并排序分治、稳定排序、空间换时间经常考在链表中排序(Leetcode经典)
堆排序二叉堆结构、原地排序、优先队列基础常作为Top K 问题基础
插入排序稳定、简单,考察基本理解代码简单,适合考察写基础排序
计数排序线性时间排序代表理解适用范围 + 稳定排序基础
冒泡排序教学用、面试中考“你写一个最基础排序”了解基本交换机制
桶/基数排序高效但场景特定高级笔试题中出现,用于浮点/大数据位排序

🎯 企业面试中高频考察点

  • 写一个快速排序(原地/非递归)
  • 链表使用归并排序排序 O(n log n)
  • 从数据流中找第K大(堆排序)
  • Top K 频率元素(堆 + 计数)
  • 计数排序 vs 比较类排序差别(适用场景)
  • 给定整数数组用基数排序排序

🧠 拓展建议

方向建议练习题
📚 基础写法快速排序、归并排序、堆排序手写
🔍 排序思想比较类 vs 非比较类排序的适用场景
📈 排序优化小数组用插入排序,大数组快速+归并
🧪 Leetcode#215, #912, #148, #347, #451

🎯 排序算法面试核心知识清单

✅ 高频要求手写的排序算法

算法重点考察方向稳定性原地
快速排序分治思想、原地实现、递归/非递归
归并排序分治思想、链表排序实现
堆排序大顶堆构建、Top K 使用
插入排序简单直接、部分有序数组快

🔝 面试高频 Leetcode 题目(附关键词)

题目编号名称涉及排序类型难度
#912排序数组快速/归并排序🟠 中等
#215数组第K大元素快排/堆排序🟠 中等
#347前K高频元素堆 + 计数排序思想🟠 中等
#148链表排序归并排序🔵 困难
#451按频率排序计数 + 自定义排序🟠 中等

🧩 排序面试思维框架(你可以这样答)

🌟 经典问题:快速排序的时间复杂度?

  • 平均:O(n log n)
  • 最坏:O(n²)(已排序数组)
  • 优化:三路快排、随机pivot

🌟 高级问题:为什么说归并适合链表?

  • 不依赖随机访问
  • 可以轻松实现O(1)空间的链表归并
  • 稳定、时间复杂度始终 O(n log n)

🌟 扩展:非比较类排序的适用场景?

  • 计数排序:整数,范围小
  • 基数排序:整数、位数小(如手机号、身份证)
  • 桶排序:小数、浮点数、分布均匀

🧠 排序算法复习笔记(面试 & 考试专用)


一、排序算法分类

分类算法稳定性是否原地时间复杂度(平均)时间复杂度(最坏)适用场景
比较类排序冒泡、插入、选择、归并、快速、堆插入/冒泡/归并 ✅ 其余 ❌归并 ❌ 其余 ✅O(n^2)/O(nlogn)O(n^2)/O(nlogn)通用排序
非比较类排序计数、桶、基数O(n)/O(nk)O(n)/O(nk)整数/位数小/范围有限的排序场景

二、常考排序算法精讲

1. 快速排序(Quick Sort)
  • 思想:分治 + 原地交换
  • 特点:高效,最常用,平均 O(nlogn),最坏 O(n^2)
  • 代码:C++/Python(略,见代码库)
  • 常考形式:手写实现;找第K大元素;排序 + 去重
2. 归并排序(Merge Sort)
  • 思想:分治 + 合并
  • 特点:稳定,适合链表,空间复杂度 O(n)
  • 常考形式:链表排序;大数据排序
3. 堆排序(Heap Sort)
  • 思想:最大堆构建 + 弹出堆顶
  • 特点:原地,不稳定,优先队列基础
  • 常考形式:Top K 问题,最大/最小K个数
4. 插入排序(Insertion Sort)
  • 思想:构建有序序列,将新元素插入
  • 特点:适合小数组、基本有序场景
5. 计数排序(Counting Sort)
  • 思想:统计频次 -> 回写数组
  • 特点:非比较排序,稳定,O(n+k),适合范围小的整数
6. 基数排序(Radix Sort)
  • 思想:按位排序(低位到高位)
  • 特点:适合大整数排序;与计数结合使用

三、面试高频题推荐

Leetcode 编号题目重点算法
912Sort an Array快排 / 归并
215Kth Largest Element in Array快排 / 堆排序
347Top K Frequent Elements堆 + 计数排序思想
148Sort List归并(链表版)
451Sort Characters by Frequency计数 + 自定义排序

四、应答框架 & 面试建议

1. 你知道哪些排序?哪种最好?

  • 分析场景再选:快排适合通用,归并适合链表,计数适合整数范围小

2. 快排最坏时间复杂度?怎么优化?

  • O(n^2),优化方法:随机化 pivot,三路快排

3. 为什么归并适合链表?

  • 链表不能随机访问,归并分治直接分中间节点,合并无需额外数组

4. 如何实现 Top K 问题?

  • 小顶堆维护前 K 个元素,堆排序或快速选择法

五、实战建议

  • 手写练习:快排(原地)、归并(链表)、堆构建
  • 使用库时:记得 sort() 默认用 IntroSort(快排+堆+插入)
  • 注意稳定性、是否原地、空间复杂度等细节

📌 建议每日刷 1-2 道经典题,注重思维过程而非背代码
📌 可搭配可视化工具(如 Visualgo.net)加深理解

相关文章:

  • 数据仓库元数据的管理
  • 【js】nvm1.2.2 无法下载 Node.js 15及以下版本
  • 支持iOS与Android!SciChart开源金融图表库助力高效开发交易应用
  • C++字符串操作详解
  • Dify什么?Dify 零门槛打造专属 AI 应用
  • Rust重定义数据库内核:从内存安全到性能革命的破界之路
  • 国内MCP服务有哪些?MCP服务器搜索引擎哪家好?
  • 深入学习LLM开发 第十三章:智能代理(Agents)基于LangGraph实现
  • 【嵌入式硬件】LAN9253说明书(中文版)
  • 刘哲尔:新生代演员的多元“征途”
  • python-65-常用的数据可视化库和框架
  • 每日算法-250411
  • 【网络原理】网络通信基础
  • 局域网内文件共享的实用软件推荐
  • CD7 CAR-T细胞治疗移植后复发伴髓外病灶的急性髓系白血病
  • 【Raqote】 1.2 路径填充ShaderClipMaskBlitter结构体(blitter.rs)
  • 小星星-第16届蓝桥第3次STEMA测评Scratch真题第4题
  • 琥珀扫描 2.0.5.0 | 文档处理全能助手,支持扫描、文字提取及表格识别
  • 为什么drupal7的分类中的术语增加了日语版本,但是日语页面显示的还是英文的
  • C语言 |位域结构体
  • 炫酷一些的网站/百度seo公司哪家好一点
  • 公司没注册可以做网站吗/免费发布推广平台
  • 网站开发需要怎么做/国外免费源码共享网站
  • dw对网站建设有哪些作用/好用的种子搜索引擎
  • 做网站排名公司推荐/怎么制作链接网页
  • 做家乡的网站/搜索引擎优化指南