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

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) 掌握常见比较排序算法的实现&#xff1b; (2) 掌握常用比较排序算法的性能及其适用场合。 实验内容 (1) 平均时间复杂度O(n2)和O(nlog2n)的算法至少各选两种实现&#xff1b; (2) 待排序的无重复关键字存放在一维整型数组中&#xff0c;数量为60000个&#xff…...

C++并发多线程--死锁问题及解决方法

1--死锁问题 死锁问题&#xff1a;两个线程访问资源时加锁&#xff0c;但都需要对方的资源才能执行释放锁&#xff1b; 代码实例&#xff1a;下面的代码中&#xff0c;当线程 1 使用 my_mutex1 上锁后&#xff0c;会继续使用 my_mutex2 进行上锁&#xff0c;若此时线程 2 已经使…...

【Spring】纯注解开发

1、简介 在Spring3.0升级了纯注解开发模式&#xff0c;使用Java类来代替配置文件&#xff0c;开启了Spring快速开发赛道。 2、定义bean Component Service Controller Repository 3、纯注解开发 使用Configuration声明一个配置类&#xff0c;使用ComponentScan来扫描作为bea…...

【算法心得】正确估计dfs时间复杂度;剪枝优化不怕重构

https://leetcode.cn/problems/verbal-arithmetic-puzzle/ 这题看到题&#xff0c;“表达式中使用的不同字符数最大为 10”&#xff0c;就觉得dfs就完事了&#xff0c;最多不过10!&#xff0c;10!才1e6&#xff0c;1e7这样。如果字符再少点&#xff0c;6! 7! 8!的&#xff0c;…...

通过网关访问微服务,一次正常,一次不正常 (nacos配置的永久实例却未启动导致)

微服务直接访问没问题&#xff0c;通过网关访问&#xff0c;就一次正常访问&#xff0c;一次401错误&#xff0c;交替正常和出错 负载均衡试了 路由配置检查了 最后发现nacos下竟然有2个order服务实例&#xff0c;我明明只开启了一个呀 原来之前的8080端口微服务还残留&…...

div输入框的文字超过指定行数用省略号表示css

实现效果&#xff1a;超过四行用省略号表示 实现方法&#xff1a; .text{overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 4; // 自定义行数-webkit-box-orient: vertical; }...

STM32 F103C8T6学习笔记5:定时器输出不同占空比PWM驱动舵机旋转角度

现在学习使用STM32 F103C8T6的定时器PWM模式&#xff0c;使用PWM驱动舵机转动不同角度&#xff0c;文章提供源码&#xff0c;测试工程&#xff0c;测试动态效果图。 目录 基础原理&#xff1a; 实验目标&#xff1a; 测试视频结果&#xff1a; 测试工程下载&#xff1a; 基…...

液体神经网络:LNN是个啥概念?

一、说明 在在人工智能领域&#xff0c;神经网络已被证明是解决复杂问题的非常强大的工具。多年来&#xff0c;研究人员不断寻求创新方法来提高其性能并扩展其能力。其中一种方法是液体神经网络&#xff08;LNN&#xff09;的概念&#xff0c;这是一个利用动态计算功能的迷人框…...

开源数据库Mysql_DBA运维实战 (DCL/日志)

SQL&#xff08;Structured Query Language 即结构化查询语言&#xff09; a.DDL语句 数据库定义语言&#xff1a; 数据库&#xff0c;表&#xff0c;视图&#xff0c;索引&#xff0c;存储过程&#xff0c;函数&#xff0c;创建删除ALTER(CREATE DROP ALTER) b.DML语句 数…...

神经网络基础-神经网络补充概念-03-逻辑回归损失函数

概念 逻辑回归使用的损失函数通常是"对数损失"&#xff08;也称为"交叉熵损失"&#xff09;或"逻辑损失"。这些损失函数在训练过程中用于衡量模型预测与实际标签之间的差异&#xff0c;从而帮助模型逐步调整权重参数&#xff0c;以更好地拟合数…...

基于深度信念神经网络的矿石产量预测,基于DBN的矿石产量预测,DBN的详细原理

目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) DBN的矿石产量预测 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类算法,本文将DBN算法进行矿石产量预测 DB…...

JavaWeb-Filter过滤器

目录 Filter过滤器 1. Filter的生命周期 2.Filter的配置 3.拦截路径 4.拦截具体的使用 5.拦截方式配置&#xff08;资源被访问方式&#xff09; 6.FilterChain拦截链 Filter过滤器 filter是过滤器&#xff0c;相比于Servlet的发送请求&#xff0c;filter是用于拦截请求。…...

python如何实现1ms内触发两个接口请求

在Python中&#xff0c;可以通过多线程或者协程来实现1ms内触发两个接口请求。以下是两种方法的示例代码&#xff1a; 1.多线程实现&#xff1a; import threading import requestsdef send_request(url):response requests.get(url)print(response.text)# 创建两个线程&…...

深入解析路由与网络:网络的脉络

目录 路由 广域网 公网 外网 局域网 内网 以太网 Wi-Fi CDN IPv4和IPv6 IP地址分类 无类别域间路由&#xff08;CIDR&#xff09; 路由 路由是指在计算机网络中&#xff0c;将数据包从源地址传递到目标地址的过程。在一个复杂的网络中&#xff0c;数据包需要经过多…...

spring.HttpMessageNotReadableException: JSON parse error

实体类如下&#xff1a; Value public class Search{//搜索内容String value;//是否模糊搜索boolean fuzzy true; //其实这样写并不是“默认”模糊搜索&#xff0c;而是“一定是”模糊搜索 }spring.HttpMessageNotReadableException: JSON parse error: Cannot construct ins…...

安全中间件的设计思路和简单实践

rasp 的侵入式特性和拦截特性导致开发和运维普通不太愿意配合&#xff0c;当生产环境出现问题时往往第一时间先把责任推给 rasp&#xff0c;逐渐的安全部门普遍只能把 rasp 设置为告警模式&#xff0c;而且越是大的集群拦截开的就越少&#xff0c;所以字节的 elkeid 和某外卖大…...

试卷扫描成电子版方法分享,这个方法不要错过

很多时候&#xff0c;为了方便传输我们需要将试卷扫描成电子版进行存档&#xff0c;以备不时之需。很多小伙伴如果遇到试卷需要扫描转成电子版可能就不知道该如何操作了&#xff0c;其实试卷扫描是一项非常重要的工作&#xff0c;因此需要注意一些方法和细节。以下是试卷扫描成…...

【PostgreSQL的CLOG解析】

同样还是这张图&#xff0c;之前发过shared_buffer和os cache、wal buffer和work mem的文章&#xff0c;今天的主题是图中的clog&#xff0c;即 commit log&#xff0c;PostgreSQL10之前放在数据库目录的pg_clog下面。PostgreSQL10之后修更名为xact,数据目录变更为pg_xact下面&…...

腾讯云国际站代充-阿里云ECS怎么一键迁移到腾讯云cvm?

今天主要来介绍一下如何通过阿里云国际ECS控制台一键迁移至腾讯云国际CVM。腾讯云国际站云服务器CVM提供全面广泛的服务内容。无-需-绑-定PayPal&#xff0c;代-充-值腾讯云国际站、阿里云国际站、AWS亚马逊云、GCP谷歌云&#xff0c;官方授权经销商&#xff01;靠谱&#xff0…...

东方晶源亮相第十一届半导体设备年会,共话发展“芯”机遇

8月11日&#xff0c;以“协力同芯抢机遇&#xff0c;集成创新造设备”为主题的第十一届&#xff08;2023年&#xff09;中国电子专用设备工业协会半导体设备年会暨产业链合作论坛&#xff08;CSEAC&#xff09;在无锡太湖国际博览中心圆满闭幕。为期3天的CSEAC&#xff0c;通过…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...