常见排序算法的实现

前言

排序算法是计算机科学中最基础且重要的算法之一,广泛应用于数据处理、数据库管理、图像处理等领域。通过排序算法,我们可以将无序的数据按照一定的规则重新排列,从而提高数据的查找、插入和删除效率。本次实验旨在通过实现几种常见的排序算法,深入理解其工作原理,并通过测试验证其正确性和效率。实验内容主要包括插入类排序、交换类排序和选择类排序的实现,具体涉及直接插入排序、冒泡排序、快速排序和简单选择排序。

插入类排序算法的实现

插入类排序算法的核心思想是将待排序的元素逐个插入到已排序序列中的适当位置,直到所有元素都插入完毕。直接插入排序是插入类排序算法的典型代表。

直接插入排序的实现

直接插入排序的实现步骤如下:

  1. 从第二个元素开始,依次将每个元素插入到前面已排序的序列中。
  2. 在插入过程中,如果当前元素小于前一个元素,则将前一个元素后移,直到找到合适的插入位置。
  3. 重复上述过程,直到所有元素都插入完毕。

以下是直接插入排序的代码实现:

cpp 复制代码
void InsertSort(SqList &ST) { 
    for (int i = 2; i <= ST.length; i++) {
        if (ST.elem[i] < ST.elem[i - 1]) {
            ST.elem[0] = ST.elem[i]; // 暂存待插入元素
            int j;
            for (j = i - 1; ST.elem[j] > ST.elem[0]; j--) {
                ST.elem[j + 1] = ST.elem[j]; // 元素后移
            }
            ST.elem[j + 1] = ST.elem[0]; // 插入元素
        }
    }
}

直接插入排序的特点

  • 时间复杂度:最好情况下为O(n),最坏和平均情况下为O(n²)。
  • 空间复杂度:O(1),是一种原地排序算法。
  • 稳定性:稳定排序算法,相同元素的相对位置不会改变。

交换类排序算法的实现

交换类排序算法的核心思想是通过交换元素的位置来实现排序。常见的交换类排序算法包括冒泡排序和快速排序。

冒泡排序的实现

冒泡排序的实现步骤如下:

  1. 从第一个元素开始,依次比较相邻的两个元素,如果前一个元素大于后一个元素,则交换它们的位置。
  2. 每一轮比较都会将当前未排序序列中的最大元素"冒泡"到末尾。
  3. 重复上述过程,直到所有元素都排序完毕。

以下是冒泡排序的代码实现:

cpp 复制代码
void BubbleSort(SqList &L){  
    for (int i = 1; i < L.length; i++) {
        for (int j = 1; j <= L.length - i; j++) {
            if (L.elem[j] > L.elem[j + 1]) {
                swap(L.elem[j], L.elem[j + 1]); // 交换元素
            }
        }
    }
}

冒泡排序的特点

  • 时间复杂度:最好情况下为O(n),最坏和平均情况下为O(n²)。
  • 空间复杂度:O(1),是一种原地排序算法。
  • 稳定性:稳定排序算法。

快速排序的实现

快速排序是一种分治算法,其实现步骤如下:

  1. 选择一个基准元素(通常选择第一个元素),将序列分为两部分,左边部分小于基准元素,右边部分大于基准元素。
  2. 递归地对左右两部分进行快速排序。
  3. 合并左右两部分,得到最终排序结果。

以下是快速排序的代码实现:

cpp 复制代码
int Partition(SqList &L, int low, int high) {
    L.elem[0] = L.elem[low]; // 暂存基准元素
    while (low < high) {
        while (low < high && L.elem[high] >= L.elem[0]) high--;
        L.elem[low] = L.elem[high]; // 元素后移
        while (low < high && L.elem[low] <= L.elem[0]) low++;
        L.elem[high] = L.elem[low]; // 元素前移
    }
    L.elem[low] = L.elem[0]; // 基准元素归位
    return low;
}

void QuickSort(SqList &L, int low, int high) {
    if (low < high) {
        int pivotloc = Partition(L, low, high);
        QuickSort(L, low, pivotloc - 1);
        QuickSort(L, pivotloc + 1, high);
    }
}

void QuickSort(SqList &L) {
    QuickSort(L, 1, L.length);
}
快速排序的特点
  • 时间复杂度:平均情况下为O(n log n),最坏情况下为O(n²)。
  • 空间复杂度:O(log n),递归调用栈的深度。
  • 稳定性:不稳定排序算法。

选择类排序算法的实现

选择类排序算法的核心思想是通过选择最小(或最大)元素来实现排序。简单选择排序是选择类排序算法的典型代表。

简单选择排序的实现

简单选择排序的实现步骤如下:

  1. 从第一个元素开始,依次找到未排序序列中的最小元素。
  2. 将最小元素与未排序序列的第一个元素交换位置。
  3. 重复上述过程,直到所有元素都排序完毕。

以下是简单选择排序的代码实现:

cpp 复制代码
void SelectSort(SqList &L) {
    for (int i = 1; i < L.length; i++) {
        int min = i;
        for (int j = i + 1; j <= L.length; j++) {
            if (L.elem[j] < L.elem[min]) {
                min = j;
            }
        }
        if (min != i) {
            swap(L.elem[i], L.elem[min]); // 交换元素
        }
    }
}
简单选择排序的特点
  • 时间复杂度:最好、最坏和平均情况下均为O(n²)。
  • 空间复杂度:O(1),是一种原地排序算法。
  • 稳定性:不稳定排序算法。

总结

通过本次实验,我们实现了插入类、交换类和选择类排序算法,并对它们的特点进行了分析。以下是各排序算法的总结:

  1. 直接插入排序:适合小规模数据或基本有序的数据,时间复杂度为O(n²),稳定且原地排序。
  2. 冒泡排序:适合小规模数据,时间复杂度为O(n²),稳定且原地排序。
  3. 快速排序:适合大规模数据,平均时间复杂度为O(n log n),不稳定但效率高。
  4. 简单选择排序:适合小规模数据,时间复杂度为O(n²),不稳定但实现简单。

在实际应用中,我们需要根据数据规模、数据特点以及性能要求选择合适的排序算法。例如,对于大规模数据,快速排序通常是更好的选择;而对于小规模数据或基本有序的数据,直接插入排序或冒泡排序可能更为合适。通过本次实验,我们不仅掌握了这些排序算法的实现方法,还加深了对它们性能特点的理解。

相关推荐
Morwit6 小时前
【力扣hot100】 1. 两数之和
数据结构·c++·算法·leetcode·职场和发展
无小道6 小时前
算法——暴力+优化
算法·优化·暴力
Free Tester6 小时前
如何判断 LeakCanary 报告的严重程度
java·jvm·算法
zyq99101_17 小时前
DFS算法实战:经典例题代码解析
python·算法·蓝桥杯·深度优先
智者知已应修善业7 小时前
【51单片机单按键切换广告屏】2023-5-17
c++·经验分享·笔记·算法·51单片机
广州灵眸科技有限公司7 小时前
为RK3588注入澎湃算力:RK1820 AI加速卡完整适配与评测指南
linux·网络·人工智能·物联网·算法
qinian_ztc7 小时前
frida 14.2.18 安装报错解决
算法·leetcode·职场和发展
AI应用实战 | RE7 小时前
012、检索器(Retrievers)核心:从向量库中智能查找信息
人工智能·算法·机器学习·langchain
凤年徐7 小时前
C++手撕红黑树:从0到200行,拿下STL map底层核心
c++·后端·算法
Thomas.Sir7 小时前
AI 医疗之罕见病/疑难病辅助诊断系统从算法到实现【表型驱动与知识图谱推理】
人工智能·算法·ai·知识图谱