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

用C语言实现了——一个基于顺序表的插入排序演示系统

一、知识要点、

插入排序是一种简单直观的排序算法,它的工作方式类似于我们整理扑克牌。

基本原理:

插入排序通过构建有序序列来工作。它每次从无序序列中取出一个元素,然后将其插入到已排序序列的适当位置。这个过程重复进行,直到所有元素都已插入到已排序序列中。
 

算法步骤:

  1. 初始化:假设数组的第一个元素已经是一个有序序列。

  2. 遍历数组:从第二个元素开始,依次取出当前元素。

  3. 比较和插入:将当前元素与已排序序列中的元素进行比较,找到合适的位置插入当前元素。

  4. 重复:重复上述过程,直到所有元素都已插入到有序序列中。
     

详细步骤示例:

假设有一个数组:[5, 2, 4, 6, 1, 3]

  1. 初始状态:已排序序列 [5],未排序序列 [2, 4, 6, 1, 3]

  2. 取第二个元素 2
    与已排序序列的 5 比较,发现 2 < 5,将 5 后移一位。
    插入 2 到合适位置,已排序序列变为 [2, 5]

  3. 取第三个元素 4
    与 5 比较,4 < 5,将 5 后移一位。
    与 2 比较,4 > 2,插入到 2 和 5 之间,已排序序列变为 [2, 4, 5]

  4. 重复以上过程

性能分析:

时间复杂度

  • 最好情况:O(n)(当输入数组已经是有序的)

  • 最坏情况:O(n²)(当输入数组是逆序的)

  • 平均情况:O(n²)

空间复杂度:O(1)(只需要一个额外的临时变量)

稳定性:稳定排序(相同值的元素不会交换顺序)

优点

  1. 简单易实现:代码结构简单,容易理解和实现。

  2. 高效处理小规模数据:对于小规模数据,插入排序的性能较好。

  3. 适应性强:对于部分有序的数组,插入排序的性能表现优秀。

缺点

  1. 对大规模数据效率低:时间复杂度为 O(n²),在处理大规模数据时效率较低。

  2. 不适合逆序数据:当数据完全逆序时,需要最多的交换操作。

插入排序是一种简单且直观的排序算法,适用于小规模数据或部分有序的数据。尽管在大规模数据上效率不高,但它的简单性和稳定性使其在某些特定场景中仍然具有应用价值。

二、代码解析

1.结构体定义

int* array:

这是一个指向整数的指针,用于存储用户输入的原始数据。

它指向一个动态分配的内存区域,该区域的大小由用户输入的数组元素数量决定。
 

int* sortedArray:

这也是一个指向整数的指针,用于存储排序后的数据。

array 类似,它同样指向一个动态分配的内存区域,其大小与 array 相同。

在程序中,sortedArray 初始时会被复制 array 的内容,然后在排序过程中被修改。
 

int size

这是一个整数,用于存储数组的大小(即数组中元素的数量)。它定义了 arraysortedArray 所指向的内存区域的大小。

2. 初始化函数initSortSystem

参数SortSystem* sys,这是一个指向 SortSystem 结构体的指针,表示函数将对这个结构体进行操作。

sys->array = NULL;:  表示当前没有为原始数据分配内存。

sys->sortedArray = NULL;:   表示当前没有为排序后的数据分配内存。

sys->size = 0;:    表示当前数组的大小为 0,即没有数据。

3. 输入数组函数inputArray

3.1 函数定义:

返回类型void,表示该函数不返回任何值。

参数SortSystem* sys,这是一个指向 SortSystem 结构体的指针,表示函数将对这个结构体进行操作。

3.2 获取数组大小

提示用户输入:首先提示用户输入数组元素的数量。

读取输入:使用 scanf_s 函数读取用户输入的整数,并将其存储到 sys->size 中。

3.2 动态内存分配

分配内存:为 sys->array 动态分配内存,内存大小为 sys->size * sizeof(int)

检查分配是否成功:如果 malloc 返回 NULL,表示内存分配失败。此时输出错误信息并退出程序。

3.4. 用户输入数组元素

提示用户输入元素:提示用户输入指定数量的整数。

读取元素:使用循环读取用户输入的每个整数,并将其存储到 sys->array 中。

 

3.5. 复制数组到排序数组

分配内存:为 sys->sortedArray 动态分配内存,内存大小同样为 sys->size * sizeof(int)

检查分配是否成功:如果 malloc 返回 NULL,表示内存分配失败。此时输出错误信息,释放之前分配的 sys->array 内存,并退出程序。

复制数据:使用循环将 sys->array 中的数据复制到 sys->sortedArray 中。

3.6 函数作用

初始化数组:从用户那里获取数组元素的数量和具体元素,初始化 SortSystem 结构体中的 arraysortedArray

动态内存分配:根据用户输入的数组大小动态分配内存,确保程序能够处理不同大小的输入数据。

数据备份:将原始数据复制到 sortedArray,以便后续的排序操作不会影响原始数据。

后两个点也是该函数处理的优点。

4. 显示数组函数displayArray

4.1 函数定义

返回类型void,表示该函数不返回任何值。

参数

const int* array:指向整数数组的指针,表示要显示的数组。

int size:数组的大小。

int currentStep:当前排序步骤。

int currentElem:当前正在操作的元素的索引。

4.2 函数体:

4.3 代码分析

① 清屏(注释掉)

system("cls") 是 Windows 系统下的清屏命令。在 Unix/Linux 系统中,应使用 system("clear")

由于 system("cls") 可能导致程序依赖于特定的操作系统,或者在某些环境下不可用,因此被注释掉了。

显示当前排序步骤

作用:输出当前排序步骤的编号,帮助用户了解排序的进度。

遍历并显示数组元素

遍历数组:使用 for 循环遍历数组的每个元素。

高亮当前元素

当前操作的元素(currentElem)使用红色显示,以便于用户观察。

使用了 ANSI 转义序列 \033[1;31m 设置文本颜色为红色,\033[0m 重置颜色。

{

ANSI 转义序列兼容性\033[1;31m\033[0m 是 ANSI 转义序列,可能不被所有终端支持。在不支持的终端中,颜色显示可能无效。

}

换行和暂停(注释掉)

换行:在输出完成后添加两个空行,使输出更易读。

暂停(注释掉)sleep(1) 会使程序暂停 1 秒,以便用户有时间观察每一步的变化。由于可能需要额外的头文件(如 <unistd.h>),因此被注释掉了。

 

5. 插入排序操作的实现

5.1 函数定义:

返回类型void,表示该函数不返回任何值。

参数SortSystem* sys,这是一个指向 SortSystem 结构体的指针,表示函数将对这个结构体中的数组进行排序。

5.2 变量声明:

key:用于存储当前要插入的元素。

j:用于标记当前正在比较的元素的位置。

5.3 外层循环

循环变量i 从 1 开始,遍历整个数组。

作用:从数组的第二个元素开始,依次将每个元素插入到前面已排序的子数组中。

5.4 内层循环:将大于key的元素向右移动

条件判断:当 j 不小于 0 且当前元素大于 key 时,执行循环体。

元素移动:将当前元素向右移动一位,为插入 key 腾出位置。

更新 jj 减 1,继续比较前一个元素。

显示中间状态:调用 displayArray 函数显示当前数组状态,便于观察排序过程。

5.5 插入操作

key 插入到正确的位置。

5.6 显示交换后的状态

再次调用 displayArray 函数显示插入后的数组状态。

在排序完成后输出提示信息。

6. 显示函数displayResult

用于显示排序系统的原始数据和排序后的结果。

6.1 函数定义:

参数const SortSystem* sys,这是一个指向 SortSystem 结构体的指针,表示函数将读取这个结构体中的数据但不会修改它。

6.2 函数体:

① 显示标题

输出一个标题,用于分隔和标识排序结果部分,使输出更清晰。
 

② 检查数组大小

 检查 SortSystem 结构体中的 size 是否为 0。

如果 size 为 0,表示用户尚未输入数据,输出提示信息并退出函数。

③ 显示原始数据

输出原始数据。

使用 for 循环遍历 sys->array,并依次输出每个元素。

每个元素之间以空格分隔,最后换行。

④ 显示排序结果

输出排序后的结果。

使用 for 循环遍历 sys->sortedArray,并依次输出每个元素。

每个元素之间以空格分隔,最后换行。

7. 运行runSortSystem 的函数

1. 初始化排序系统

定义一个 SortSystem 类型的变量 sys,并调用 initSortSystem 函数对其进行初始化。

确保 sys 结构体的成员变量处于初始状态,避免未定义行为。

使用 switch 语句处理不同的用户选择,让代码逻辑变得清晰。

该函数是整个排序系统的主控制中心,负责显示菜单、获取用户输入并调用相应的功能函数。

通过循环持续运行,直到用户选择退出。

三、完整代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>// 定义结构体存储排序系统所需信息
typedef struct
{int* array;                   // 存储用户输入的数组int* sortedArray;             // 存储排序后的数组int size;                     // 数组大小
} SortSystem;// 函数声明
void initSortSystem(SortSystem* sys);
void inputArray(SortSystem* sys);
void displayArray(const int* array, int size, int currentStep, int currentElem);
void insertionSort(SortSystem* sys);
void menu();
void runSortSystem();
void displayResult(const SortSystem* sys);void menu()
{printf("\n===== 排序系统主菜单 =====\n");printf("1. 输入数据\n");printf("2. 执行插入排序\n");printf("3. 查看原始数据\n");printf("4. 查看排序结果\n");printf("5. 退出系统\n");printf("请选择操作: ");
}int main()
{printf("===== 基于顺序表的插入排序系统 =====\n");runSortSystem();return 0;
}// 初始化排序系统
void initSortSystem(SortSystem* sys)
{sys->array = NULL;sys->sortedArray = NULL;sys->size = 0;
}// 输入数组
void inputArray(SortSystem* sys)
{printf("请输入数组元素的数量: ");scanf_s("%d", &sys->size);// 分配内存sys->array = (int*)malloc(sys->size * sizeof(int));if (sys->array == NULL){printf("内存分配失败!\n");exit(1);}printf("请输入 %d 个整数:\n", sys->size);for (int i = 0; i < sys->size; i++){scanf_s("%d", &sys->array[i]);}// 复制一份原始数组到排序数组sys->sortedArray = (int*)malloc(sys->size * sizeof(int));if (sys->sortedArray == NULL){printf("内存分配失败!\n");free(sys->array);exit(1);}for (int i = 0; i < sys->size; i++){sys->sortedArray[i] = sys->array[i];}
}// 显示数组
void displayArray(const int* array, int size, int currentStep, int currentElem)
{// system("cls"); // 清屏printf("\n排序步骤 %d:\n", currentStep);for (int i = 0; i < size; i++){if (i == currentElem){printf("\033[1;31m[%d]\033[0m ", array[i]); // 红色显示当前元素}else{printf("[%d] ", array[i]);}}printf("\n\n");// sleep(1); // 暂停1秒,便于观察
}// 插入排序实现
void insertionSort(SortSystem* sys)
{int key = 0;int j = 0;for (int i = 1; i < sys->size; i++){key = sys->sortedArray[i];j = i - 1;// 将大于key的元素向右移动while (j >= 0 && sys->sortedArray[j] > key){sys->sortedArray[j + 1] = sys->sortedArray[j];j--;displayArray(sys->sortedArray, sys->size, i, j + 1); // 显示中间状态}sys->sortedArray[j + 1] = key;displayArray(sys->sortedArray, sys->size, i, j + 1); // 显示交换后的状态}printf("\n排序完成!\n\n");
}// 运行排序系统
void runSortSystem()
{SortSystem sys;initSortSystem(&sys);int choice = 0;while (1){menu();scanf_s("%d", &choice);switch (choice){case 1:inputArray(&sys);printf("数据输入完成!\n");break;case 2:if (sys.size == 0){printf("尚未输入数据,请先选择1 输入数据!\n");}else{insertionSort(&sys);}break;case 3:if (sys.size == 0){printf("尚未输入数据,请先选择1 输入数据!\n");}else{printf("原始数据:\n");for (int i = 0; i < sys.size; i++){printf("%d ", sys.array[i]);}printf("\n");}break;case 4:if (sys.size == 0){printf("尚未输入数据,请先选择1 输入数据!\n");}else{printf("排序结果: ");for (int i = 0; i < sys.size; i++){printf("%d ", sys.sortedArray[i]);}printf("\n");}break;case 5:if (sys.array != NULL)free(sys.array);if (sys.sortedArray != NULL)free(sys.sortedArray);printf("感谢使用插入排序系统,再见!\n");return;default:printf("无效的选择,请重新输入!\n");}}
}// 显示结果
void displayResult(const SortSystem* sys)
{printf("\n===== 排序结果 =====\n");if (sys->size == 0){printf("尚未输入数据\n");}else{printf("原始数据: ");for (int i = 0; i < sys->size; i++){printf("%d ", sys->array[i]);}printf("\n排序结果: ");for (int i = 0; i < sys->size; i++){printf("%d ", sys->sortedArray[i]);}printf("\n");}
}

用C语言实现了——一个基于顺序表的插入排序演示系统,具有交互式菜单和可视化排序过程。

  1. 系统结构
    使用SortSystem结构体统一管理数据,包含原始数组、排序数组和数组大小,通过动态内存分配实现灵活的数据存储。

  2. 核心功能

    • 用户交互:提供菜单选项(输入数据、执行排序、查看数据、退出等),支持多次操作。

    • 插入排序实现:通过insertionSort函数完成排序,并在每一步移动元素时调用displayArray,用红色高亮显示当前操作的元素,直观展示排序过程。

    • 数据可视化:支持查看原始数据和排序结果,排序过程中每一步的中间状态会被实时打印。

  3. 技术细节

    • 动态内存管理:使用malloc分配数组内存,退出时通过free释放内存,避免泄漏。

    • 跨平台兼容性:使用scanf_s(需注意编译器兼容性)和ANSI颜色代码(部分终端可能不支持)。

  4. 适用场景
    适合用于算法教学或排序过程演示,用户可通过交互式操作观察插入排序的逐步执行逻辑。

相关文章:

  • 班会内容模板
  • GitHub 趋势日报 (2025年05月14日)
  • 沃伦森智能无功补偿系统解决电力电容器频繁投切的隐患
  • [特殊字符] 苍穹外卖项目中的 WebSocket 实战:实现来单与催单提醒功能
  • 红黑树解析
  • uniapp x
  • 网络安全EN18031-1,EN18031-2,EN18031-3三个标准对应的测试项目
  • jedis+redis pipeline诡异的链接损坏、数据读取异常问题解决
  • vue使用vite, 渲染glb模型时报错
  • Nginx与Tomcat负载均衡集群配置指南
  • 牛客网NC21994:分钟计算
  • 计量经济学——预测与chow检验
  • [6-8] 编码器接口测速 江协科技学习笔记(7个知识点)
  • 虚拟网络编辑器
  • 【数据结构入门训练DAY-35】棋盘问题
  • Python-Django系列—日志
  • 张 提示词优化(相似计算模式)深度学习中的损失函数优化技巧
  • ES常识9:如何实现同义词映射(搜索)
  • 平滑过滤值策略
  • 时序数据库IoTDB分布式架构解析与运维指南
  • 人民日报整版聚焦:外贸产品拓内销提速增量,多地加快推动内外贸一体化
  • 国家卫健委通报:吊销肖某医师执业证书,撤销董某莹四项证书
  • 把中国声音带向世界,DG和Blue Note落户中国
  • 新任美国驻华大使庞德伟抵京履职,外交部回应
  • 鄂州交警通报致1死2伤车祸:女子操作不当引发,已被刑拘
  • 外交部:各方应为俄乌双方恢复直接对话创造条件