数据结构(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://www.hqwc.cn/news/643951.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx配置挂载html

目标 很多软件的官方文档&#xff0c;在国内打开很慢&#xff0c;每次都得等很久&#xff0c;看到官方同时提供了html的包&#xff0c;所以想着挂载到本地nginx下&#xff0c;查看会方便很多。 下载官方html文档包&#xff0c;解压到documentation_htmls下 想添加新的文档也是…

springboot停机关闭前保证处理完请求

application.yml配置 server:shutdown: graceful // 处理完请求在关闭服务server:shutdown: immediate // 立刻关闭&#xff0c;默认 jvm关闭自带的回调

在vscode上面进行分支merge的记录

前言&#xff1a;在我们的项目中&#xff0c;有两个分支&#xff1a;master和liutielong。现在要将liutielong分支的改动merge到master分支中。 如果master分支已经更改了&#xff0c;所以要先pull&#xff08;这是在git bash里面的命令&#xff09;。 git pull origin master…

jvm(JVM快速入门、stack栈、堆、GC垃圾回收、Arthas)

文章目录 1. JVM快速入门1.1. 结构图1.2. 类加载器ClassLoader1.3. 执行引擎Execution Engine1.4. 本地接口Native Interface1.5. Native Method Stack1.6. PC寄存器(程序计数器)1.7. Method Area方法区 2. stack栈3. 堆3.1. 堆体系概述3.1.1. 新生区3.1.2. 老年代3.1.3. 永久代…

【JAVA】UDP与TCP套接字编程

目录 一、UDP数据报套接字编程 1、DatagramSocket API 2、DatagramPacket API 3、InetSocketAddress API 4、示例一 5、示例二 二、TCP流套接字编程 1、ServerSocket API 2、Socket API 3、TCP中的长短连接 4、示例一 5、示例二 一、UDP数据报套接字编程 1、Datag…

SpanBert学习

SpanBERT: Improving Pre-training by Representing and Predicting Spans 核心点 提出了更好的 Span Mask 方案&#xff0c;也再次展示了随机遮盖连续一段字要比随机遮盖掉分散字好&#xff1b;通过加入 Span Boundary Objective (SBO) 训练目标&#xff0c;增强了 BERT 的性…

虚假新闻检测——Adapting Fake News Detection to the Era of Large Language Models

论文地址&#xff1a;https://arxiv.org/abs/2311.04917 1.概论 尽管大量的研究致力于虚假新闻检测&#xff0c;这些研究普遍存在两大局限性&#xff1a;其一&#xff0c;它们往往默认所有新闻文本均出自人类之手&#xff0c;忽略了机器深度改写乃至生成的真实新闻日益增长的现…

消消乐算法总结

前言 最近在工作中遇到一个问题&#xff0c;做一个消消乐的demo项目&#xff0c;连续相同数目超过四个后就要消除。我在网上看了很多解决方案&#xff0c;有十字形&#xff0c;横向&#xff0c;纵向&#xff0c;梯形搜索。越看越迷糊。这不是用一个BFS就能解决的问题吗&#x…

ADC内部运行原理

1以一个简单的外置ADC为例讲解 1在外部由地址锁存和译码经行去控制通道选择开关//去控制外部那一条IO口输入&#xff0c;输入到比较器 2逐次逼近寄存器SAR每次从三态锁存缓冲器读取值在由DAC&#xff08;数模转换成模拟电压&#xff09;在输入到比较器当io信号和DAC信号几乎一样…

详解数据结构:队列(含栈与队列扩展)

一、顺序队列 有一种线性序列&#xff0c;特点是先进先出&#xff0c;这种存储结构称为队列。队列也是一种线性表&#xff0c;只不过它是操作受限的线性表&#xff0c;只能再两端操作&#xff1a;一端进、一端出。进的一端称为队尾&#xff0c;出的一端称为队头。队列可以用顺…

LeetCode78:子集

题目描述 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的 子集 &#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 代码 class Solution { public:vector<vector<int>> res;vector<…

【数据库】MongoDB

文章目录 [toc]数据库操作查询数据库切换数据库查询当前数据库删除数据库查询数据库版本 数据集合操作创建数据集合查询数据集合删除数据集合 数据插入插入id重复的数据 数据更新数据更新一条丢失其他字段保留其他字段 数据批量更新 数据删除数据删除一条数据批量删除 数据查询…