基础排序算法详解——插入、选择与交换排序

基础排序算法详解------插入、选择与交换排序

1. 排序的概念与运用

1.1 什么是排序?

排序(Sorting)是指将一组记录,按照其中某个或某些关键字的大小,进行递增或递减排列的操作。它是计算机科学中最基础且重要的算法之一。

1.2 排序的常见应用

  • 电商筛选:如京东、淘宝按"评论数"、"新品"、"价格"对商品进行排序。
  • 院校排名:如按综合评分对大学进行排名(北京大学、清华大学等)。
  • 日常数据处理:如成绩排名、文件按名称排序等。

2. 常见排序算法实现

这里我们以数组 int a[] = {5, 3, 9, 6, 2, 4, 7, 1, 8}; 为例进行讲解。

2.1 插入排序

2.1.1 直接插入排序

基本思想 :

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止。这非常像我们打扑克牌时整理手牌的过程。

代码实现:

c 复制代码
void InsertSort(int* a, int n) {
    for (int i = 0; i < n - 1; i++) {
        int end = i;
        int tmp = a[end + 1];
        while (end >= 0) {
            if (a[end] > tmp) {
                a[end + 1] = a[end];
                end--;
            } else {
                break;
            }
        }
        a[end + 1] = tmp;
    }
}

特性总结:

  • 时间复杂度:(O(N^2)),但在元素集合越接近有序时,效率越高(最好可达 (O(N)))。
  • 空间复杂度:(O(1))。
  • 稳定性:稳定。
2.1.2 希尔排序(缩小增量法)

基本思想 :

希尔排序是对直接插入排序的优化。先选定一个整数 gap = n/3 + 1,将待排序文件所有记录分成各组,对每一组进行插入排序。然后缩小 gap,重复上述过程,当 gap = 1 时,相当于直接插入排序,但此时数组已接近有序,效率极高。

代码实现:

c 复制代码
void ShellSort(int* a, int n) {
    int gap = n;
    while (gap > 1) {
        gap = gap / 3 + 1; // 推荐写法:除3
        for (int i = 0; i < n - gap; i++) {
            int end = i;
            int tmp = a[end + gap];
            while (end >= 0) {
                if (a[end] > tmp) {
                    a[end + gap] = a[end];
                    end -= gap;
                } else {
                    break;
                }
            }
            a[end + gap] = tmp;
        }
    }
}

特性总结:

  • 时间复杂度:约为 (O(N^{1.3})),最坏 (O(N^2))。
  • 空间复杂度:(O(1))。
  • 稳定性:不稳定。

2.2 选择排序

2.2.1 直接选择排序

基本思想 :

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

代码实现:

c 复制代码
void SelectSort(int* a, int n) {
    int begin = 0, end = n - 1;
    while (begin < end) {
        int mini = begin, maxi = begin;
        for (int i = begin; i <= end; i++) {
            if (a[i] > a[maxi]) maxi = i;
            if (a[i] < a[mini]) mini = i;
        }
        if (begin == maxi) maxi = mini;
        swap(&a[mini], &a[begin]);
        swap(&a[maxi], &a[end]);
        ++begin;
        --end;
    }
}

特性总结:

  • 时间复杂度:(O(N^2)),效率较低,实际中很少使用。
  • 空间复杂度:(O(1))。
  • 稳定性:不稳定。
2.2.2 堆排序

利用堆积树(堆)这种数据结构设计的一种排序算法,属于选择排序的一种。排升序要建大堆,排降序建小堆。

2.3 交换排序

2.3.1 冒泡排序

基本思想 :

通过比较相邻元素的大小,将较大的元素向序列尾部移动。就像水中的气泡一样,大的气泡先浮出水面。

代码实现:

c 复制代码
void BubbleSort(int* a, int n) {
    int exchange = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (a[j] > a[j + 1]) {
                exchange = 1;
                swap(&a[j], &a[j + 1]);
            }
        }
        if (exchange == 0) break;
    }
}

特性总结:

  • 时间复杂度:(O(N^2))。
  • 空间复杂度:(O(1))。
  • 稳定性:稳定。
2.3.2 快速排序(Hoare版)

基本思想 :

任取待排序元素序列中的某元素作为基准值(key),按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程。

Hoare版本代码实现:

c 复制代码
int _QuickSort(int* a, int left, int right) {
    int begin = left;
    int end = right;
    int keyi = left;
    ++left;
    while (left <= right) {
        // 右边找小
        while (left <= right && a[right] > a[keyi]) --right;
        // 左边找大
        while (left <= right && a[left] < a[keyi]) ++left;
        if (left <= right) swap(&a[left++], &a[right--]);
    }
    swap(&a[keyi], &a[right]);
    return right;
}

快速排序特性总结:

  • 时间复杂度:(O(N \log N)),最坏情况 (O(N^2))。
  • 空间复杂度:(O(\log N))。
  • 稳定性:不稳定。

下一章我们将继续介绍几种排序方法,如果觉得对你有帮助,欢迎点赞评论并收藏

相关推荐
青蓝智慧马老师1 小时前
想学数据分析但零基础,正确顺序不是先学 Python
大数据·人工智能·算法
jeo陽1 小时前
05-数组与冒泡排序:第一个数据结构与经典算法
c语言·数据结构·算法
鸽鸽程序猿2 小时前
【刷题册】hot21-25
算法
Keven_112 小时前
算法札记:记忆化搜索中面对多组数据的初始化
算法
happyprince2 小时前
02-具体观 · JevAny算法与实现剖析
人工智能·算法
Nil2082 小时前
leetcode 75颜色分类
数据结构·算法·leetcode
Liaiyang662 小时前
空圈容错视角 · 多维切面篇:我们生活的世界,不止三维
人工智能·算法·系统架构·前沿技术·哲学·认知科学
闻缺陷则喜何志丹2 小时前
【环】P6709 [CCC 2020] Swapping Seats 环|普及+
算法·洛谷·环
开开心心就好2 小时前
打印机卡住打不了?一键清理卡死打印队列
服务器·开发语言·算法·pdf·ocr·idea·visual studio code