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

【数据结构】从线性表到排序算法详解

数据结构与算法基础:从线性表到排序算法详解

📚 目录

  1. 线性表的两种存储方式
  2. 三大基础排序算法详解
  3. 归并排序:分治思想的经典应用
  4. 算法对比与实际应用

线性表的两种存储方式

顺序存储结构

特点:逻辑上相邻的元素在物理位置上也相邻

// 顺序表的定义
#define MAXSIZE 100
typedef struct {int data[MAXSIZE];  // 存储数组int length;         // 当前长度
} SeqList;

优点

  • 随机访问速度快:O(1)
  • 存储密度高
    缺点
  • 插入删除操作需要移动大量元素:O(n)
  • 必须预先分配连续空间

链式存储结构

特点:用指针来表示元素之间的逻辑关系

// 单链表的定义
typedef struct LNode {int data;           // 数据域struct LNode *next; // 指针域
} LNode, *LinkList;

优点

  • 插入删除操作方便:O(1)
  • 动态分配内存,空间利用率高
    缺点
  • 访问第i个元素需要遍历:O(n)
  • 额外空间存储指针

三大基础排序算法详解

1. 直接插入排序

核心思想:将待排序的元素插入到已排序序列的合适位置

void InsertSort(int A[], int n) {for (int i = 2; i <= n; i++) {  // 从第二个元素开始if (A[i] < A[i-1]) {         // 需要插入A[0] = A[i];             // 哨兵暂存int j;for (j = i-1; A[0] < A[j]; j--) {A[j+1] = A[j];        // 元素后移}A[j+1] = A[0];            // 插入到正确位置}}
}

特点

  • ✅ 稳定排序
  • 📊 时间复杂度:O(n²)
  • 🎯 适用于小规模数据或基本有序的数据

2. 简单选择排序

核心思想:每次从未排序部分选择最小元素放到已排序部分末尾

void SelectSort(int A[], int n) {for (int i = 0; i < n-1; i++) {  // n-1趟选择int min = i;                  // 记录最小元素下标for (int j = i+1; j < n; j++) {if (A[j] < A[min]) min = j;  // 找到更小元素}if (min != i) {              // 交换到正确位置int temp = A[i];A[i] = A[min];A[min] = temp;}}
}

特点

  • ❌ 不稳定排序
  • 📊 时间复杂度:O(n²)
  • 🔄 交换次数少,适合交换成本高的场景

3. 冒泡排序

核心思想:相邻元素两两比较,逆序则交换,每轮将最大元素"冒泡"到末尾

void BubbleSort(int A[], int n) {for (int i = 0; i < n-1; i++) {  // n-1趟bool flag = false;            // 优化标记for (int j = n-1; j > i; j--) {  // 从后往前if (A[j] < A[j-1]) {     // 逆序则交换int temp = A[j];A[j] = A[j-1];A[j-1] = temp;flag = true;          // 标记有交换}}if (!flag) break;             // 无交换则提前结束}
}

特点

  • ✅ 稳定排序
  • 📊 时间复杂度:O(n²)
  • ⚡ 有优化空间,最好情况可达O(n)

归并排序:分治思想的经典应用

核心思想

归并排序采用分治策略:

  1. 分解:将序列分成两半
  2. 解决:递归排序两个子序列
  3. 合并:将两个有序子序列合并

递归实现

// 归并排序主函数
void mergeSort(ListNode* p, int n) {if (n < 2) return;  // 递归终止条件int m = n >> 1;     // 中间位置ListNode* q = p;    // 后半段起点// 寻找中间节点for (int i = 0; i < m; i++) {q = q->next;}// 递归排序前后两段mergeSort(p, m);mergeSort(q, n - m);// 合并两个有序子序列merge(p, m, q, n - m);
}

合并操作

// 合并两个有序链表
ListNode* merge(ListNode* p, int m, ListNode* q, int n) {ListNode dummy;     // 哨兵节点ListNode* tail = &dummy;while (m > 0 && n > 0) {if (p->data <= q->data) {  // 选择较小元素tail->next = p;p = p->next;m--;} else {tail->next = q;q = q->next;n--;}tail = tail->next;}// 处理剩余元素if (m > 0) tail->next = p;if (n > 0) tail->next = q;return dummy.next;
}

特点

  • ✅ 稳定排序
  • 📊 时间复杂度:O(n log n)
  • 💾 空间复杂度:O(n)
  • 🎯 适用于大规模数据排序

算法对比与实际应用

性能对比表

算法时间复杂度空间复杂度稳定性适用场景
插入排序O(n²)O(1)✅ 稳定小规模、基本有序数据
选择排序O(n²)O(1)❌ 不稳定交换成本高的场景
冒泡排序O(n²)O(1)✅ 稳定教学演示、简单场景
归并排序O(n log n)O(n)✅ 稳定大规模数据、外部排序

实际应用建议

  1. 小规模数据(n < 50):使用插入排序
  2. 中等规模数据:考虑快速排序或堆排序
  3. 大规模数据且要求稳定:使用归并排序
  4. 内存受限环境:选择堆排序

优化技巧

// 混合排序:小数组用插入排序,大数组用归并排序
void hybridSort(int A[], int n) {if (n < 16) {InsertSort(A, n);  // 小数组用插入排序} else {// 大数组用归并排序int mid = n / 2;hybridSort(A, mid);hybridSort(A + mid, n - mid);merge(A, mid, A + mid, n - mid);}
}

总结

通过今天的学习,我们掌握了:

  1. 线性表的两种存储方式及其优缺点
  2. 三大基础排序算法的实现和特点
  3. 归并排序的分治思想和实现
  4. 算法选择的实际应用指导
http://www.dtcms.com/a/544608.html

相关文章:

  • 网站家建设培训学校设计科技公司官网
  • SPIR-V后端稳定性的推进工作报告总结
  • MySQL逗号分隔字段-历史遗留原因兼容方案
  • Bun.js + Elysia 框架实现基于 SQLITE3 的简单 CURD 后端服务
  • 做网站 怎么赚钱吗网站数据分析课程
  • Rust——迭代器适配器深度解析:函数式编程的优雅实践
  • 理解PostgreSQL中的映射表
  • Java1029 抽象类:构造方法
  • 类和对象(中)——日期类的实现取地址运算符重载
  • Linux系统编程—线程同步与互斥
  • 【笔试真题】- 百度第一套-2025.09.23
  • notion模板 | 小胡的第二大脑[特殊字符]- 使用案例
  • notion模版 | 小胡的第二大脑[特殊字符]-介绍
  • 公司网站被百度转码了银川网站建设设计
  • 链式二叉树算法精讲:前中后序、层序与完全二叉树判断
  • 项目中遇到的特殊需求所作的特殊处理
  • 会所网站建设wordpress 怎样做模版
  • vue3使用ONLYOFFICE 实现在线Word,Excel等文档
  • Python数据分析自动化:从入门到精通
  • 零依赖一键多端!用纯 Node.js 打造“IP 可访、角色隔离”的轻量化 Mock 服务器
  • Azure 监控工具怎么选?从原生局限到第三方解决方案的效率跃升
  • 湖南省人力资源网夫唯seo
  • 佛山+网站建设品牌建设发展规划
  • 0009.STM32等单片机的RAM和FLASH使用情况查询
  • CloudFront分发安全优化指南:提升性能与用户体验的完整方案
  • 分享修改文件md5的工具
  • 拓展知识:了解grid、block、thread 关系
  • 打破视频壁垒:视频融合平台EasyCVR如何实现多路视频监控上屏的高效管理?
  • 仓颉原子操作封装:从底层原理到鸿蒙高并发实战
  • BIOS 设置PC 上电自启动