一、前言

1、数据结构是什么?

数据结构(Data Structure)是计算机存储、组织数据的⽅式,指相互之间存在⼀种或多种特定关系的数 据元素的集合。没有⼀种单⼀的数据结构对所有⽤途都有⽤,所以我们要学各式各样的数据结构, 如:线性表、树、图、哈希等

下面我们就要踏上学习数据结构的旅程了,我们这部分主要是通过C语言来学习初阶数据结构,后续我们学习C++的时候,就会继续高阶数据结构和算法。

2、算法是什么?

算法(Algorithm):就是定义良好的计算过程,他取⼀个或⼀组的值为输⼊,并产⽣出⼀个或⼀组值作为 输出。简单来说算法就是⼀系列的计算步骤,⽤来将输⼊数据转化成输出结果。

简单来说,算法就是我们在程序中,为了解决一些问题,使用某些方法,然后让其可以的得到正确的值,那么这个方法就是算法。

比如,我们要求一个数的几次放,那么我们使用一个函数实现,然后调用这个函数,输入一个n就是求n次方,那么其也是一种算法,我们求某些问题,其合适的算法不是唯一的。

那么可以解决问题的算法不是唯一的,那么我们遇到问题的时候,该如何选择合适的算法呢?如何去衡量一个算法的好坏呢?有没有啥标准衡量一个算法呢?

我们今天要学习的内容就是去衡量一个算法的好坏的。

我们通过对这个算法的时间复杂度、空间复杂度来衡量他的好坏。

3、数据结构和算法的重要性

我们前面学习C语言的时候,就经常听到数据结构和算法,还有我们看的这么多的竞赛基本都是对于数据结构和算法的竞赛,我们去看招聘网站看到的相关的工作也都基本上对于算法的熟练程度都是有要求的,然后再招聘的笔试和面试中也都是必考的项目,可想而知其的重要性。

如下:

 

那么我们要学好数据结构和算法有没有什么秘诀呢?要学好数据结构和算法的秘诀就是:1、死磕代码  2、画图+思考,做到这两点想不学会都难,前面我们学习C语言的时候,画图的好处其实已经显现出来了。

二、算法效率

如何衡量一个算法的好坏呢?

1、复杂度的概念

法在编写成可执⾏程序后,运⾏时需要耗费时间资源和空间(内存)资源。因此衡量⼀个算法的好坏,⼀般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度

时间复杂度主要衡量⼀个算法的运⾏快慢,⽽空间复杂度主要衡量⼀个算法运⾏所需要的额外空间。在计算机发展的早期,计算机的存储容量很⼩。所以对空间复杂度很是在乎。但是经过计算机⾏业的迅速发展,计算机的存储容量已经达到了很⾼的程度。所以我们如今已经不需要再特别关注⼀个算法的空间复杂度。

三、时间复杂度

在计算机科学中,算法的时间复杂度是一个函数式T(N),它定量的描述了这个算法的运算时间,时间复杂度是衡量一个算法的时间效率,那么有同学就会问了,那么我们为啥不直接去算一个程序的运行时间呢?

1、程序的运行时间运行机器的配置都是有关系的,比如一个硬件好的机器和一个硬件一般的机器,其机器的算力就不一样了,那么其运行时间肯定就不一样的。

2、程序的运行时间和编译的环境也有关系,对于同一个算法程序,用一个老版本的编译器和一个新的编译器在同一台机器下的运行时间也是可能不同的。

3、程序的运行时间只能在程序写好后运行才好测试,没办法咋事前就通过理论进行计算。

4、同一个程序在同一台机器上的每一次的运行时间都会有差异。

所以我们算法的时间复杂度都是通过一个函数式T(N)来衡量的。

那么这个函数式T(N)到底是什么呢?
那么算法的时间这个T(N)函数式计算了程序的执⾏次数。通过c语⾔编译链接章节学习,我们知道算法程序被编译后⽣成⼆进制指令,程序运⾏,就是cpu执⾏这些编译好的指令。那么我们通过程序代码或者理论思想计算出程序的执⾏次数的函数式T(N),假设每句指令执⾏时间基本⼀样(实际中有差别,但是微乎其微),那么执⾏次数和运⾏时间就是等⽐正相关,这样也脱离了具体的编译运⾏环境。执⾏次数就可以代表程序时间效率的优劣。⽐如解决⼀个问题的算法a程序T(N)=N,算法b程序T(N)=N^2,那么算法a的效率⼀定优于算法b。

下面我们通过一个例子来学习:

我们不需要知道这个函数是实现啥功能的,我们只需要求++count语句执行了多少次:

首先是第一个二层循环,其执行的次数为N^2。然后就是第二个for循环,其执行的次数为2*N。第三个循环就执行了10次,那么总的执行次数为:T(N)=N^2+2*N+10

那么通过我们之前的数学的学习,当N达到很大的时候,只有N^2对于执行次数的影响是最大的,实际我们在计算时间复杂度的时候,计算的也不是程序的执行次数。

我们想知道的是输入N对于程序的执行次数的增长趋势的变化的影响,也就是当N变化的时候T(N)的变化咋样。

我们在对复杂度的表示通常使用大O渐进表示法

四、大O渐进表示法

大O符合:是用于描述函数渐进行为的数学符号,使用大O渐进表示法后,我们不需要再将程序的执行次数很精确的计算出来,主要是推算出其影响最大的即可。

下面为大O渐进表示法的规则:

1、时间复杂度函数式T(N)中,其只保留高阶项,去掉那些低阶项,这是因为当N不断变大的时候,低阶项对于结果的影响基本可以忽略不计的了。

如上面的那个案例,其时间复杂度为T(N)=N^2+2*N+10,那么我们使用大O渐进表示法,那么就为:O(N^2)。

2、如果最高阶项存在而且不是1,那么则除去这个项目的常数系数,这是因为当N不断增大的时候,这个系数对于结果的影响也是微乎其微的了,那么也就可以忽略不记了。

3、T(N)中如果只含有常数项,那么我们用常数1取代其所有的加法项,不过要注意的是1并不是代表其次数为1,而是表示其输入N对于时间复杂度的影响趋势是1,也就是一条平行于X轴的直线,即没有影响。

4、如果这个程序的算法的时间复杂度其会有多种情况,即其有最好的情况,平均情况,最坏的情况,那么我们就以最坏的情况为最后的结果。

五、空间复杂度

上面我们已经学习了时间复杂度,那么我们再学习另外一个衡量算法效率的东西:空间复杂度

空间复杂度也是一个函数表达式,其是对一个算法再运行过程中需要临时开辟的空间。

有的同学可能会以为其是开辟的空间的字节数,其实不是,这是以为每个变量的大小差异不是很大,我们所学的数据类型,就是1个字节,2个字节,4 个字节,8个字节等,其差异不是很大。所以空间复杂度算的是我们需要创建的变量个数。

空间复杂度的表达方式也是使用大O表示法,那么其使用规则也是一样的。

不过要注意的是:

函数运行时需要的栈空间(存储参数,局部变量,一些寄存器信息等)在编译的时候已经确定了的,所以空间复杂度主要通过函数在运行时申请的额外空间来确定。

六、练习

1、时间复杂度的练习

练习1:

上面的时间复杂度就很好计算了,我们首先求出其函数表达式T(N),然后再使用大O表示法。

那么我们现在开始计算吧:首先第一个循环,其执行的次数是2*N,然后是第二个循环其执行次数为10,那么其函数表达式T(N)=2*N+10,然后我们使用大O表达法,先保留最高阶次项,那么此时为2N,然后最高次的系数改为1,那么最终其大O表示法为O(N)。

 练习2:

那么我们还是一样先求其函数表达式,上面的函数表达式很明显为:T(N)=1000。那么其和N 没有关系,那么其很明显使用大O表示法的话就需要使用到第三条规则,将其变成1表示:O(1)。

练习3:

可以看到这个时间复杂度和我们上面的计算有点不一样了,我们对N进行取值看看其规律:

当为2的时候,代码的执行次数为1,当N为4的时候,那么代码的执行次数为2,当N为8的时候,代码执行3次......那么我们假设代码的执行次数为x,然后我们可以得到2^x=N。那么我们可以得到x=log N 其中这个对数的底为2,那么我们这个程序的时间复杂度就是O(log N)了。

当我们遇到对数的时间复杂度的时候我们会发现,底数对于复杂度的变化趋势影响不大,那么我们可以不写这个底数,不同的教材间的写法也会有差异,但是区别不大,我们的话建议使用log N的形式。

练习4: 

 

上面的代码是我们前面学习C语言的时候学习的冒泡排序,那么我们来分析其时间复杂度看看:

首先我们看看其两个循环,外层循环:end从n递减到1,那么一个n次迭代。

然后是内层循环遍历整个数组,比较相邻的两个元素,如果前面的大于后面的元素,那么就进行交换。

那么其时间复杂度会受到数组的排序受到影响:

1、最坏情况:完全倒置。

那么外层循环:还是一样要执行n次。

内层循环:

第一轮:n-1次比较,第二轮:n-2次比较.....第n-1轮:1次比较。

那么总的操作次数为:

(n-1)+(n-2)+(n-3)+(n-4)......+1=n(n-1)/2

那么此时的时间复杂度为O(n^2)。 

最好的情况:(已经是降序)

那么外层循环执行1次。

然后内层循环遍历那么就执行n-1次比较。

那么就直接终止了所以其时间复杂度为O(n)。

平均情况:(顺序是随机的)

那么平均需要n(n-1)/4次,那么其时间复杂度为O(n^2)。

2、空间复杂度的练习

这里的的Fac函数很明显使用了递归,而且其每运行一次就要创建一个函数栈帧,然后其不继续递归的条件就是函数的参数变成0,那么就是当N减到0的时候,那么这个函数的空间复杂度为N。大O表达式为O(N)。

七、常见的复杂度的对比 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/76984.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/76984.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/76984.shtml

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

相关文章

记录 | Pycharm中如何调用Anaconda的虚拟环境

目录 前言一、步骤Step1 查看anaconda 环境名Step2 Python项目编译器更改 更新时间 前言 参考文章: 参考视频:如何在pycharm中使用Anaconda创建的python环境 自己的感想 这里使用的Pycharm 2024专业版的。我所使用的Pycharm专业版位置:【仅用…

linux如何用关键字搜索日志

在 Linux 系统中搜索日志是日常运维的重要工作,以下是几种常用的关键字搜索日志方法: 1. 基础 grep 搜索 bash 复制 # 基本搜索(区分大小写) grep "keyword" /var/log/syslog# 忽略大小写搜索 grep -i "error&…

K-均值聚类机器学习算法的优缺点

K-均值聚类是一种常用的无监督学习算法,用于将具有相似特征的数据点聚集到一起。以下是K-均值聚类算法的步骤及其优缺点: K-均值聚类算法步骤: 初始化:随机选择K个点作为初始的聚类中心。分配数据点:将每个数据点分配…

AI驱动SEO关键词实战策略

内容概要 AI驱动的SEO关键词优化体系通过技术融合实现了策略升级。该框架以语义理解模型为基础,结合实时流量监测与行业数据库,构建了包含关键词挖掘、竞争评估、内容适配三大核心模块的闭环系统。通过自然语言处理(NLP)技术解析…

Golang|在线排查协程泄漏

根据我们的代码,前5毫秒内,每隔1毫秒就会来一个请求,5毫秒之后由于前面的协程执行完,后面又会来新的协程,所以协程数目会保持稳定但是代码一运行,协程数量一直增长,发生了协程泄漏 我们可以list…

Java项目之基于ssm的QQ村旅游网站的设计(源码+文档)

项目简介 QQ村旅游网站实现了以下功能: 管理员权限操作的功能包括管理景点路线,板块信息,留言板信息,旅游景点信息,酒店信息,对景点留言,景点路线留言以及酒店留言信息等进行回复,…

高级语言调用C接口(四)结构体(2)-Python

这个专栏好久没有更新了,主要是坑开的有点大,也不知道怎么填,涉及到的开发语言比较多,写起来比较累,需要看的人其实并不多,只能说,慢慢填吧,中间肯定还会插很多别的东西,…

JAVA 主流微服务常用框架及简介

Java微服务架构的优势在于其轻量级、高效资源利用,支持快速开发与灵活部署,拥有强大的生态系统与跨平台兼容性,能够实现高性能与稳定性,并允许独立扩展与技术栈多样性。然而,其劣势也不容忽视,包括架构复杂…

儿童后期至青少年早期脑网络隔离增强的发育机制研究

目录 1 研究背景 2 研究方法 2.1 纵向数据集 2.2 图像预处理 2.3 个体化区域放射组学相似网络构建 2.4 分离度(模块化)度量 2.5 分离度指数发育变化的建模 2.6 分离指数与认知表现的相关性分析 2.7 成像转录组分析 3 研究结果 3.1 三个尺度上…

redis 内存中放哪些数据?

在 Java 开发中,Redis 作为高性能内存数据库,通常用于存储高频访问、低延迟要求、短期有效或需要原子操作的数据。以下是 Redis 内存中常见的数据类型及对应的使用场景,适合面试回答: 1. 缓存数据(高频访问,降低数据库压力) 用户会话(Session):存储用户登录状态、临时…

Spring AOP 学习笔记 之 Advice详解

学习材料:https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/advice.html 1. 什么是 Advice(通知) 定义:Advice 是 AOP 的核心概念之一,表示在特定的连接点(Join Point)上…

数智读书笔记系列029 《代数大脑:揭秘智能背后的逻辑》

《代数大脑:揭秘智能背后的逻辑》书籍简介 作者简介 加里F. 马库斯(Gary F. Marcus)是纽约大学心理学荣休教授、人工智能企业家,曾创立Geometric Intelligence(后被Uber收购)和Robust.AI公司。他在神经科学、语言学和人工智能领域发表了大量论文,并著有《重启AI》等多部…

如何看电脑的具体配置?

李升伟 整理 要查看电脑的具体配置,可以通过系统工具、命令行工具或第三方软件实现,以下是具体方法: 一、系统自带工具查看(无需安装软件) Windows系统: 系统设置: 右键点击桌面“此电脑”…

开源TTS项目GPT-SoVITS,支持跨语言合成、支持多语言~

简介 GPT-SoVITS 是一个开源的文本转语音(TTS)项目,旨在通过少量语音数据实现高质量的语音合成。其核心理念是将基于变换器的模型(如 GPT)与语音合成技术(如 SoVITS,可能指“唱歌语音合成”&am…

D1084低功耗LDO稳压器:技术解析与应用设计

引言 在现代电子设计中,低功耗和高效率是至关重要的。D1084是一款5A低功耗低压差线性稳压器(LDO),以其出色的负载调节能力和快速瞬态响应,成为低电压微处理器应用的理想选择。本文将深入解析D1084的技术特性和应用设计…

Log4j详解:Java日志系统全指南

文章目录 1. 日志系统简介1.1 什么是日志1.2 为什么使用日志框架1.3 Java中的常见日志框架 2. Log4j概述2.1 Log4j简介2.2 Log4j的版本历史2.3 Log4j与Log4j 2的主要区别 3. Log4j架构与核心组件3.1 Logger(日志记录器)3.2 日志级别(Level&am…

【信息系统项目管理师】高分论文:论信息系统项目的整合管理(银行数据仓库项目)

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 正文一、制定项目章程二、制定项目管理计划三、指导和管理项目的实施四、管理项目知识五、监控项目工作六、实施整体变更控制七、结束项目或阶段正文 2023年6月,我以项目经理的身份,参加了 xx银行xx省分行数…

sql server 预估索引大小

使用deepseek工具预估如下: 问题: 如果建立一个数据类型是datetime的索引,需要多大的空间? 回答: 如果建立一个数据类型是 datetime 的索引,索引的大小取决于以下因素: 索引键的大小&#…

干货 | 高性能 Nginx 优化配置总结

文章目录 一、前言二、配置优化2.1 并发处理架构优化2.1.1 工作进程配置2.1.2 事件驱动模型 2.2 传输效率优化2.2.1 零拷贝技术2.2.2 长连接复用 2.3 缓存体系构建2.3.1 文件描述符缓存2.3.2 代理缓存2.3.3 静态资源缓存 2.4 协议层深度优化2.4.1 HTTP/2 支持2.4.2 TLS优化 2.5…

ES DSL 常用修改语句

字段值替换修改 修改sql update zyzkwjj set dhreplace(dh,"WS","WSS") where dh like %WS% update zyzkwjj set dh replace(dh, WS, DZ),ztm replace(ztm, WS, DZ),zrz replace(zrz, WS, DZ) where dh like %WS% or ztm like %WS% or zrz like %WS%…