无论是在大学还是工作中,对于从事程序相关工作的人来说,数据结构与算法都是非常非常重要的,然而很多人意识不到这点。这是因为,我们当今的软件行业从事人员没有一个良好的职业素养,很多科班出身的人与培训机构的人都是以结果为目标,很少在乎代码质量,在开发过程中也更多的是复制粘贴,修修补补。
计算机里有四大不动产,之所以这么说是因为一旦掌握它们就会成为自己的永久性技能,它们分别是数据结构与算法、计算机操作系统、计算机网络、计算机组成原理。这四门课是所有计算机科学教学计划的基础,随着计算机应用领域的不断扩张,这些基础方法的影响也会不断扩大。
在上大二时,没有学好数据结构,于是想着重新学习一下,同时也写写自己的博客。本篇博客仅仅讲述一下数据结构的基本概念,之后会写一系列的有关数据结构的知识,最终我会将这些知识整理成自己的知识图谱。如有不足之处敬请指正,谢谢!
正文:
在用计算机解决实际问题时,我们需要将一个问题抽象成一个数学模型,然后设计一个试用于此模型的算法,再编出程序,进行测试和调整直到解决问题。
数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。这个怎么理解呢?
1. 在我们的用户登录信息数据表中有username和password,一个username对应一个password,这种一对一的关系,我们称之为线性结构。
2.在我们描述家族关系时,会先从最老的一辈开始分析,例如从爷爷开始分析,爷爷有三个儿子,每个儿子各自家庭里又有自己的孩子,一个爷爷对应三个儿子,四个子孙,这种一对多的关系,我们称之为树状结构。
3.在生活中,我们在看警匪片时,总会出现警察对着黑板,分析各个罪犯之间的关系,又或者我们在看全国高铁线路图时,发现每个大城市都被连成一个网状。这种多对多的关系图我们称之为图状结构或者网状结构。
4.其次,我们在初次学习高中数学或者高数时,首章都会提到一个概念“集合”,在数据结构中,这种结构我们不深究,知道就可以了。
上面所讲的四种结构,我们其实是在将一个个实际问题用对应的结构逻辑化,所以我们将这些结构成为逻辑结构。然而计算机如何识别这些结构呢?我们说计算机由五大部分组成,分别是运算器、控制器、存储器、输入设备、输出设备。我们所有的程序代码,文件内容都是放在存储器上面的,存储器是物理硬件。因此,我们有了逻辑结构,就应该考虑到这些结构到底如何在计算机中表示呢?
我们都知道计算机中表示信息的最小单位是二进制数的一位,叫做位(bit)。在计算机中,我们用一个由若干位组合形成的一个位串表示一个数据元素,通常称这个位串为元素或结点(注意不要写成节点,这两个意思完全不一样)。当数据元素由若干数据项组成时,位串中对应于各个数据项的子位串称为数据域。例如,在C语言中,学习的指针章节,一个链表结点,结点包含值域和指针域,这里的一个结点可以看做一个数据元素,其中的值域和指针域都是这个元素的数据域。
数据元素之间的关系在计算机中有两种不同的表示方法:顺序映像和非顺序映像,并由此得到两种不同的存储结构:顺序存储结构和链式存储结构。顺序映像是借助数据元素在存储器中的相对位置来表示数据之间的逻辑关系;非顺序映像是借助指针表示数据元素之间的逻辑关系。事实上,数据结构有以下四种常用的存储方法:
(1)顺序存储
该方法把逻辑上相邻的结点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现。
(2)链式存储
该方法不要求逻辑上相邻的结点在物理位置上也相邻,结点间的逻辑关系是由附加的指针字段表示的。由此得到的存储结构表示称为链式存储结构。
(3)索引存储
该方法在存储结点信息时建立除了建立存储结点信息外,还建立附加的索引表来标识结点的地址。索引项的一般形式为<关键字,地址>。关键字标识唯一一个结点,地址作为指向结点的指针。
(4)散列存储
该方法根据结点的关键字通过散列函数直接计算出该节点的存储地址。这种方法本质上是对顺序存储方法的扩展。
一个算法由控制结构(顺序,分支和循环3种)和原操作(指固有数据类型的操作)构成的,算法时间取决于两者的综合效果。同一个算法用不同的语言来实现,或者用不同的编译器进行编译时,或者在不同的计算机上运行时,效率均不相同。因此用绝对的时间衡量算法的效率是不合适的。所以只能依赖问题的规模,通常用整数量n来表示。
求解算法的时间复杂度,其具体步骤是:
⑴ 找出算法中的基本语句;
算法中执行次数最多的那条语句就是基本语句,通常是最内层循环的循环体。
⑵ 计算基本语句的执行次数的数量级;
只需计算基本语句执行次数的数量级,这就意味着只要保证基本语句执行次数的函数中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数。这样能够简化算法分析,并且使注意力集中在最重要的一点上:增长率。
⑶ 用大O记号表示算法的时间性能。
将基本语句执行次数的数量级放入大O记号中。
如果算法中包含嵌套的循环,则基本语句通常是最内层的循环体,如果算法中包含并列的循环,则将并列循环的时间复杂度相加。
(1)一个简单的例子解释时间复杂度
计算Σ(N i=1) i^3 的一个简单的程序片段
int
Sum( int N)
{
int i,PartialSum;
/*1*/ PartialSum=0;
/*2*/ for( i =1;i<=N;i++)
/*3*/ PartialSum += i*i*i;
/*4*/ return PartialSum;
}
对这个程序进行分析,第一行和第三行是我们要找的基本语句,第一行很明显占一个时间单元,只执行一次。第三行每执行一次占用四个时间单元(两次乘法,一次加法和一次赋值),而执行N次共需要4N个时间单元。第二行的循环语句初始值i=1;占一个时间单元,判断体占用N+1个时间单位,自增运算占用N个时间单位。我们忽略调用函数和返回值的开销,得到总量是6N+4,最终去掉系数和常数,时间复杂度就是O(N)。
然而如果每次分析程序都要像上面一步一步的分析,这样是不可取的。上面程序,第三行,分析它占几个时间单元是不可取的,显然每次执行它的时间复杂度为O(1)。可以解释为一般来说,只要算法中不存在循环语句,其时间复杂度就是O(1)。所以第一行我们也直接可以忽略不计了。
(2)时间复杂度的一般法则
法则一——for循环
一次for循环的运行时间至多是该for循环内语句的运行时间乘以迭代的次数
法则二——嵌套for循环
从里向外分析这些循环,在一组嵌套循环内部的一条语句总的运行时间为该语句的运行时间乘以该组所有的for循环的大小的乘积
例子:下面片段时间复杂度为O(N^2)
for(i=0;i for(j=0;j k++; O(1) 这条基本语句,其时间复杂度就是O(1) 法则三——顺序语句 将各个句子的运行时间求和即可(这意味着,其中最大值就是所得的运行时间) 例子:下面程序中,一次循环的时间复杂度为O(N),嵌套循环的时间复杂度为O(N^2),所以总的时间复杂度为O(N^2) for(i=0;i A[i] = 0; O(1) for(i=0;i for(j=0;j A[i] += A[j] + i + j;O(1) 特别提示: T1(N)= O(f(N))且T2(N)=O(g(N)),那么 (a)T1(N)+T2(N)= max (O(f(N)),O(g(N))) (b)T1(N)*T2(N)=O(f(N)*g(N)) 法则四——if/else语句 if(Condition) s1 else s2 一个if/else语句中的运行时间,从不超过判断开始,再加上s1和s2中运行时间长者,的总的运行时间。 分析的策略都是从内部向外部展开,若果有函数调用,那么这些调用要首先分析。 【硬盘存储数据方式】 硬盘是在硬质盘片(一般是铝合金,以前 IBM 也尝试过使用玻璃)上涂敷薄薄的一层铁磁性材料。硬盘储存数据的原理和盒式磁带类似,只不过盒式磁带上存储是模拟格式的音乐,而硬盘上存储的是数字格式的数据。写入时,磁头线圈上加电,在周围产生磁场,磁化其下的磁性材料;电流的方向不同,所以磁场的方向也不同,可以表示 0 和 1 的区别。读取时,磁头线圈切割磁场线产生感应电流,磁性材料的磁场方向不同,所以产生的感应电流方向也不同。 现在的硬盘,无论是IDE还是SCSI,采用的都是"温彻思特“技术,都有以下特点: 1.磁头,盘片及运动机构密封。 2.固定并高速旋转的镀磁盘片表面平整光滑。 3.磁头沿盘片径向移动。 4.磁头对盘片接触式启停,但工作时呈飞行状态不与盘片直接接触。 盘片:硬盘盘片是将磁粉附着在铝合金(新材料也有用玻璃)圆盘片的表面上.这些磁粉被划分成称为磁道的若干个同心圆,在每个同心圆的磁道上就好像有无数的任意排列的小磁铁,它们分别代表着0和1的状态。当这些小磁铁受到来自磁头的磁力影响时,其排列的方向会随之改变。利用磁头的磁力控制指定的一些小磁铁方向,使每个小磁铁都可以用来储存信息。 盘体:硬盘的盘体由多个盘片组成,这些盘片重叠在一起放在一个密封的盒中,它们在主轴电机的带动下以很高的速度旋转,其每分钟转速达3600,4500,5400,7200甚至以上。 磁头:硬盘的磁头用来读取或者修改盘片上磁性物质的状态,一般说来,每一个磁面都会有一个磁头,从最上面开始,从0开始编号。磁头在停止工作时,与磁盘是接触的,但是在工作时呈飞行状态。磁头采取在盘片的着陆区接触式启停的方式,着陆区不存放任何数据,磁头在此区域启停,不存在损伤任何数据的问题。读取数据时,盘片高速旋转,由于对磁头运动采取了精巧的空气动力学设计,此时磁头处于离盘面数据区0.2---0.5微米高度的”飞行状态“。既不与盘面接触造成磨损,又能可靠的读取数据。 不论是什么计算机文件,歌曲、视频、图片、文档等等,都是以一个二进制的序列存在的,也就是很多个"10010001110011......"这样的东西,硬盘上的存储的文件实际上就是存储着这些0和1的序列。硬盘的磁头能够按照指令读取相应位置的信号,并且能够改变指定位置的磁场方向,这就是数据的读和写。5.数据在硬盘的存储
电机:硬盘内的电机都为无刷电机,在高速轴承支撑下机械磨损很小,可以长时间连续工作。高速旋转的盘体产生了明显的陀螺效应,所以工作中的硬盘不宜运动,否则将加重轴承的工作负荷。硬盘磁头的寻道饲服电机多采用音圈式旋转或者直线运动步进电机,在饲服跟踪的调节下精确地跟踪盘片的磁道,所以在硬盘工作时不要有冲击碰撞,搬动时要小心轻放。