数据结构(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;
    else
       return 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.结束语

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Set A Light 3D Studio:轻松上手,打造专属3D作品!

set a light 3d studio mac版是mac上一款功能方面相当强大的3D摄影棚布光工具&#xff0c;可以帮助摄影行业的工作用户在进行3D室内拍摄的时候&#xff0c;完成对灯光的位置调整设置&#xff0c;只要运用该软件&#xff0c;支持对各种灯光的道具摆放位置&#xff0c;灯光的反射…

Pycharm远程连接实验室服务器Conda环境配置

如何配置Pycharm和远程服务器 这类博客较多&#xff0c;参考内容 https://blog.csdn.net/fengbao24/article/details/125515542 Python解释器选择&#xff08;conda3&#xff09; 1. Settings -> Add Interpreter -> On SSH 注意&#xff0c;这里的SSH需要在你把远程…

Python读写文本URL蓝牙WIFI自动连接电子名片位置坐标智能海报等NDEF标签

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?id615391857885&spma1z10.5-c.w4002-21818769070.11.60ad789erlonvk 近场通信&#xff08;Near Field Communication&#xff0c;简称NFC&#xff09;&#xff0c;是一种新兴的技术&…

雨云 湖北十堰 8272CL 高防高性能云服务器测评

雨云 湖北十堰 高防云服务器&#xff0c;铂金8272CL高性能处理器&#xff0c;2核2G 10兆 400G防御&#xff0c;仅需60元/月&#xff1b;8核16G 20兆 400G高防&#xff0c;仅需170元/月&#xff0c;年付8折1632元/年&#xff08;约136元/月&#xff09;。 企业级纯NVME固态硬盘高…

javase__进阶 day18 多线程02

1. 线程池 1.1 线程状态介绍 当线程被创建并启动以后&#xff0c;它既不是一启动就进入了执行状态&#xff0c;也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢&#xff1f;Java中的线程 状态被定义在了java.lang.Thread.Stat…

Nginx 防盗链

原文&#xff1a;https://blog.iyatt.com/?p14998 基于 Nginx 1.18 服务器默认配置文件路径&#xff1a;/etc/nginx/sites-available/default 屏蔽非指定域名的解析 我这里如果发现请求的地址不是我的 iyatt.com&#xff0c;就会返回 403 比如有人用其它域名指向我的服务器…

基于 Spring Boot 博客系统开发(四)

基于 Spring Boot 博客系统开发&#xff08;四&#xff09; 本系统是简易的个人博客系统开发&#xff0c;为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。&#x1f33f;&#x1f33f;&#x1f33f; 基于 Spring Boot 博客系统开发&#xff08;三&#xff09;&#x1f…

MySQL库表占用空间排序

在进行数据库备份恢复时&#xff0c;经常会碰到耗时很长的问题。大概率是因为某些库表的占用空间太大。 以下语句按照库表占用空间大小&#xff0c;进行降序排序&#xff1a; SELECT table_schema AS Database,table_name AS Table,ROUND((data_length index_length) / 1024…

【C语言】结构体,联合体,枚举--->自定义类型详解!

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 结构体 1.1 结构体定义 1.2 结构体的声明 1.3 结构体变量的定义和初始化 1.4 结构体的特殊声明->匿名声明 1.5 结构体的自应用 2. 结构体内存对齐…

上海·得物技术沙龙-「无线技术」专场报名开启!

本次无线沙龙聚焦于最新的技术趋势和实践&#xff0c;将在上海/线上为你带来四个令人期待的演讲话题&#xff0c;包括&#xff1a;《快手主App启动接口带宽优化实践》、《得物App视频体验优化实践》、《Chromium内核架构和网络库优化介绍》、《得物App发热监控实践》。相信这些…

本地部署Llama3教程,断网也能用啦!

4月18日&#xff0c;Meta在官方博客官宣了Llama3&#xff0c;标志着人工智能领域迈向了一个重要的飞跃。经过笔者的个人体验&#xff0c;Llama3 8B效果已经超越GPT-3.5&#xff0c;最为重要的是&#xff0c;Llama3是开源的&#xff0c;我们可以自己部署&#xff01; 本文和大家…

C++感受9-Hello Object 生死版•上

你好对象&#xff01; 认识C中基础中的基础类型&#xff1b;创建用户自定义的复合类型&#xff1b;创建新类型的对象&#xff1b;定制新类型对象的生死过程 零、面向对象启蒙 之前我们一直在问候世界&#xff0c;从这节课开始&#xff0c;我们的问候对象就是“对象&#xff08…

验证 python解释器是否安装成功

一. 简介 前一篇文章学习了下载并安装 python解释器&#xff0c;文章如下&#xff1a; windows系统下python解释器安装-CSDN博客 本文验证 python解释器是否安装成功。 二. 验证 python解释器是否安装成功 1. 首先&#xff0c;打开 Windows系统的 "cmd" 界面。…

Netty学习——实战篇8 Handler链调用、TCP粘包和拆包

1 Handler链调用-需求 使用自定义的编码器和解码器来说明Netty的Handler调用机制。客户端发送long类型数据到服务端&#xff1b;服务端发送long到客户端。 2 Handler链调用-实战 2.1 NettyServer.java public class NettyServer {public static void main(String[] args) {…

C语言——小知识和小细节16

一、左旋字符串 例如字符串 abcd &#xff0c;左旋一个就是 bcda &#xff0c;左旋两个就是 cdab 。 方法一&#xff1a;循环 #include <stdio.h> #include <string.h>void func(char* str, int n) {int i 0;int j 0;int len (int)strlen(str);n % len;//超出…

算法打卡day48|动态规划篇16| Leetcode 583. 两个字符串的删除操作、72. 编辑距离

算法题 Leetcode 583. 两个字符串的删除操作 题目链接:583. 两个字符串的删除操作 大佬视频讲解&#xff1a;583. 两个字符串的删除操作视频讲解 个人思路 本题和115.不同的子序列相比&#xff0c;变为了两个字符串都可以删除&#xff0c;整体思路是不变的&#xff0c;依旧…

vue 表格获取当前行索引,加颜色

vue 表格获取当前行索引&#xff0c;加颜色 <span styledisplay:inline-block;width:10px;height:10px;border-radius:50% :style"{background:color[scope.$index]}" />//定义颜色color: [#5387F7, #A794E0, #F3543C, #999999, #77D3F8, #FFA1B4, #26CEBA, #…

ElementUI RUOYI 深色适配

1. 切换按钮&#xff1a;随便找个页面放上去 页面触发逻辑如下 a. html 按钮结构&#xff08;可自定义&#xff09; <el-switchstyle"margin-top: 4px; margin-left: 8px; margin-right: 8px"v-model"isDark"inline-promptactive-icon"Moon"…

使用 Gradio 的“热重载”模式快速开发 AI 应用

在这篇文章中&#xff0c;我将展示如何利用 Gradio 的热重载模式快速构建一个功能齐全的 AI 应用。但在进入正题之前&#xff0c;让我们先了解一下什么是重载模式以及 Gradio 为什么要采用自定义的自动重载逻辑。如果你已熟悉 Gradio 并急于开始构建&#xff0c;请直接跳转到第…

vite和webpacke的常规配置

文章目录 1、vite和webpacke的区分2、vite的常规配置介绍主要部分介绍vite基本配置示例 3、webpacke的常规配置介绍主要部分介绍Webpack 基本配置示例 1、vite和webpacke的区分 相同点&#xff1a; 都是构建工具&#xff0c;用于资源打包 &#xff1b; 都有应用到摇树原理 tre…