【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)是关联规则学习的经典算法之一,常常应用在商业等诸多领 ...
随机推荐
- 手工设置Eclipse文本编辑器的配色
Eclipse中不同的文件都有自己专门的编辑器配色设置,下面分别说明. 文本编辑器的背景色: Window->Preferences-> General->Editors->T ...
- git 切换分支 本地代码失踪找回办法
解决方案: https://blog.csdn.net/hupoling/article/details/79017382 主要步骤: git reflog 然后找到之前commit的分支 git c ...
- S3C2440—11.und异常
文章目录 1 未定义指令 2 中断向量表 3 设置一个未定义指令 4 调用C函数 5 UND异常处理程序 6 汇编源码 7 注意点 lr与pc 保存现场 中断向量表的跳转 程序执行顺序 问题 1 未定 ...
- noip22
T1 考试的时候打的特殊性质分,然而暴力竟然写假了. 正解: 显然是个贪心,要最大化 \(a_{\min}\times b_{\min}\),肯定是要删掉若干个 \(a\) 最小,\(b\) 最小的矩 ...
- 题解 w
传送门 一直觉得有点后效性什么的,也不知道怎么写 这题什么时候再康一遍,第一次见这个样子的树形DP,是个树上带不定权边的DP(??? 这里能树形DP的原因好像是在这里所有子节点的状态都能表示出来 还有 ...
- java集成网站微信,微博,qq登录
微信 WechatConfig.java package com.meeno.chemical.common.sdk.wechat.config; import org.springframework ...
- MySQL——分表,分库操作
说明 大数据量并且访问频繁的表,将其分为若干个表.如果不分的话,进行一次查询就会将表锁住,导致不能进行其他操作,故分表.表分割垂直分割应用场景:热数据放一个表里,冷数据放一个表里.冷数据使用MyIsa ...
- IO异常--缓冲流--转换流--序列化流( IO流2 )
1.IO异常的处理 JDK7前处理:使用try...catch...finally 代码块,处理异常部分 // 声明变量 FileWriter fw = null; try { //创建流对象 fw ...
- Mooc中国大学Python学习笔记--数字类型及操作
整数类型 只需知道整数无限制,pow(),4进制表示形式 与数学中整数的概念一致 --可正可负,没有取值范限制 --pow(x,y)函数:计算x^y,想算多大算多大 -十进制:10 -二进制,以0b或 ...
- SpringCloud 商品架构例子(一)
架构演进和分布式系统基础知识 1.传统架构演进到分布式架构 简介:讲解单机应用和分布式应用架构演进基础知识 高可用 LVS+keepalive 单体应用: 集群: 微服务架构: 1.单体应用: 开发速 ...