数据结构第一课-----------数据结构的介绍

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


数据结构的初识

  • **作者前言**
  • 介绍
  • 算法的时间复杂度和空间复杂度
    • 算法效率
    • 时间复杂度
    • 大O渐进表示法
    • 时间复杂度练习
  • 空间复杂度
  • 总结

介绍

数据结构:是计算机存储、组织数据的方式,指的是相互之间存在一种或者多种特定关系的数据元素的集合
如果学习过数据库的大佬就会知道,数据库主要是在硬盘上操作的管理数据,一般归结为增删改查,里面的精髓全部容纳在里面,而数据结构是在内存上管理数据的,

内存的读取速度快,价格高,带电存储,一旦掉电就会数据丢失,而硬盘的读取和存储速度就很慢,价格低 ,不带电存储,掉电不会数据丢失。

算法是定义良好的计算过程,他取一个或者一组的值输入,并产生出一个或者一组值作为输出,简单的说就是输入数据到输出数据之间的过程就是算法

算法的时间复杂度和空间复杂度

算法效率

1.代码简洁不一定效率高

#include<stdio.h>
int Fib(int a)
{
	if (a < 3)
	{
		return 1;
	}
	else
	{
		return Fib(a - 1) + Fib(a - 2);
	}
}
int main()
{
	printf("%d", Fib(2));


	return 0;

这道题主要是求斐波那契数,使用了递归,代码虽然简便,但是计算过程却不简便,

衡量一个算法的好坏主要从两个维度来衡量。一个是时间复杂度,一个是空间复杂度
时间复杂度主要是用来衡量一个算法的时间,时间越短,空间复杂度就越好。
空间复杂度是用来衡量一个算法在计算过程中空间的使用情况,可以理解,这个算法在使用过程中创建了多少个变量、数组、结构,浪费了多少内存,

时间复杂度

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间,一个算法执行所消耗的时间,一个算法所花费的时间和其中语句的执行次数成正比,算法中的基本操作的执行次数就为算法的时间复杂度
注意这个函数不是C语言里面的函数,而是我们的数学函数,例如
aX^2 + bX+ c ; 这样的表达式
我们来练习一下

void Func1(int N)
{
int count = 0;

for (int i = 0; i < N ; ++ i)
{
 for (int j = 0; j < N ; ++ j)
 {
 ++count;
 }
}
 
for (int k = 0; k < 2 * N ; ++ k)
{
 ++count;
}
int M = 10;
while (M--)
{
 ++count;
}

我们可以利用我们学习的C语言常识来理解一下,第一个for循环执行了NN次
在外层的for首先每循环一次,里面for就会循环N次,外层有N次,总共就会循环N
N次,第二个for循环了2N次
第三个while循环了10次
int count = 0;也执行了一次
所以全部就执行了 F(N) = NN+ 2N+ 11,随着N的增大主要影响这个表达式的结果时NN,所以我们计算时间复杂度就要取这个影响最大的项,那我们就可以使用一种方法大O渐进表示法
O(N^2)

大O渐进表示法

主要是进行估算的
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。
推导大O阶方法
1、用常数1取代运行时间中的所有加法常数。例如O(1),只要运行的次数是常数就用这个来表示
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

时间复杂度练习

void Func2(int N)
{
 int count = 0;
 for (int k = 0; k < 2 * N ; ++ k)
 {
 ++count;
 }
 int M = 10;
 while (M--)
 {
 ++count;
 }
 printf("%d\n", count);
}

这里我们可以的数学表达是就是 F(N) = 2*N + 10, 大O渐进表示就是O(N)

// 计算Func3的时间复杂度?
void Func3(int N, int M)
{
 int count = 0;
 for (int k = 0; k < M; ++ k)
 {
 ++count;
 }
 for (int k = 0; k < N ; ++ k)
 {
 ++count;
 }
 printf("%d\n", count);
}

这道题的时间复杂度的数学表达式是M+ N+ 1,大O渐进表示O(M + N),
这里如果是M大于N就是O(M),如果是M小于 N就是O(N),如果M=N就是O(M)或者O(N)

void Func4(int N)
{
 int count = 0;
 for (int k = 0; k < 100; ++ k)
 {
 ++count;
 }
 printf("%d\n", count);
}

这里的时间复杂度是一个常量,是常量,大O渐进表示就是O(1).

下面我引入一个函数
在这里插入图片描述

#include<stdio.h>
#include<string.h>
int main()
{
	char *p = strchr("dfksdfsfkl", 's');
	printf("%p", p);
	return 0;
}

这个函数的作用是在一个字符串中找字符,找到就返回第一次出现的地址,否则返回NULL
str是要进行查找的字符串。
charcter是要查找的字符,它以整数形式传递,通常使用字符的ASCII码。
假设我们要找一个字符,这个字符可能存在第一个,可能中间,或者末尾,
在这里插入图片描述
这种方法叫预期管理法
有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

// 计算BubbleSort的时间复杂度?
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;
 }
}

这里的我们还要区分一下,两层for不一定是O(N^2),还有可能是O(N),这里的计算主要是次数
(n - 1) + (n - 2)+…+1 +0利用等差数列公式可以求出是n(n -1)/2
时间复杂度主要还是根据代码的思路去进行判断,而不是根据代码,前面根据代码计算时间复杂度是因为前面的代码思路简单

int BinarySearch(int* a, int n, int x)
{
 assert(a);
 int begin = 0;
 int end = n-1;
 // [begin, end]:begin和end是左闭右闭区间,因此有=号
 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;
}

这里是二分查找,使用二分查找的的前提是要有序,无序就不行
时间复杂度是O(log N),为啥是O(log N),我们可以想象一下,当我们通过二分查找当找到最后一个的时候,我们可以反过来想,每次寻找元素个数都减半,那我们通过最后一个元素来反推出元素总数
假设最后找到最后一个元素, 次数设为x ,总数是N , 122*…2 = N我们可以发现,当我们每找一次就会除2.那有找了x次就会有x个2,也就是2^x = N,时间复杂度算的是次数,x = log N(默认以2为底)
在这里插入图片描述

// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{
 if(0 == N)
 return 1;
 
 return Fac(N-1)*N;
}

这里的时间复杂度为O(N), 当参数值为N时 函数调用N次,每次为1,所以时间复杂度就是O(N),时间复杂度算的是次数

// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{
 if(N < 3)
 return 1;
 
 return Fib(N-1) + Fib(N-2);
}

在这里插入图片描述

我们可以看左边,就像一个直角三角型一样 , 总共有N层 ,每一层是2的幂
第一层 2^0,第二层2 ^1 …,
最终的结果 2^0 + 2^1 +2 ^2 +2 ^3 +…+ 2^(N -2),等比数列 :2^(N- 1) - 1
所以最终是O(2 ^N),这种思路我们可以学习,但是实际价值却很低
我们可以使用循环来减少时间复杂度

#include<stdio.h>
#include<string.h>
int main()
{
	int n1 = 1;
	int n2 = 1;
	int n3 = 1;
	int num = 0;
	scanf("%d", &num);
	int i = 0;
	for (i = 0; i < (num - 2) && num >2; i++)
	{
		n3 = n1 + n2;
		n1 = n2;
		n2 = n3;
	}
	printf("%d", n3);
	return 0;
}

空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 。
空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。
空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

// 计算BubbleSort的空间复杂度?
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;
 }
}

这里的变量创建了3个空间复杂度s
在计算空间复杂度时,形参通常不会被考虑在内。空间复杂度主要关注的是算法执行过程中所使用的额外空间,而形参通常是在函数调用时传递的参数,不会占用额外空间。因此,在计算空间复杂度时,通常只考虑算法中使用的变量、数据结构和临时空间等。

// 计算Fibonacci的空间复杂度?
// 返回斐波那契数列的前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)

那下面我来推荐一道题
在这里插入图片描述
这道题我们可以通过创建额外的空间让时间复杂度降低, 数组中的元素充当额外数组的下标,遍历一遍额外数组找出不存在的,就可以解出来,空间复杂度是O(n).时间复杂度是O(n)

// 计算阶乘递归Fac的空间复杂度?
long long Fac(size_t N)
{
 if(N == 0)
 return 1;
 
 return Fac(N-1)*N;
}

这里主要是递归,函数里面调用函数
调用情况:
在这里插入图片描述
一共调用了N次,总共创建了N个空间,空间复杂度是O(N)
而我们计算斐波那契数的空间复杂度也是O(N)
在这里插入图片描述
因为递归的空间复杂度,也是空间的累计,但是不同的是空间是重复利用,为啥要这样说呢?
因为函数调用是一个个调用的,不是一下子调用全部函数
下面的代码可以演示

#include<stdio.h>
#include<string.h>
int fun(int N)
{
	int a = 0;
	printf("%p\n", &a);
}
int fun1(int N)
{
	int a = 0;
	printf("%p\n", &a);
}
int main()
{
	fun(1);
	fun1(1);


	return 0;
}

在这里插入图片描述
在这里插入图片描述

总结

时间复杂度和空间复杂度就介绍到这里了,感兴趣的小可爱可以私聊我

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

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

相关文章

VueRouter 源码解析

重要函数思维导图 路由注册 在开始之前&#xff0c;推荐大家 clone 一份源码对照着看。因为篇幅较长&#xff0c;函数间的跳转也很多。 使用路由之前&#xff0c;需要调用 Vue.use(VueRouter)&#xff0c;这是因为让插件可以使用 Vue export function initUse(Vue: GlobalAP…

有哪些项目适合程序员业余时间做,并且短期内能赚点小钱?

要我说&#xff0c;程序员赚点小钱就别指望着自己搞个大项目了。 这几年的市场环境不好&#xff0c;如果你没点家底的话&#xff0c;打工攒的那点积蓄让你创业&#xff0c;一不小心就会血本无归。 对于程序员来说&#xff0c;最合适的还是给别人打工&#xff01;低风险稳定回款…

Vlice DM蓝牙5.2双模热插拔PCB

键盘使用说明索引&#xff08;均为出厂默认值&#xff09; 软件支持&#xff08;驱动的详细使用帮助&#xff09;一些常见问题解答&#xff08;FAQ&#xff09;首次使用步骤蓝牙配对规则&#xff08;重要&#xff09;蓝牙和USB切换键盘默认层默认触发层0的FN键配置的功能默认功…

创造产业链协同优势后,凌雄科技在DaaS行业转动成长飞轮

企业服务领域&#xff0c;一直存在一种共识&#xff1a;做好很难&#xff0c;但一旦服务模式跑通了&#xff0c;得到了市场的认可&#xff0c;要滚起雪球就会事半功倍。 重资产、重运营的DaaS&#xff08;设备及服务&#xff09;赛道&#xff0c;是个非常典型的细分领域。在这…

苹果AirTag固件更新

苹果公司针对其热销的物品追踪器 AirTag 于今天发布了新的固件更新&#xff0c;最新版本号为 2A61&#xff0c;但是这次更新苹果并未提供发布说明&#xff0c;所以目前还不知道这次更新有什么新内容。 关于这次更新&#xff0c;用户无法自己手动更新 AirTag 固件&#xff0c;因…

能看就能下?这个工具太牛了~

在抖音或者TikTok上看到很多精彩视频&#xff0c;想保存或者在微信或者其他地方分享&#xff0c;但是抖音和TikTok的APP都做了限制&#xff0c;有些视频没有下载权限&#xff0c;而且即使可以下载&#xff0c;也都会带上水印&#xff0c;影响观看效果。那么要如何在抖音和TikTo…

Pandas教程(非常详细)(第一部分)

Pandas 库是一个免费、开源的第三方 Python 库&#xff0c;是 Python 数据分析必不可少的工具之一&#xff0c;它为 Python 数据分析提供了高性能&#xff0c;且易于使用的数据结构&#xff0c;即 Series 和 DataFrame。Pandas 自诞生后被应用于众多的领域&#xff0c;比如金融…

Distribution-Aware Coordinate Representation for Human Pose Estimation阅读笔记

主要研究人体姿态估计中heatmap转坐标的方法&#xff0c;提出一种新的解码方法 &#xff08;其实这人体姿态我毛也不会&#xff0c;过来看看这个heatmap解码方法&#xff09; 代码&#xff1a;https://github.com/ilovepose/DarkPose/blob/master/lib/core/inference.py 方法…

【SOC基础】单片机学习案例汇总 Part1:电机驱动、点亮LED

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

【QT】鼠标常用事件

新建项目 加标签控件 当鼠标进去&#xff0c;显示【鼠标进入】&#xff0c;离开时显示【鼠标离开】 将QLable提升成自己的控件&#xff0c;然后再去捕获 添加文件 改继承的类名 提升类 同一个父类&#xff0c;可以提升 效果 现在代码就和Qlabel对应起来了。 在.h中声明&…

【Azure】存储服务:Azure 的存储账户

文章目录 一、前提知识&#xff08;建议了解&#xff09;二、介绍 Azure 存储帐户三、使用 Microsoft Azure 门户创建存储帐户 一、前提知识&#xff08;建议了解&#xff09; 在每一个云厂商中&#xff0c;都有自身的云存储&#xff0c;也有根据不同功能进行区分的不同类型的…

双目视觉检测 KX02-SY1000型测宽仪 有效修正和消除距离变化对测量的影响

双目视觉检测的基本原理 利用相机测量宽度时&#xff0c;由于单个相机在成像时存在“近大远小”的现象&#xff0c;并且单靠摄入的图像无法知道被测物的距离&#xff0c;所以由被测物的跳动导致的被测物到工业相机之间距离变化&#xff0c;使测量精度难以提高。 因此测宽仪需…

java实现pdf文件添加水印,下载到浏览器

java实现pdf文件添加水印&#xff0c;下载到浏览器 添加itextpdf依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.8</version> </dependency>文件下载到浏览器和指定路径 …

55个软件测试工具,正在做测试的你get到了吗

网络“黑色星期五”威胁&#xff0c;安全漏洞&#xff0c;网上银行盗窃&#xff0c;系统停机时间&#xff0c;以及许多这样的恶梦让全球的企业忧心忡忡难以入眠。确保性能具有加载的安全性和增强的经验是这个领域每个有能力的玩家所必备的。 我们为你提供了一个丰富的软件测试…

如何使用查看器筛选、搜索功能进行数据定位?

前言 我们曾探讨过观测云如何通过将内置视图与查看器相联结&#xff0c;实现更全面的数据关联分析。&#xff08;参见《内置视图联动查看器&#xff0c;实现数据关联分析》&#xff09;这里提到的查看器&#xff0c;实际是一个功能全面且强大的数据查看分析工具。其提供多种搜…

macOS M1安装wxPython报错‘tiff.h‘ file not found的解决方法

macOS12.6.6 M1安装wxPython失败&#xff1a; 报错如下&#xff1a; imagtiff.cpp:37:14: fatal error: tiff.h file not found解决办法&#xff1a; 下载源文件重新编译&#xff08;很快&#xff0c;5分钟全部搞定&#xff09;&#xff0c;分三步走&#xff1a; 第一步&…

【element-ui】表格

效果展示 组件代码 <el-table class"compTableClass" ref"tableOOOOO":class"(className in tableConfig)?tableConfig.className:":data"tableConfig.data" :height"tableConfig.height" style"width: 100%"…

学习笔记|单样本秩和检验|假设检验摘要|Wilcoxon符号检验|规范表达|《小白爱上SPSS》课程:SPSS第十一讲 | 单样本秩和检验如何做?很轻松!

目录 学习目的软件版本原始文档单样本秩和检验一、实战案例二、统计策略三、SPSS操作1、正态性检验2&#xff0e;单样本秩和检验 四、结果解读第一&#xff0c;假设检验摘要第二&#xff0c;Wilcoxon符号检验结果摘要。第三&#xff0c;Wilcoxon符号秩检验图第四&#xff0c;数…

【c++Leetcode】287. Find the Duplicate Number

问题入口 思想&#xff1a;Floyds Tortoise and Hare 这个算法除了可以检测是否有环&#xff08;问题入口&#xff09;&#xff0c;还可以用来检测重复数。当然这还需要一个慢指针才能实现。具体请点击标题跳转到原视频&#xff0c;这里是把内容再梳理一遍。如果有不对的地方…

可以直接在线制作电子画册的网站

​随着互联网技术的发展&#xff0c;越来越多的人开始使用在线工具来制作电子画册。今天&#xff0c;小编就来介绍一款可以直接在线制作电子画册的网站&#xff0c;让你的电子画册更加精美、个性化和实用。 1.首先点击FLBOOK在线制作制作电子杂志平台 2.点击开始制作&#xff0…