【PHP数据结构】在学数据结构和算法的时候我们究竟学的是啥?
一说到数据结构与算法,大家都会避之不及。这本来是一门专业基础课,但是大部分人都并没有学好,更不用说我这种半路出家的码农了。说实话,还是很羡慕科班出身的程序员,因为你们在日常工作或者面试中,只需要复习一下就好了,而我则是完全的从头开始学。不过,还好一切都不晚,在这里,我们就用 PHP 作为示例代码,来和大家一起真正的从头学一遍恐怖的数据结构与算法。
数据结构
什么是数据结构呢?
数据结构是带“结构”的数据元素的集合,“结构”就是指数据元素之间存在的关系
这是严蔚敏老师在《数据结构》第二版中对数据结构的定义。其实,就是关于数据的一种组合形式。就像你去一家书店,或者是图书馆,或者是你家的书柜。这些书应该怎么摆放呢?关于书的摆放形式,就是数据结构。你可以乱七八糟的摆放,也可以分门别类的摆放,也可以根据自己的兴趣爱好摆放,也可以将最常用的书放在手边,将不常看的书放在柜子的深处。这些都是数据结构。
在程序世界中,数据结构包含两种形式,一种是逻辑结构,一种是物理结构。
逻辑结构
即使你完全没有接触过数据结构,但只要你学习过编程,一定会多多少少地听说过这样一些名词:集合、线性表、树、图,它们指的就是数据结构中的逻辑结构。也就是从逻辑关系上描述数据,是具体问题抽象出来的数学模型。比如我们将书进行分类,每个分类下放着相对应的书籍,这就是一种树形结构。或者我们将书按书名拼音建立索引,然后在书架上贴上索引标签,这就是一种哈希结构。
逻辑结构将是我们整个学习中的一个重点,因为各种算法都是针对这些结构的操作实现。这个我们在下面的算法解释中再进行详细的说明。
物理结构
物理结构主要是数据的物理存储方式,也叫做存储结构。这个非常好记,它只有两种形式,顺序存储结构和链式存储结构。通常,顺序存储结构我们使用数组来表示,而链式存储结构在 C语言 中使用结构体的指针来表示,但在 PHP 中,链式结构我们将使用类来表述。
上面说的那些逻辑结构,都可以用顺序或者链式的方式来实现,不管使用哪种方式,都可以完成对应逻辑结构的算法操作,但不同的形式或者算法又有不同的效率。而效率,正是整个数据结构和算法学习核心中的核心。
算法
接下来我们看看什么是算法。
算法是一个有限指令集,它接受一些输入(有些情况下不需要输入),产生输出,并一定在有限步骤之后终止
这是陈越老师在浙大版《数据结构》第二版中对于算法的定义。其实我们简单点理解的话,针对上面的数据结构的一系列操作,就是算法。比如说我们定义了一个树,如何遍历这颗树呢?这就是一个算法,遍历一颗树有先序、中序、后序,也可以进行层序遍历,有这么多种方法,哪种好?哪种不好?用哪种物理结构?线性还是链式?这些结论都以算法的执行效率为基础。可以说,算法种类繁多,效率也千差万别,但是,不能一棒子打死说某个算法一定不好,每种算法也有它不同的应用场景。这就是我们要研究算法的原因。
关于算法,我们最关心的是它的效率,这个效率在这里我们使用的是时间复杂度和空间复杂度来定义的。
时间复杂度
时间复杂度一般使用 O(n) 来表示,它关心的是问题规模和语句频度,一般会以 n 表示问题规模 (注意,这个 n 是未知的,如果这个 n 是已知的,那么它就是常数阶)。这个 n 有可能是一个常数(n 明确等于多少),记成 O(1) 。这是最好的情况,也可以线性增长,如 O(n) 。当然也可能对数或指数级增长,O(logN) 、 O(N^2),当然最要不得的是 O(2^N) 级的增长,这种情况下可能有生之年你都看不到运算的结果了。
我们可以看看简单的一段代码来分析它的时间复杂度:
echo $a++, PHP_EOL; // O(1)
$n = 10; // 假设一个数量用于测试,实际这个 n 是未知的,如果面试题代码中真的出现了这种已知 n 的情况,那么这个算法就是 O(1)
for($i = 0;$i<$n;$i++){
echo $i, PHP_EOL;
}
// O(n)
for($i = 0;$i<$n;$i*=2){
echo $i, PHP_EOL;
}
// O(logN)
for($i = 0;$i<$n;$i++){
for($j = 0;$j<$n;$j++){
echo $i, $j, PHP_EOL;
}
}
// O(N^2)
从上面代码中可以看出,循环嵌套次数与 n 的增长有很大的关系,另外就是看在循环内部的操作也会影响到增长的情况。比如如果我们是这样一段代码:
$n = 10; // 假设一个数量,实际这个 n 是未知的
$m = 3; // 假设一个数量,实际这个 m 是未知的
for($i = 0;$i<$n;$i++){
for($j = 0;$j<$m;$j++){
echo $i, $j, PHP_EOL;
}
}
那么它的时间复杂度就不是 O(N^2) 而是,O(NM) ,因为我们这两层循环并不是都是对最大的 N 的操作,而是 N * M 的操作。但是,如果当 M 很大甚至等于 N 的时候,那么这个算法也就成为了 N^2 。
对于时间复杂度的分析其实是需要一些数学功底的,但是对于我这种半吊子出身的码农来说,把握住循环层次以及循环内的操作情况就可以大致地分析出一段算法的时间复杂度了。当然,对于某些大厂比较刁钻的面试题来说,还是需要用数学方法进行分解求得正确的时间复杂度。
另外,在一段算法或者说一个函数中,时间复杂度以最大的那个为准,同时,也要考虑最好和最差时间复杂度,因为基于数据规模有可能在数据量大的时候时间复杂度会越来越惨。这个时候我们就会以最差时间复杂度来作为这一段算法的最终时间复杂度。
关于时间复杂度的问题,可以参考各类算法书籍,当然最好是以大学教材及练习题为主,多做题就能掌握得更深入。
空间复杂度
相对时间复杂度来,空间复杂度在数据结构和算法中要关心的少一些,因为大部分情况下我们只借助一个第三方变量的话,这个空间复杂度就是 O(1) 。而如果需要借助一个数组或者链表来实现算法的话,这个算法的空间复杂度就是 O(n) 。
一般情况下我们不太会去过于的关注空间复杂度,因为大部分算法基本都会维持在 O(1) 或 O(n) 这个级别。当然,也就一些算法会出现占用非常大的空间复杂度的情况,这样分分钟就能撑爆你的内存。当在遇到这类算法的时候,我们会单独来说明空间复杂度的情况。
总结
第一篇文章都是以理论方面的东西为基础的,这也是学习数据结构与算法的实际情况,必须是理论与实际相结合的学习。让我们从此开始,迈向这个深不见底的超级大坑吧!!
参考资料:
《数据结构》第二版,严蔚敏
《数据结构》第二版,陈越
《数据结构高分笔记》2020版,天勤考研
===============
关注公众号:【硬核项目经理】获取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料
知乎、公众号、抖音、头条搜索【硬核项目经理】
B站ID:482780532
【PHP数据结构】在学数据结构和算法的时候我们究竟学的是啥?的更多相关文章
- 前端要不要学数据结构&算法
我们都知道前端开发工程师更多偏向 DOM 渲染和 DOM 交互操作,随之 Node 的推广前端工程师也可以完成服务端开发.对于服务端开发而言大家都觉得数据结构和算法是基础,非学不可.所以正在进行 No ...
- 数据结构C语言版 弗洛伊德算法实现
/* 数据结构C语言版 弗洛伊德算法 P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...
- 简学Python第二章__巧学数据结构文件操作
#cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...
- hdu 3336:Count the string(数据结构,串,KMP算法)
Count the string Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 每周一道数据结构(四)A*算法&博弈树α-β剪枝
A*算法/博弈树 前阵子考试学了A*算法.博弈树和回溯,自己真是愚蠢至极,根本没就搞明白这些,所以对于这些算法问道的话就不能说清楚,也记不住,所以才有了这篇笔记.在这里感谢面试我的那位工程师~~ A* ...
- 你真的懂redis的数据结构了吗?redis内部数据结构和外部数据结构揭秘
Redis有哪些数据结构? 字符串String.字典Hash.列表List.集合Set.有序集合SortedSet. 很多人面试时都遇到过这种场景吧? 其实除了上面的几种常见数据结构,还需要加上数据结 ...
- 一步步教你轻松学支持向量机SVM算法之案例篇2
一步步教你轻松学支持向量机SVM算法之案例篇2 (白宁超 2018年10月22日10:09:07) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...
- 一步步教你轻松学支持向量机SVM算法之理论篇1
一步步教你轻松学支持向量机SVM算法之理论篇1 (白宁超 2018年10月22日10:03:35) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...
- 一步步教你轻松学关联规则Apriori算法
一步步教你轻松学关联规则Apriori算法 (白宁超 2018年10月22日09:51:05) 摘要:先验算法(Apriori Algorithm)是关联规则学习的经典算法之一,常常应用在商业等诸多领 ...
随机推荐
- GraphQL API vs REST API
REST是构建API的一种流行方法,而且比GraphQL应用更广泛,让我们看看GraphQL和REST的区别. Rest是一个概念 REST是一个事实上的架构标准,但它实际上没有规范,有大量的非官方定 ...
- Ajax 局部刷新 异步提交
AJAX简介 局部刷新,异步提交. AJAX 不是新的编程语言,而是一种使用现有标准的新方法.它最大的有点就是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容. 浏览器朝后端发送请 ...
- 手机摄像头作为视频画面捕捉设备与OBS连接(有线)
手机有线连接OBS(以无他伴侣作为测试案例) 1.硬件设备 安卓手机1台.安卓手机对应的数据线.电脑2台(windows系统,1台做OBS与手机连接.1台做直播后台:配置等如果能达到要求也可以只使用一 ...
- APIO 2007 动物园 题解
链接题面 看清楚找到小数据范围,第一维表示遍历到的栅栏,第二维是五位状态 先预处理每个状态会使多少小朋友高兴 方程是 f[i][j]=max(f[(i&((1<<4)-1))&l ...
- 如何在github上传本地项目代码
首先你要在github上申请一个账号 网址:https://github.com/ 然后你要下载一个git工具 网址:https://gitforwindows.org/ 进入官网直接下载就行,下载完 ...
- SpringBoot五步配置Mybatis
第一步:Maven里面添加mybatis的引用jar包: <!--mybatis--> <dependency> <groupId>org.mybatis.spri ...
- C语言之----面向对象的方法实现链表的操作
1 /* 2 * 详细运行过程: 本程序实现的是对链表的简单的操作,即链表的增 删 改 查 销毁 初始化 3 * 运用面向对象的思想,实现一个类op,op中包括了所有的链表操作方法 4 * 其他的程序 ...
- PipedInputStream and PipedOutputStream example
必须要有PipedInputStream ,PipedOutputStream 在不同线程,不然死锁 Java.io.PipedOutputStream and java.io.PipedInputS ...
- mysql基础操作(二):简单查询DQL
-- 1.查询所有字段 select * from student; -- 2.查询指定的字段 select id from student; select id, name from student ...
- Ansible部署及配置介绍
原文转自:https://www.cnblogs.com/itzgr/p/10233932.html作者:木二 目录 一 Ansible的安装部署 1.1 PIP方式 1.2 YUM方式 二 Ansi ...