与你相识
博主介绍:
– <远马神工>不是一个人的名字,它是一个团队,目前纵深学习Go语言,其它语言也有所涉猎,“远马”有“源码”的谐音,甚至和“猿”也沾点关系,我们希望能通过这个平台认识其它人,和其它人一起讨论我们所热爱的东西,在这个账号上会转发团队中投稿过来的技术文章,也欢迎您和我们交流。
引言
介绍了第一章的内容,绪论主要是解释一个问题——这一学期的数据结构在学什么?
本篇文章转发自团队成员飞飞的csdn:文章链接
基本的思路是:
数据结构是计算机在长久的发展中,对解决一些生活中特定问题而总结出来了一些数据规则,使用这些数据规则可以让我们在某些问题的处理中变得最优。
但是需要说明的是数据结构和具体的代码是两码事,只是他们的关系比较密切,经常在一起用而已,就好像我们讨论汉字的形体结构
(上下结构,左右结构)不需要关心具体的汉字一样。
接下来我就跟你聊聊,学习数据结构到底在学什么?
由于要走计算机这一条路,所以要了解计算机的各个环节,才能把计算机使用的更顺手,让计算机不走弯路
,
比如说我们都有在计算机中搜索文件的经历,在我的电脑中搜索文件往往需要很长的时间,但是我就用过一个叫everything的工具,它可以实现在一秒内搜索你想要的文件,而这,就需要你对数据结构有深刻的理解,也是你会更有价值的地方,不过了解计算机的路相当漫长,数据结构只是其中一环而已。
如果你不学习数据结构,当然也可以写出高效的程序(计算机最开始本来就是一片空白),但不是人人都是天才,能凭空想出这些东西,所以我们才需要学习数据结构,让整个行业可以站在巨人的肩膀上解决问题。
就像我们学习数学,从一开始就是站在数学的高楼上添砖加瓦,而不是自己凭空构建出一个数学体系。
又好比你要学习做饭,有成型的菜谱可以让你做出好吃的东西,为什么不用呢?有成套的汉字可以让我们去使用,为什么不用呢?
所有能被计算机识别、存储和处理的符号的集合(包括数字,字符,声音,图像等信息)
计算机的底层都是2进制存储,图片,压缩包,软件,声音,图像,视频都是二进制存储,因为计算机并不能像你一样很自然的知道识别各种事物,它只是按照某种规则去解析数据(我们会规定图片,压缩包等的数据格式)而已,那么这些,都叫数据,它们一起组成了一个集合。
数据元素是数据的一个个体,具有完整的实际意义(又称元素,顶点,记录),是数据的一个基本单位,比如一张图片,一个压缩包,它是一个整体,压缩包内部还有很多的功能可以细分。或者是一个逻辑上的基本单位,比如一个班级的花名册,一个地区的道路情况。
构成数据元素的项目。是具有独立含义的最小标识单位(又称字段,域,属性等)。数据项是数据的最小单位。
和前两个概念的关系是:数据>数据元素>数据项
例子:班级通讯录>个人记录>姓名、年龄……
具有相同特征的数据元素的集合称为数据对象。 如:字母数据对象,学生数据对象等
能被计算机所表示的事物,基本上可以被拆解为两部分,一部分是属性(如姓名,颜色,身高,体重,毛色,习性),一部分是动作(如抓,说,咬,砍,走,睡)。
那么假如说我们要表示一种生物,我们定义它有名字和体重的属性,以及睡觉的动作。
那么我们通过这个属性和动作,具体的给个值,比如给它起个名字,就叫大宝,它重10斤,那么它的属性就是:名字=大宝,体重=10,它的行为是每天都在睡觉,这就是一个具体的生物了。
同样的,我们还可以有二宝,重8斤,就有:名字=二宝,体重=8,行为是每天睡觉…… 之后你可以定义更多的,三宝,四宝……。
那么大宝,二宝,三宝他们都有着相同的属性和动作,只是具体的值不同,他们就是具有相同特征的,他们的集合就被称为这种生物的数据对象。
相互之间存在一种或多种特定关系的数据元素的集合。
它主要包括逻辑结构,物理结构(即存储结构) 和 数据运算这三个方面,我感觉它的解释相当的抽象,这个我们可以之后再理解,学习《数据结构》,学的就是这个东西,这三个方面也是我们整门课的核心内容。
数据的逻辑结构是脱离于计算机,就好像讨论汉字结构可以脱离汉字一样。根据数据元素之间逻辑关系的不同,可以细分为4类:集合结构,线性结构(一对一),树结构(一对多),图结构(多对多)
(其中集合结构我们这门课讨论不多。)
数据元素及其关系在计算机存储器内的表示,即数据的存储表示,它依赖计算机的硬件
根据不同的存储结构可以分为顺序,链式,索引,散列四类,下面这些简单有个印象就像,记不住,不理解也没关系,确实没那么容易懂。
顺序存储是指元素是按照逻辑次序,连续存放的
链式存储不是连续存放的,它的每一个结点会存储下一个结点的地址,这样可以通过第一个结点找到第二个结点,通过第二个结点找到第三个节点……。
索引结构会在一个节点处建立索引,然后通过这个索引来找元素的位置。
散列结构可以根据关键字的值确定存储的地址,但是可能会出现关键字转化出来的散列值冲突的情况,所以需要设计一个好的散列函数。
这算是我们要遵守的一些原则性的东西,其实我经常看过之后就会忘掉,因为平常在生活中,没有人会跟我掰扯写的某个算法是否严格遵守算法的特性等等。
但是也都是大白话,并不是很难理解。
下图是离散数学图那一部分章节的Prim算法,按照下面的这些步骤一直重复,就能从一个加权连通图中得到最小生成树。
其实就是定义流水线,原料进来,经过中间机器的加个,最终出结果。 如果你的算法无穷的话,原料进来,经过机器加工,就一直加工,加工,加工,那肯定是不行的。
语句频度是计算出程序的运行次数,下面这个从i运行到n,运行了n词,所以语句频度就是n
但是语句频度有的时候会比较复杂,如下,因为我的数学功底比较差,另外它没有那么重要,我也没往下钻,所以我就理解到这了。
相比于计算语句频度来讲,当我们面对一个算法处理海量的数据的时候,我们只需要用时间复杂度稍微估算一下即可,我们的眼光是无穷的延伸,是趋势。
另外如果它的语句频度=2n2 + 2n,则时间复杂度为O(n2) ,也就是说要忽略掉系数和常数项,我们只关注最重要的那个。
还是拿上面这两张图来说,第一张图for循环n次,也就是n有多大,这个循环就执行多少次,那么我们就认为它的时间复杂度是O(n)的。
下面这张图在很多地方都能找到,横轴是数据量,纵轴是时间,可以看到时间复杂度分了很多条线,不同条线面对不同的数据量它的处理速度是不同的,O(1)最快,基本上不怎么耗费时间,
那么我们衡量算法的时间复杂度,实际上就是看看自己的算法是属于哪根线上的,至于为什么要忽略系数呢? 不管前面的系数多大,在无穷大的数据量面前O(n),或者O(100n),或者O(10000n),其实差不多,它始终还在这条线上,不会超过根号n的速度,这就是量变和质变的差距。
而我们的追求,就是怎么能让一个O(n2)的算法变成O(n),怎么把O(n)的算法变成O(logn)的时间复杂度。
空间复杂度现在我们并不怎么关心了,因为现在的硬盘太大了,我们根本用不完。
通过两个例子简单的说一下我的理解吧,在一般情况下,我们只需要分析算法所需的辅助空间就可以了,不去考虑程序本身所占空间和输入数据所占空间。
比如我们要算数组逆序,下面的算法1,一个数组a,和一个变量t都是这个算法所必须要有的,不然算法都走不下去,我们也没使用辅助空间,所以空间复杂度为常数——O(1)。
而算法2是使用了另一个数组来倒着把第一个数组存储起来以实现数组逆序,使用了一个辅助空间b,b的长度随着a的长度而改变,a的长度是n,b的长度也是n,所以相当于多开辟了n个空间——O(n)。
我们目前大概知道了《数据结构》要干什么,了解了一些术语,了解了算法的五个特性
,也知道了数据的逻辑结构和物理结构
,以及如何简单的看一个算法有多快,对算法的运行时间
有了个基本的概念。
你很可能是一脸懵逼的。绪论的目的,是让你知道接下来整本书要告诉你什么,但是你问问自己,好像还不知道。没关系,我来尝试告诉你一下。
我们的二 ~ 七章介绍了几种具体的数据结构,后面的几章介绍了数据结构的具体使用。第二章是线性表,第三章是栈和队列,第四章是串,第五章是数组和广义表,第六章是树,第七章是图。
我们知道我们所涉及的逻辑结构有集合结构,线性结构,树结构,图结构,物理结构有顺序,链式,索引,散列。(其中逻辑结构的集合结构我们涉及不多)。
那么他们之间互相交叉,就有了我们的这些章节,第一章讲了线性表和链表,其实就是:
线性结构 + 顺序存储 = 线性表
线性结构 + 链式存储 = 链表
第三章栈和队列是加了限制条件的线性表(第二章),是一种特殊的线性表,比如我们规定添加数据必须得在头部添加,查看数据必须得在尾部查看,这就是栈
。
我们又规定添加数据必须在头部添加,查看数据也必须在头部,这就是队列
。
第四章串也是一样的道理,和线性表非常类似,和线性表的区别仅在于串的数据对象为字符集
,另外因为元素的不同,操作也有所区别,当然也分顺序存储和链式存储。
到了第六章就到了树的章节,看到一个数据结构,就要问问自己能不能顺序存储和链式存储,树可以顺序存储,但是一般我们使用链式存储。
现在,我们应该已经知道了数据的逻辑结构和物理结构,并明白这些章节就是它们交叉所产生的一些具体的数据结构,当我们根据数据结构写出一些算法(具体实现
)之后,我们需要评估我们的算法有多快,就需要用到时间复杂度
。
简单回顾一下吧! (更全的习题因为篇幅原因没能放出来,欢迎私信获取噢~)
答案:
欢迎评论区讨论,或指出问题。 如果觉得写的不错,欢迎点赞,转发,收藏。