【算法】计算程序执行时间(C/C++)

【算法】计算程序执行时间(C/C++)

引言

我们在写算法时要考虑到算法的执行效率,有的题目规定了时间限制,我们需要在这个时间之内去解决问题。如果我们需要比对算法的好坏,就需要输出这个程序运行了多长时间。

在C或C++中计算程序执行时间,可以使用多种方法,下面我介绍几种比较常见且好用的几种方法,大家可以选择适合自己的一种记住就可以了。

方法1:使用 clock() 函数(C/C++)

在C/C++中,<time.h>库提供了clock()函数。这个方法是博主比较推荐的一个,非常简便,且易懂,它用于测量程序的CPU时间。clock() 函数返回程序从启动到函数被调用时所经过的时钟周期数。这个函数主要用于测量程序的CPU时间消耗,而不是实际的墙钟时间(即从墙上的时钟测量的时间)。

函数原型

clock_t clock(void);
  • clock_t 类型,表示自程序启动以来的时钟周期数。 

使用实例:

以下是使用clock()函数计算递归与非递归程序执行时间的示例代码:

#include<iostream> #include<time.h> using namespace std; typedef long long ll; ll n, sum=1; ll fun(int dep) {//递归函数 if (dep == 1) { return 1; } else { return 2 * (fun(dep - 1) + 1); } } void test0() {//非递归直接利用数学公式推理 cin >> n; for (int i = 0; i < n-1; i++) { sum = (sum + 1) * 2; } cout << sum << endl; //printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC); } void test01() { cin >> n; cout << fun(n) << endl; //printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC); } int main() { // 开始时间 clock_t start = clock(); // 要执行的代码 // ... test01(); // 结束时间 clock_t end = clock(); // 计算执行时间(以秒为单位) double execution_time = (double)(end - start) / CLOCKS_PER_SEC; // 输出执行时间 printf("程序执行时间:%f 秒\n", execution_time); return 0; }

 

第一个是 递归的程序占用CPU的时间,第二个是非递归的程序占用CPU的时间。

注意事项

  • CLOCKS_PER_SEC 是 <time.h> 库中定义的一个宏,表示每秒的时钟周期数。
  • (end - start) 单位是毫秒, 除以CLOCKS_PER_SEC周期转化为以秒为单位。
  • clock() 函数返回的是程序占用CPU的时间 ≠ 程序的实际运行时间。
  • clock() 函数返回的是程序占用CPU的时间,不包括睡眠时间或其他非CPU时间。
  • 在多处理器系统上,clock() 函数的行为可能有所不同,具体取决于操作系统的实现。
  • clock() 函数的精度依赖于系统,可能每次运行程序可能不相同。

clock() 函数是测量程序性能的一个简单工具,但它不适用于需要高精度时间测量的场景,适用于对比算法时,不需要计算准确时间。对于更高精度的时间测量,可以考虑使用C++11中的 <chrono> 库,或者在Unix-like系统中使用 clock_gettime() 函数。


方法2:使用 <chrono> 库(C++11及以上)

C++11引入了<chrono>库,它提供了高精度的时间测量功能。这个库里面有很多函数,都是与时间有关的,功能非常强大,下面列举一个比较常用的函数。

函数实例:

std::chrono::system_clock::now获取当前系统时间的时间点
std::chrono::steady_clock::now获取当前稳定时间的时间点
std::chrono::high_resolution_clock::now获取当前高分辨率时间的时间点
std::chrono::time_point模板类,用于表示时间点
std::chrono::duration模板类,用于表示时间间隔
std::chrono::system_clock::to_time_ttime_point转换为std::time_t
std::chrono::system_clock::from_time_tstd::time_t转换为time_point
std::put_time用于将时间格式化为字符串
std::this_thread::sleep_for使当前线程睡眠一段时间

这个是实打实的计算程执行时间的,其原理类似一个计时器,当执行到 auto start = std::chrono::high_resolution_clock::now();这个语句获取一个时间,开始计时。auto end = std::chrono::high_resolution_clock::now();这个语句也是获取一个时间,执行完就结束计时,最后,使用count()函数以秒为单位打印出运行时间。

代码示例:

以下是使用<chrono>库计算程序执行时间的示例代码:

#include <iostream> #include <chrono> using namespace std; int main() { // 开始时间点 auto start = chrono::high_resolution_clock::now(); // 要执行的代码 // ... // 结束时间点 auto end = chrono::high_resolution_clock::now(); // 计算持续时间 chrono::duration<double, milli> duration = end - start; // 输出执行时间 cout << "程序执行时间:" << duration.count() << "毫秒" << endl; return 0; }

方法3:使用time.h头文件中的time()函数

time.h 是 C 语言标准库中的一个头文件,它提供了多种与时间相关的函数。这个time函数是C语言初学者最熟悉的一个。其中,time() 函数用于获取当前的日历时间(自1970年1月1日00:00:00 UTC以来的秒数)。

time.h头文件常用函数:

  1. time():
    1. 功能:获取当前时间。
    2. 原型:time_t time(time_t *tloc);
    3. 返回值:返回当前时间(自1970年1月1日00:00:00 UTC以来的秒数),如果出错返回-1。
    4. 参数:tloc是一个可选的指针,如果提供,函数会将当前时间存储在这个指针指向的位置。
  2. ctime():
    • 功能:将 time_t 值转换为本地时间的字符串表示。
    • 原型:char *ctime(const time_t *timep);
    • 返回值:返回一个指向以 null 结尾的字符串的指针,该字符串表示本地时间。
  3. localtime():
    • 功能:将 time_t 值转换为表示本地时间的 tm 结构体。
    • 原型:struct tm *localtime(const time_t *timep);
    • 返回值:返回一个指向 tm 结构体的指针,该结构体包含本地时间。
  4. gmtime():
    • 功能:将 time_t 值转换为表示 UTC 时间的 tm 结构体。
    • 原型:struct tm *gmtime(const time_t *timep);
    • 返回值:返回一个指向 tm 结构体的指针,该结构体包含 UTC 时间。
  5. difftime():
    • 功能:计算两个 time_t 值之间的差异(以秒为单位)。
    • 原型:double difftime(time_t time1, time_t time2);
    • 返回值:返回两个时间之间的差异。
  6. mktime():
    • 功能:将 tm 结构体转换为 time_t 值。
    • 原型:time_t mktime(struct tm *timeptr);
    • 返回值:返回表示时间的时间戳。
  7. asctime():
    • 功能:将 tm 结构体转换为 24 小时制的时间字符串。
    • 原型:char *asctime(const struct tm *timeptr);
    • 返回值:返回一个指向以 null 结尾的字符串的指针,该字符串表示时间。
  8. strftime():
    • 功能:根据指定的格式将 time_t 或 tm 结构体的时间格式化为字符串。
    • 原型:size_t strftime(char *strDest, size_t maxsize, const char *format, const struct tm *timeptr);
    • 返回值:返回写入的字符数。

代码示例:

以下是如何使用 time.h 头文件中的 time() 函数来计算递归与非递归程序的一个简单示例:

#include<iostream> #include<time.h> using namespace std; typedef long long ll; ll n, sum=1; ll fun(int dep) {//递归函数 if (dep == 1) { return 1; } else { return 2 * (fun(dep - 1) + 1); } } void test0() {//非递归直接利用数学公式推理 cin >> n; for (int i = 0; i < n-1; i++) { sum = (sum + 1) * 2; } cout << sum << endl; } void test01() { cin >> n; cout << fun(n) << endl; } int main(){ time_t start=time(NULL);//开始时间 test01();//这里填写您测试的代码 time_t end =time(NULL);//结束时间 double dif_time=difftime(end, start);//计算差值 cout<<dif_time<<endl; return 0; }

对于这种计算算法的执行效率肯定是不会考的,可能在测试以及开发过程中使用,大家看看图一乐就行,对于日期问题的考察可以看一下这一篇文章:【算法】日期问题(C/C++)-ZEEKLOG博客

执笔至此,感触彼多,全文将至,落笔为终,感谢大家的支持。

Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk