数据结构(C):时间复杂度和空间复杂度

目录

🚀 0.前言

🚀 1.为何会有时间复杂度和空间复杂度的概念

🚀 2.时间复杂度

2.1初步时间复杂度

2.2大O表示法

2.2.1.O(N*N)

2.2.2.O(N)

2.2.3.O(1)

2.3最坏情况?

2.3.1O(N*N)

2.4递归 

2.4.1O(N)

2.4.2O(2^N)

🚀 3.空间复杂度

3.1O(1)

3.2 O(N)

🚀4.结束语


🚀 0.前言

        言C之言,聊C之识,以C会友,共向远方。各位CSDN的各位你们好啊,这里是持续分享数据结构知识的小赵同学,今天要分享的数据结构知识是时间复杂度和空间复杂度,在这一章,小赵将会向大家展开聊聊何为时间复杂度,何为空间复杂度。✊

🚀 1.为何会有时间复杂度和空间复杂度的概念

        其实为何会有这两个概念呢?其实很简单,就像我们人类的工作吧,老板在挑选工作的时候总会挑选那些工作效率高(即用时少),给工资低的人,来作为自己的员工。因为挑选这样的人做自己的员工可以让自己的利益最大化。而我们的计算机在写程序的时候也一样,我们要让自己的程序最好,那么就要降低它的工作时间和占用空间的大小。由此引申出两个概念时间复杂度和空间复杂度。而这两个东西又该如何去看呢?别急小赵下面一一介绍。

🚀 2.时间复杂度

2.1初步时间复杂度

        什么叫时间复杂度呢?其实就是程序运行次数的极限。那固定的次数有极限吗?答案当然是没有啦,所以我们的所有固定次数的程序是最容易看出时间复杂度的。虽然我们在学的时候往往会将它们归向程序的时间复杂度较低的一列,但如果运行次数过多,那它的时间复杂度也是很恐怖的,那什么时候就很多了呢?请看下面的代码:

for (int i = 1; i <= 10000000000; i++)
{for (int j = 1; j <= 10000000000; j++)printf("%d", 1);
}

       大家只要稍微算一下这个代码的运行次数,就会发现这个代码的运行次数无比庞大,而这种代码也往往是我们不能用的,因为其的运行次数太多,尽管没有n但其的时间复杂度也惊为天人。

好了聊完了这个的时间复杂度,下面我们进入正题,来看看我们带n(未知数)的时间复杂度该如何计算和表示。 

2.2大O表示法

        在上面小赵举了一个非常恐怖的例子,明明次数是固定的,但好像程序的运行次数还是如此恐怖,那究竟是原因导致了它呢?其实大多数小伙伴已经看出其中的玄妙了,这个代码的运行是两层循环次数的乘积。同样的代码各位可以看看这个代码:

2.2.1.O(N*N)

for (int i = 0; i < N ; ++ i)
{for (int j = 0; j < N ; ++ j) { ++count;}
}

各位如果去算它的运行次数,就会发现它是N*N次的运行次数,这样的运行次数是很恐怖,那我们该如何记录它呢,于是我们就发明了大O表示法。即O((里面是运行了多少次))。这里我们的程序运行了N*N次,用大O表示法就是O(N*N),像这一类的算法我们一般是不用的,因为其的运行次数太多,时间复杂度太高。如果我们用这个来做程序的话,那个程序往往会很慢。

好了有了这个例子我们就可以举一反三再看看别的程序的时间复杂度了。

2.2.2.O(N)

for (int k = 0; k < 2 * N ; ++ k){++count;}

有了前面的例子相信有不少小伙伴会一个说出这个代码的时间复杂度是O(N),当然也有小伙伴会说是O(2N) ,那这里的答案是什么呢?答案是O(N),为什么呢?其实一般的解释是要省略其中的数字,这里小赵给大家一个解释吧。就像你把N取无穷一样,你会看得起你面前的二吗?答案应该大多数都是不会,那无穷会看得起谁呢?答案就是无穷,只有两个地位差不多或者相似的人才能谈得上话。不然都是空谈。

2.2.3.O(1)

for (int k = 0; k < 100; ++ k){++count;}

那这种没有N的呢?这里我们特殊地给了他们一个位置,我们叫它O(1),虽然在定义上这种程序的运行速度应该很快,但实际上很多时候都会出现诈尸的情况,如我举得第一个例子,其的运行次数太多,让人难以接受,所以各位在做题时也要极为小心,避免写出时间复杂度极高的程序,让程序过不了。

2.3最坏情况?

2.3.1O(N*N)

 好了开胃菜吃多了,下面也该上点正菜,就用我们学过的冒泡排序举例子吧

void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

看到这个程序,很多人会一口直出,这不简简单单, O(N*N),但实际上很多人并不理解为什么是这个答案。那么是这个答案的原因是什么呢?其实是因为我们在看计算机的程序运行次数的时候,往往考虑的其实是他的最差情况,那么这样也就好理解这个答案,按我们去算这个最坏就是每个数字都要换,用数学方法算出来就是(N*(N+1)/2次,然后我们去掉数字,就是N*N,所以这题的结果就是O(N*N)。而这样的时间复杂度其实也决定了冒泡排序不是我们主流的排序方法,因为其的时间复杂度太大。

2.3.1O(log N)

看完了冒泡排序,我们再来看看我们的二分查找。

int BinarySearch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n-1;while (begin <= end){int mid = begin + ((end-begin)>>1);if (a[mid] < x)begin = mid+1;else if (a[mid] > x)end = mid-1;elsereturn mid;
}return -1;
}

二分查找的最坏情况是logN次所以其的时间复杂度是O(logN),这个时间复杂度是很小的,二分查找也是我们在查找数字常用的算法,但是其必须要求数组是已经排好的,这让他有了局限性。

2.4递归 

好了看惯了循环,给各位换换胃口,我们看看递归的时间复杂度该如何看:

2.4.1O(N)

long long Fac(size_t N)
{if(0 == N)return 1;return Fac(N-1)*N;
}

这个代码我们只要一直向下迭代就会发现最后其实是运行了N次,那么其的时间复杂度就是 O(N);

2.4.2O(2^N)

long long Fib(size_t N)
{if(N < 3)return 1;return Fib(N-1) + Fib(N-2);
}

这个递归就相对比较复杂了,也是我们后面二叉树时候将要面对的难题,这里我们我们用递归展开图神器解决

我们对这个代码进行估算,最后会发现我们这个代码最多运行2的N次方-1,那么其的时间复杂度就是O(2^N)。

好了时间复杂度到这里就结束了,相信各位已经能够熟练掌握了,为自己再掌握一个知识点欢呼

🚀 3.空间复杂度

了解了时间复杂度,其实空间复杂度就很简单了,因为这两个都是用的大O表达式,而这里就是吧运行次数改成你这个程序在运行时开辟的额外空间。

直接举例子吧。

3.1O(1)

void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

以冒泡排序举例,x,我们就定为O(1)(或者开辟几个固定空间跟前面一样)。

3.2 O(N)

long long* Fibonacci(size_t n)
{if(n==0)return NULL;long long * fibArray = (long long *)malloc((n+1) * sizeof(long long));fibArray[0] = 0;fibArray[1] = 1;for (int i = 2; i <= n ; ++i){fibArray[i] = fibArray[i - 1] + fibArray [i - 2];}return fibArray;
}

在这个程序中一共开辟了N+1个空间,所以空间复杂度为O(N); 

🚀4.结束语

 好了小赵今天的分享就到这里了,如果大家有什么不明白的地方可以在小赵的下方留言哦,同时如果小赵有什么地方不对也希望得到大家的指点,谢谢各位家人们的支持。你们的支持是小赵创作的动力,加油。

如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持小赵,如有不足还请指点,小赵及时改正,感谢大家支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2979021.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

揭秘分销系统:商业模式的新风向

大家好&#xff0c;我是微三云周丽&#xff0c;今天给大家分析当下市场比较火爆的商业模式&#xff01; 小编今天跟大伙们分享什么是分销系统&#xff1f; 在数字化浪潮席卷全球的今天&#xff0c;电子商务以其独特的优势&#xff0c;正在重塑商业世界的格局。其中&#xff0…

大模型产业盛典上石景山智能算力中心绽放新光芒

2024年4月16日&#xff0c;由中关村数智人工智能产业联盟主办的“2024人工智能大模型产业发展大会”圆满闭幕。在这场盛会中&#xff0c;企商在线石景山智能算力中心以其作为北京最大规模的公共智能算力中心的身份亮相&#xff0c;为首都建设全球数字标杆城市注入了新的活力。 …

KingbaseES数据库bulkload快速导入导出数据

数据库版本&#xff1a;KingbaseES V008R006C008B0014 简介 sys_bulkload 是 kingbase 快速将 CSV 文件导入数据库的命令行工具&#xff0c;它支持串行和并行的方式&#xff0c;是目前导入数据最快的工具。 文章目录如下 1. 基础语法 1.1. 语法说明 1.2. 参数选项 1.3. 配置…

C语言进阶课程学习记录- 函数与宏分析

C语言进阶课程学习记录- 函数与宏分析 实验-宏和函数实验-宏的副作用实验-宏的妙用小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 实验-宏和函数 #include <stdio.h>#define RESET(p, len) …

贪心算法练习day.1

理论基础 贪心算法是一种常见的解决优化问题的方法&#xff0c;其基本思想就是在问题的每个决策阶段&#xff0c;都选择当前看起来最优的选择&#xff0c;即贪心地做出局部的最优决策&#xff0c;以此得到全局的最优解&#xff0c;例如在十张面额不同的钞票&#xff0c;让我们…

批量修改kingbase数据库中表未生成的rowid字段

批量修改生成kingbase的rowid列 show default_with_rowid; 如果结果是off&#xff0c;说明不会生成rowid的列&#xff0c;则无法查询rowid列 想要查询需要手动将表得rowid列加上或者修改上面参数后重新迁移数据批量修改对应用户对应模式下所有表的rowid的存储过程如下&#xf…

【C++】详解初始化列表,隐式类型转化,类静态成员,友元

前言 初始化列表是对构造函数内容的补充&#xff0c;小编会详细的讲解初始化列表的概念&#xff0c;特性&#xff0c;注意点。这是本篇内容的重头戏&#xff0c;小编会先提一个问题来抛砖引玉。 隐式类型转换顾名思义&#xff0c;首先它不需要主动转换&#xff0c;类似于把浮点…

Vision Pro 手势追踪 - ARKit 教程

在 visionOS 中,ARKit 可以实现手部追踪和世界感应等增强现实功能,在 ARKit 中调用手部追踪的流程如下: ARKit 追踪数据使用流程 首先,需要向用户描述手势追踪数据的用途并取得用户授权。 Xcode Info 中填写 NSHandsTrackingUsageDescription 为了确保用户隐私,要调用…

这一世,要学会二维凸包

玩玩二维凸包 前言&注明 最近在学计几&#xff08;计算几何&#xff09;&#xff0c;然后…… 精神状态越来越好了。&#xff08;阿辉~&#xff09; 本文只写了二维凸包的一种解法&#xff1a;扫描法。个人认为和 FHQ_Treap 一样&#xff0c;都是解同类问题的算法中易懂…

IDEA 2021.3.3最新激活破解教程(可激活至2099年,亲测有效)

1、ja-netfilter-all Windows 系统&#xff0c;点击运行 install-current-user.vbs 脚本&#xff0c;为当前用户安装破解补丁 截图是window环境下的激活方式 运行此补丁大约花费几分钟&#xff0c;点击 确定&#xff0c; 等待 Done 完成提示框出现&#xff0c;到这里&#xf…

YashanDB V23.2 LTS发版 | 共享集群首个长期支持版本

4月&#xff0c;YashanDB正式发布长期支持版本YashanDB V23.2 LTS&#xff0c;标志着YashanDB单机主备、共享集群和分布式实时数仓等完整产品体系&#xff0c;已全面进入可规模化使用的长期支持阶段&#xff1b;同时配套数据迁移工具、监控运维工具和开发者工具&#xff0c;可以…

S32 Design Studio PE工具配置canCom

工具配置 基本就是默认配置就行&#xff0c;有需要的话就按照下面的方式改改。 生成代码 在Generated_Code/canCom1.c里面&#xff0c;对应刚才配置的信息。canCom1_InitConfig0是配置结构体&#xff0c;canCom1_State是初始化之后的状态结构体。 flexcan_state_t canCom1_S…

docker 虚拟化与docker的概念

一、云计算的三种服务模式 laas、pass、saas 1.1 IaaS: Infrastructure-as-a-Service&#xff08;基础设施即服务&#xff09; 第一层叫做IaaS&#xff0c;有时候也叫做Hardware-as-a-Service&#xff0c;几年前如果你想在办公室或者公司的网站上运行一些企业应用&#xff0c…

06:HAL----定时器

前言&#xff1a; 每来一个TIM 时钟CNT计数器就记一个数&#xff0c;记到某一个程度就会产生溢出。然后ARR就会装载到CNT计数器里面 一:TIM 1:介绍 TIM&#xff08;Timer&#xff09;定时器 定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断 16位计…

牛客周赛 Round 40(A,B,C,D,E,F)

比赛链接 官方讲解 这场简单&#xff0c;没考什么算法&#xff0c;感觉有点水。D是个分组01背包&#xff0c;01背包的一点小拓展&#xff0c;没写过的可以看看&#xff0c;这个分类以及这个题目本身都是很板的。E感觉就是排名放高了导致没人敢写&#xff0c;本质上是个找规律…

消费增值:革新你的消费体验,让每一分钱都更有价值

亲爱的顾客们&#xff0c;你们好&#xff01;今天&#xff0c;我想为大家介绍一种革新性的消费模式——消费增值&#xff0c;它赋予每一次购物以额外的价值&#xff0c;让消费过程变得更加丰富多彩。 过去&#xff0c;我们的消费观念往往是“一手交钱&#xff0c;一手交货”&am…

Pytorch:张量的梯度计算

目录 一、自动微分简单介绍1、基本原理2、梯度计算过程3、示例&#xff1a;基于 PyTorch 的自动微分a.示例详解b.梯度计算过程c.可视化计算图 4、总结 二、为什么要计算损失&#xff0c;为何权重更新是对的&#xff1f;1、梯度下降数学原理2、梯度上升 三、在模型中使用自动微分…

Hbuilder快捷键个人习惯修改

自定义修改 [// {"key":"ctrld","command":"editor.action.deleteLines"},// {"key":"ctrle","command":"editor.action.addSelectionToNextFindMatch"}//目录内查找字符串{"key"…

DC-DC电源设计中电感选型详解

电感参数: DC-DC 电感选型步骤: 1, 根据 DC-DC 的输入输出特性计算所需的最小电感量。 (1)对于 Buck 型 DC-DC,计算公式如下 Lmin= 【Vout*(1-Vout/Vinmax)】/ (Fsw*Irpp ) 其中: Vinmax = maximum input voltage Vout = output voltage fsw = switching frequency…

电路仿真,为何国产软件成首选?

随着科技的飞速发展&#xff0c;电路仿真技术在电子工程设计中的作用日益凸显。面对市场上琳琅满目的电路仿真软件&#xff0c;为何我们应该优先选择国产软件呢&#xff1f;本文将从多个方面为您深入解析。 一、国产软件的安全性保障 在当前国际形势下&#xff0c;信息安全尤为…