C数据结构与算法——常见排序算法时间复杂度比较 应用
实验任务
(1) 掌握常见比较排序算法的实现;
(2) 掌握常用比较排序算法的性能及其适用场合。
实验内容
(1) 平均时间复杂度O(n2)和O(nlog2n)的算法至少各选两种实现;
(2) 待排序的无重复关键字存放在一维整型数组中,数量为60000个;
(3) 对于不同的排序算法,分成两轮进行性能对比:
第1轮对比:关键字初始为升序状态;
第2轮对比:关键字初始为乱序状态;
实验源码
// 由于临近期末,所以插入排序和快速排序不加以验证(读者自行验证)#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <profileapi.h>#define LENGTH(arr) (sizeof(arr)/sizeof((arr)[0])) // 计算数组长度void PrintCompare(int arr[], int length); // 打印排序结果
void knuthShuffle(int arr[], int length); // 洗牌算法
void swapInt(int *card_1, int *card_2); // 交换函数
double BubbleSortTimes(int arr[], int length); // 冒泡排序测时
double SelectSortTimes(int arr[], int length); // 选择排序测时
double HeapSortTimes(int arr[], int length); // 堆排序测时
void adjustHeap(int arr[], int i, int length); // 堆排序核心部分(大小堆顶)
double MergeSortTimes(int arr[], int length); // 归并排序测时
void mergeSort(int arr[], int left, int right, int temp[]); // 归分
void merge(int arr[], int left, int mid, int right, int temp[]); // 分治int main() {srand(time(NULL)); // 初始化随机种子printf("======= 排序算法对比 (将 60000 个无重复有序/乱序数据按升序排序)=======\n");printf("\n");printf("------------------- 第01轮比较 初始有序序列排序性能 --------------------\n");int arr[60000];// 有序数组for (int i = 0; i < LENGTH(arr); i++) { // 一副有序牌arr[i] = i + 1;}PrintCompare(arr, LENGTH(arr));printf("\n");printf("------------------- 第02轮比较 初始乱序序列排序性能 --------------------\n");// 无序数组knuthShuffle(arr, LENGTH(arr)); // 洗牌打乱顺序PrintCompare(arr, LENGTH(arr));printf("\n= 测试环境:i7-9750HF @ 4.12Ghz | 16GB RAM | Win 11 X64 | Clion 2022.1 =");getchar();
}void PrintCompare(int arr[], int length) {int tempArr[length];printf("\n ---- 排序算法 ----- - 排序耗时 - ---- 随机展示5个排序后的连续数据 -----\n");printf("【时间复杂度 O(n^2)】\n");for (int i = 0; i < length; i++) {tempArr[i] = arr[i];}printf(" 冒泡排序\t\t%7.2lf ms", BubbleSortTimes(tempArr, length));int randIndex = rand() % length; // 0 - (length-1)int printNum = 5;for (int i = 0; i < printNum; i++) {if (tempArr[randIndex] >= (length - printNum)) {i = 0;} else {printf("%7d", tempArr[randIndex++]);}}printf("\n");for (int i = 0; i < length; i++) {tempArr[i] = arr[i];}printf(" 直接选择排序\t\t%7.2lf ms", SelectSortTimes(tempArr, length));randIndex = rand() % length; // 0 - (length-1)printNum = 5;for (int i = 0; i < printNum; i++) {if (tempArr[randIndex] >= (length - printNum)) {i = 0;} else {printf("%7d", tempArr[randIndex++]);}}printf("\n");printf("【时间复杂度O(nlogn)】\n");for (int i = 0; i < length; i++) {tempArr[i] = arr[i];}printf(" 堆排序\t\t%7.2lf ms", HeapSortTimes(tempArr, length));randIndex = rand() % length; // 0 - (length-1)printNum = 5;for (int i = 0; i < printNum; i++) {if (tempArr[randIndex] >= (length - printNum)) {i = 0;} else {printf("%7d", tempArr[randIndex++]);}}printf("\n");for (int i = 0; i < length; i++) {tempArr[i] = arr[i];}printf(" 归并排序\t\t%7.2lf ms", MergeSortTimes(tempArr, length));randIndex = rand() % length; // 0 - (length-1)printNum = 5;for (int i = 0; i < printNum; i++) {if (tempArr[randIndex] >= (length - printNum)) {i = 0;} else {printf("%7d", tempArr[randIndex++]);}}printf("\n");
}void knuthShuffle(int arr[], int length) {for (int i = length - 1; i > 1; i--) {swapInt(&arr[i], &arr[rand() % (i + 1)]);}
}void swapInt(int *card_1, int *card_2) {int tCard;tCard = *card_1;*card_1 = *card_2;*card_2 = tCard;
}double BubbleSortTimes(int arr[], int length) {union _LARGE_INTEGER time_start; // 开始时间union _LARGE_INTEGER time_over; // 结束时间LARGE_INTEGER f; // 计时器频率QueryPerformanceFrequency(&f);double dqFreq = (double) f.QuadPart; // 计时器频率QueryPerformanceCounter(&time_start); // 计时开始int temp;for (int i = 0; i < length - 1; i++) { // 外层循环:轮次int index = -1;for (int j = 0; j < length - 1 - i; j++) { // 内层循环:比较并交换位置(找出每轮最大数)if (arr[j] > arr[j + 1]) {temp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = temp;index++;}}if (index == -1) {break; // 为提高排序效率,如果在每轮排序中未发生一次位置交换则代表已经是需要的顺序(直接跳出排序)}}QueryPerformanceCounter(&time_over); // 计时结束// 乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒double run_time = 1000000.0 * (time_over.QuadPart - time_start.QuadPart) / dqFreq;return run_time / 1000.0;
}double SelectSortTimes(int arr[], int length) {struct timespec start;struct timespec end;// 开始时间clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);for (int i = 0; i < length - 1; i++) {int minIndex = i; // 最小数的下标int min = arr[i]; // 最小数的值for (int j = i + 1; j < length; j++) { // 选出本轮最小值,放到当前位置if (min > arr[j]) { // 升序排序min = arr[j];minIndex = j;}}// 将最小值,放在arr[i] (即交换)if (minIndex != i) { // 如果当前位置的数就是最小值,那么不需要进行交换arr[minIndex] = arr[i];arr[i] = min;}}// 结束时间clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);// 总耗时// 转化为 ms 为单位(但是精度可以直接到 ns 级别)double start_ms = start.tv_sec * 1000.0 + start.tv_nsec / 1000000.0;double end_ms = end.tv_sec * 1000.0 + end.tv_nsec / 1000000.0;return end_ms - start_ms;
}double HeapSortTimes(int arr[], int length) {union _LARGE_INTEGER time_start; // 开始时间union _LARGE_INTEGER time_over; // 结束时间LARGE_INTEGER f; // 计时器频率QueryPerformanceFrequency(&f);double dqFreq = (double) f.QuadPart; // 计时器频率QueryPerformanceCounter(&time_start); // 计时开始int temp;// 将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆for (int i = length / 2 - 1; i >= 0; i--) {adjustHeap(arr, i, length);}for (int i = length - 1; i > 0; i--) {// 将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端temp = arr[i];arr[i] = arr[0];arr[0] = temp;// 重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序adjustHeap(arr, 0, i); // 从最顶端 下标0 开始重新调整为堆}QueryPerformanceCounter(&time_over); // 计时结束// 乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒double run_time = 1000000.0 * (time_over.QuadPart - time_start.QuadPart) / dqFreq;return run_time / 1000.0;
}void adjustHeap(int arr[], int i, int length) {// 取出当前元素的值,保存为临时变量int temp = arr[i];// k=i*2+1:k是i结点的左子结点for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {// 在保证有右子结点的前提下,比较左子结点和右子结点的值的大小if (k + 1 < length && arr[k] < arr[k + 1]) {k++; // 如果右子结点大于左子结点,则把 左子结点 赋值为 右子结点}// 如果子结点大于父结点if (arr[k] > temp) {arr[i] = arr[k]; // 把当前子结点的值赋值给父结点i = k; // 把当前子结点作为新的父结点,继续向下循环比较是否还有子结点} else {break; // 直到以 i 父结点的树无子结点未比较为止}}//当for 循环结束后,我们已经将以i 为父结点的树的最大值,放在了 最顶(局部)arr[i] = temp; // 将temp值放到调整后的被交换的位置(子结点)
}double MergeSortTimes(int arr[], int length) {union _LARGE_INTEGER time_start; // 开始时间union _LARGE_INTEGER time_over; // 结束时间LARGE_INTEGER f; // 计时器频率QueryPerformanceFrequency(&f);double dqFreq = (double) f.QuadPart; // 计时器频率QueryPerformanceCounter(&time_start); // 计时开始int tempArr[length];mergeSort(arr, 0, length - 1, tempArr);QueryPerformanceCounter(&time_over); // 计时结束// 乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒double run_time = 1000000.0 * (time_over.QuadPart - time_start.QuadPart) / dqFreq;return run_time / 1000.0;
}void mergeSort(int arr[], int left, int right, int temp[]) {if (left < right) {int mid = (left + right) / 2;// 左边分 递归分法mergeSort(arr, left, mid, temp);// 右边分 递归分法mergeSort(arr, mid + 1, right, temp);// 合并法merge(arr, left, mid, right, temp);}
}void merge(int arr[], int left, int mid, int right, int temp[]) {int i = left; // 初始化 i, 左边有序序列的初始索引int j = mid + 1; // 初始化 j, 右边有序序列的初始索引int t = 0; // 指向 temp 数组的当前索引while (i <= mid && j <= right) { // 只要左边或者右边的索引超过if (arr[i] <= arr[j]) { // 左右索引元素开始比较,如果左边小于等// 于右边索引元素值,将小的元素赋值到temp数组中temp[t++] = arr[i++]; // 索引向后 ++ 移动} else {temp[t++] = arr[j++];}}// 如果左边有剩余while (i <= mid) {temp[t++] = arr[i++];}// 如果右边有剩余while (j <= right) {temp[t++] = arr[j++];}t = 0;int tempLeft = left;while (tempLeft <= right) {arr[tempLeft++] = temp[t++];}
}
实验结果

相关文章:
C数据结构与算法——常见排序算法时间复杂度比较 应用
实验任务 (1) 掌握常见比较排序算法的实现; (2) 掌握常用比较排序算法的性能及其适用场合。 实验内容 (1) 平均时间复杂度O(n2)和O(nlog2n)的算法至少各选两种实现; (2) 待排序的无重复关键字存放在一维整型数组中,数量为60000个ÿ…...
C++并发多线程--死锁问题及解决方法
1--死锁问题 死锁问题:两个线程访问资源时加锁,但都需要对方的资源才能执行释放锁; 代码实例:下面的代码中,当线程 1 使用 my_mutex1 上锁后,会继续使用 my_mutex2 进行上锁,若此时线程 2 已经使…...
【Spring】纯注解开发
1、简介 在Spring3.0升级了纯注解开发模式,使用Java类来代替配置文件,开启了Spring快速开发赛道。 2、定义bean Component Service Controller Repository 3、纯注解开发 使用Configuration声明一个配置类,使用ComponentScan来扫描作为bea…...
【算法心得】正确估计dfs时间复杂度;剪枝优化不怕重构
https://leetcode.cn/problems/verbal-arithmetic-puzzle/ 这题看到题,“表达式中使用的不同字符数最大为 10”,就觉得dfs就完事了,最多不过10!,10!才1e6,1e7这样。如果字符再少点,6! 7! 8!的,…...
通过网关访问微服务,一次正常,一次不正常 (nacos配置的永久实例却未启动导致)
微服务直接访问没问题,通过网关访问,就一次正常访问,一次401错误,交替正常和出错 负载均衡试了 路由配置检查了 最后发现nacos下竟然有2个order服务实例,我明明只开启了一个呀 原来之前的8080端口微服务还残留&…...
div输入框的文字超过指定行数用省略号表示css
实现效果:超过四行用省略号表示 实现方法: .text{overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 4; // 自定义行数-webkit-box-orient: vertical; }...
STM32 F103C8T6学习笔记5:定时器输出不同占空比PWM驱动舵机旋转角度
现在学习使用STM32 F103C8T6的定时器PWM模式,使用PWM驱动舵机转动不同角度,文章提供源码,测试工程,测试动态效果图。 目录 基础原理: 实验目标: 测试视频结果: 测试工程下载: 基…...
液体神经网络:LNN是个啥概念?
一、说明 在在人工智能领域,神经网络已被证明是解决复杂问题的非常强大的工具。多年来,研究人员不断寻求创新方法来提高其性能并扩展其能力。其中一种方法是液体神经网络(LNN)的概念,这是一个利用动态计算功能的迷人框…...
开源数据库Mysql_DBA运维实战 (DCL/日志)
SQL(Structured Query Language 即结构化查询语言) a.DDL语句 数据库定义语言: 数据库,表,视图,索引,存储过程,函数,创建删除ALTER(CREATE DROP ALTER) b.DML语句 数…...
神经网络基础-神经网络补充概念-03-逻辑回归损失函数
概念 逻辑回归使用的损失函数通常是"对数损失"(也称为"交叉熵损失")或"逻辑损失"。这些损失函数在训练过程中用于衡量模型预测与实际标签之间的差异,从而帮助模型逐步调整权重参数,以更好地拟合数…...
基于深度信念神经网络的矿石产量预测,基于DBN的矿石产量预测,DBN的详细原理
目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) DBN的矿石产量预测 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类算法,本文将DBN算法进行矿石产量预测 DB…...
JavaWeb-Filter过滤器
目录 Filter过滤器 1. Filter的生命周期 2.Filter的配置 3.拦截路径 4.拦截具体的使用 5.拦截方式配置(资源被访问方式) 6.FilterChain拦截链 Filter过滤器 filter是过滤器,相比于Servlet的发送请求,filter是用于拦截请求。…...
python如何实现1ms内触发两个接口请求
在Python中,可以通过多线程或者协程来实现1ms内触发两个接口请求。以下是两种方法的示例代码: 1.多线程实现: import threading import requestsdef send_request(url):response requests.get(url)print(response.text)# 创建两个线程&…...
深入解析路由与网络:网络的脉络
目录 路由 广域网 公网 外网 局域网 内网 以太网 Wi-Fi CDN IPv4和IPv6 IP地址分类 无类别域间路由(CIDR) 路由 路由是指在计算机网络中,将数据包从源地址传递到目标地址的过程。在一个复杂的网络中,数据包需要经过多…...
spring.HttpMessageNotReadableException: JSON parse error
实体类如下: Value public class Search{//搜索内容String value;//是否模糊搜索boolean fuzzy true; //其实这样写并不是“默认”模糊搜索,而是“一定是”模糊搜索 }spring.HttpMessageNotReadableException: JSON parse error: Cannot construct ins…...
安全中间件的设计思路和简单实践
rasp 的侵入式特性和拦截特性导致开发和运维普通不太愿意配合,当生产环境出现问题时往往第一时间先把责任推给 rasp,逐渐的安全部门普遍只能把 rasp 设置为告警模式,而且越是大的集群拦截开的就越少,所以字节的 elkeid 和某外卖大…...
试卷扫描成电子版方法分享,这个方法不要错过
很多时候,为了方便传输我们需要将试卷扫描成电子版进行存档,以备不时之需。很多小伙伴如果遇到试卷需要扫描转成电子版可能就不知道该如何操作了,其实试卷扫描是一项非常重要的工作,因此需要注意一些方法和细节。以下是试卷扫描成…...
【PostgreSQL的CLOG解析】
同样还是这张图,之前发过shared_buffer和os cache、wal buffer和work mem的文章,今天的主题是图中的clog,即 commit log,PostgreSQL10之前放在数据库目录的pg_clog下面。PostgreSQL10之后修更名为xact,数据目录变更为pg_xact下面&…...
腾讯云国际站代充-阿里云ECS怎么一键迁移到腾讯云cvm?
今天主要来介绍一下如何通过阿里云国际ECS控制台一键迁移至腾讯云国际CVM。腾讯云国际站云服务器CVM提供全面广泛的服务内容。无-需-绑-定PayPal,代-充-值腾讯云国际站、阿里云国际站、AWS亚马逊云、GCP谷歌云,官方授权经销商!靠谱࿰…...
东方晶源亮相第十一届半导体设备年会,共话发展“芯”机遇
8月11日,以“协力同芯抢机遇,集成创新造设备”为主题的第十一届(2023年)中国电子专用设备工业协会半导体设备年会暨产业链合作论坛(CSEAC)在无锡太湖国际博览中心圆满闭幕。为期3天的CSEAC,通过…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
