【初阶数据结构】——算法复杂度

news2025/5/10 15:14:07

一、前言

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.coloradmin.cn/o/2335981.html

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

相关文章

Google-A2A协议全面解析:一文掌握Agent-to-Agent协议的核心与应用

前言: 在当今人工智能技术飞速发展的时代,智能体(Agent)已悄然融入我们生活的各个角落。无论是个人智能助手,还是企业的自动化工具,各类AI代理的应用愈发广泛。但目前这些智能体之间大多处于孤立状态&…

Linux-服务器添加审计日志功能

#查看audit软件是否在运行(状态为active而且为绿色表示已经在运行) systemctl start auditd #如果没有在运行的话,查看是否被系统禁用 (audit为0表示被禁用) cat /proc/cmdline | grep -w "audit=0" #修改/etc/default/grub里面audit=0 改为audit=1 #更新GRUB…

基于机器视觉的多孔零件边缘缺陷检测(源码C++、opencv、凸包、凸缺陷检测)

👑主页:吾名招财 👓简介:工科学硕,研究方向机器视觉,爱好较广泛… ​💫签名:面朝大海,春暖花开! 基于机器视觉的多孔零件边缘缺陷检测(源码C、ope…

如何使用AI辅助开发CSS3 - 通义灵码功能全解析

一、引言 CSS3 作为最新的 CSS 标准,引入了众多新特性,如弹性布局、网格布局等,极大地丰富了网页样式的设计能力。然而,CSS3 的样式规则繁多,记忆所有规则对于开发者来说几乎是不可能的任务。在实际开发中&#xff0c…

MySQL入门:数据表的创建

​今天我们来介绍一下除HTML外的另一种语言:MySQL语言; MySQL:即一种用于管理和处理关系数据库的标准语言。要用于执行查询、更新、管理数据库中的数据以及定义和操作数据库结构。 接下来我会逐一介绍它的作用以及其中数据表,数据…

数据库的基本原则

数据库的核心原则 原子性与持久性:原子性(Atomicity)确保一个事务中的所有操作要么全部完成,要么完全不执行,不会出现部分完成的情况。持久性(Durability)则保证一旦事务提交成功,即…

Rust 中的Relaxed 内存指令重排演示:X=0 Y=0 是怎么出现的?

🔥 Rust 中的内存重排演示:X0 && Y0 是怎么出现的? 在并发编程中,我们经常会听说“内存重排(Memory Reordering)”这个术语,但它似乎总是只出现在理论或者别人口中的幻觉里。本文将通过…

C++进程间通信开发实战:高效解决项目中的IPC问题

C进程间通信开发实战:高效解决项目中的IPC问题 在复杂的软件项目中,进程间通信(Inter-Process Communication, IPC)是实现模块化、提高系统性能与可靠性的关键技术之一。C作为一门高性能的编程语言,广泛应用于需要高效…

FPGA-DDS技术的波形发生器

1.实验目的 1.1掌握直接数字频率合成(DDS)的基本原理及其实现方法。 1.2在DE2-115 FPGA开发板上设计一个可调频率的正弦波和方波发生器,频率范围10Hz~5MHz,最小分辨率小于1kHz。 1.3使用Quartus II进行仿真,并通过S…

C#实现通过MQTT Broker——EMQX发布订阅消息及其认证、授权的安全配置操作

一、准备内容 MQTT的构成、使用场景、工作原理介绍-CSDN博客文章浏览阅读656次,点赞7次,收藏12次。MQTT(Message Queuing Telemetry Transport)是一种轻量级、基于发布-订阅模式的消息传输协议【适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境】它在物联网应用中…

【双指针】三数之和(medium)

三数之和(medium) 题⽬描述:解法(排序双指针):算法思路:C 算法代码:Java 算法代码:注:数组转列表 题⽬链接:15. 三数之和 题⽬描述: …

【项目管理】第17章 项目干系人管理-- 知识点整理

项目管理-相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 (一)知识总览 项目管理知识域 知识点: (项目管理概论、立项管理、十大知识域、配置与变更管理、绩效域) 对应:第6章-第19章 第6章 项目管理概论 4分第13章 项目资源管理 3-4分第7章 项目…

视频融合平台EasyCVR可视化AI+视频管理系统,打造轧钢厂智慧安全管理体系

一、背景分析 在轧钢厂,打包机负责线材打包,操作人员需频繁进入内部添加护垫、整理包装、检修调试等。例如,每班产线超过300件,12小时内人员进出打包机区域超过300次。若员工安全意识薄弱、违规操作,未落实安全措施就…

无参数RCE

无参数RCE(Remote Code Execution,远程代码执行) 是一种通过利用目标系统中的漏洞,在不直接传递用户可控参数的情况下,实现远程执行任意代码的攻击技术。与传统的RCE攻击不同,无参数RCE不依赖外部输入参数…

C++ 智能指针底层逻辑揭秘:优化内存管理的核心技术解读

目录 0.为什么需要智能指针? 1.智能指针的使用及原理 RAII: 智能指针的原理: 2.智能指针有哪些? std::auto_ptr std::unique_ptr std::shared_ptr std::weak_ptr 0.为什么需要智能指针? 想要回答这个问题&…

Vue接口平台学习七——接口调试页面请求体

一、实现效果图及简单梳理 请求体部分的左边,展示参数,分text和file类型。 右边部分一个el-upload的上传文件按钮,一个table列表展示,一个显示框,用于预览选择的文件,点击可大图展示。 二、页面内容实现 …

小程序css实现容器内 数据滚动 无缝衔接 点击暂停

<view class"gundongBox"><!-- 滚动展示信息的模块 --><image class"imgWid" :src"imgurlgundong.png" mode"widthFix"></image><view class"gundongView"><view class"container&qu…

【力扣】day1

文章目录 27.移除元素26. 删除有序数组的重复项 27.移除元素 26. 删除有序数组的重复项 我们仔细看一下这两道题的最后的返回值,为什么第一题返回slow 而第二题返回slow1 最后的返回值该如何返回绝对不是凭感觉,我们自己分析一下第一个slow,从0位置开始, 遇到val值就开始和fas…

图像预处理-色彩空间补充,灰度化与二值化

一.图像色彩空间转换 1.1 HSV颜色空间 HSV颜色空间使用色调&#xff08;Hue&#xff09;、饱和度&#xff08;Saturation&#xff09;和亮度&#xff08;Value&#xff09;三个参数来表示颜色 一般对颜色空间的图像进行有效处理都是在HSV空间进行的&#xff0c;然后对于基本…

项目交接时信息遗漏,如何预防

项目交接时&#xff0c;信息遗漏可能导致任务延误、质量下降和团队混乱&#xff0c;因此&#xff0c;建立系统化的交接流程和使用专业的工具是防止信息遗漏的有效策略。交接过程中的信息丢失往往源自沟通不畅、文档不完整或者责任不明确等问题&#xff0c;这不仅影响项目的顺利…