有不对的地方还劳烦大家指正,大家共同学习共同进步!
目录
数据结构概述
数据:
数据是能被计算机处理的各种符号的集合
-
是信息的载体
-
是对客观事物符号化的表示
-
能够被计算机识别、存储和加工
数据包括:数值型数据,非数值型数据
数据元素
数据元素是数据的基本单位,在计算机中通常作为一个整体,也简称为元素,或称为记录、结点或顶点。
如图上所示,每一行代表一个数据元素
数据项
数据项是数据不可分割的最小单位
如图上所示,每一个小圆圈都是一个数据项,所以数据项是数据不可分割的最小单位
数据>数据元素>数据项
学生表中包含张三的信息(数据元素)张三的信息中又可以拆分出其他的单独的信息比如张三的姓名(数据项)
数据对象
数据对象是由性质相同的数据元素所构成的一个数据集合。与数据的关系:数据对象是数据的子集。
数据结构
数据元素相互之间的关系,就是数据结构。
数据结构:数据结构是带结构的 数据元素的集合。
数据结构包括:
-
逻辑结构,数据与数据之间的关系
-
存储结构:数据元素及其关系在内存中的表示(又称为映像),也被称为物理结构。
-
运算和实现:即对数据元素可以施加的操作,以及这些操作在相应的存储结构上的实现。
逻辑结构与存储结构的关系
-
存储结构是逻辑关系的映象与元素本身的映象。
-
逻辑结构是数据结构的抽象,存储结构是数据结构的实现。
-
两者综合起来建立了数据元素之间的结构关系。
逻辑结构
逻辑结构的种类
1.线性结构与非线性结构
线性结构:
有且仅有一个开始和一个终端结点,并且所有结点都最多只有一个直接前趋和一个直接后继。
例如:线性表,栈和队列,串
非线性结构:
一个结点可能有多个直接前驱和直接后继
例如:树,图
2.基本的四种基本结构
基本的四种基本结构分别是:集合结构,线性结构,树形结构,图形结构
集合结构
线性结构
线性结构中数据元素与数据元素之间存在一对一的关系
树形结构
树形结构之间存在一对多的关系,由图所示除头结点外所有的结点都有一个直接前驱,除尾结点外所有的结点都有一个或者多个直接后继
图形结构
图形结构数据元素之间存在多对多的任意关系。
存储结构
顺序存储结构
顺序存储结构是将数据元素存储在一个连续的内存单元中去。在c语言以及java中使用数组来实现。
优点:查找速度快
缺点: 插入和删除效率相对较低
链式存储结构
链式存储结构是将数据元素存储在任意的内存单元中去,在c语言中用指针来进行连接。
由图所示数据元素是存储在内存中任意一个数据单元中,并由地址将每个数据元素之间连接起来,
图中为单链表。
索引存储结构
索引存储结构是降数据元素存储起来的同时建立一张索引表,以便于快速找到相对应的数据元素
散列存储结构
散列存储结构是将数据元素经过一系列的计算得出数据元素应该存储的位置
类型和抽象数据类型
数据类型
例如:c语言中的int类型、指针等
一些最基本的数据结构高级语言提供的数据类型就可以实现了,例如:数组,字符串,等;
高级语言所定义的数据类型的作用:高级语言所定义的数据类型其实明显的或者隐含的规定了一个变量在程序运算期间所有可能的取值范围,例如int类型的取值范围是-32768——32767,在我们编程的过程中我们可以直接用int类型来声明一个变量,并且这个变量所占用的空间就是数据类型所规定的范围。不再需要再告诉计算机这个变量应该如何存储,应该占用多大的空间 。1.约束了常量或者变量的取值范围。2.约束了常量或者变量的操作(数值类型只能做数值类型的操作,字符类型只能做字符类型的操作)。
数据类型=值的集合+值集合上的一些操作
抽象数据类型
抽象:
抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。具体地说,抽象就是人们在实践的基础上,对于丰富的感性材料通过去粗取精、去伪存真、由此及彼、由表及里的加工制作,形成概念、判断、推理等思维形式,以反映事物的本质和规律的方法。(百度百科)
其实我们生活中有很多抽象的例子,比如你在路边看见了一只狗,你会跟你的好朋友说哇这只狗好漂亮啊!而不是这只白色的爪子是黑色的母的小的耳朵大的鼻子短的长得像海盗的狗好漂亮啊。我们人类会自动的将事物抽象出来,如同上图的四个圆,我们会自动的抽象出来这是四个圆形而忽略他们的颜色大小是否被填充颜色等信息。
抽象数据类型=数据的逻辑结构+抽象运算
算法和算法分析
算法的定义
对特定问题的求解方法或者描述,是指令的有限序列,是解决问题的方法和步骤。
算法的描述
-
自然语言(汉语,中文等)
-
流程图(传统流程图,NS流程图)
-
伪代码:类语言:类C语言
算法与程序
算法
算法是解决问题的一种方法或一个过程考虑如何将输入转换成输出,一个问题可以有多种算法。
算法的特性
-
有穷性(有穷个步骤,每一步都在又穷的时间内完成)
-
确定性(没有二义性)
-
可行性(是可以执行的)
-
输入(零个或者多个输入)
-
输出(一个或者多个输出)
算法设计的要求
-
正确性(一般的我们会对程序进行精心选择、典型、苛刻且带有刁难性的几组输入能够得出满足的要求的结果);
-
可读性(易于理解,利于阅读)
-
健壮性(当输入非法数据时,算法会做出恰当的反应或者处理)
-
高效性(花费尽量小的空间和时间)
算法的分析
一个算法除了要满足以上几点外还要考虑效率。分别是时间复杂度和空间复杂度
算法时间效率的度量
-
事后统计
将算法实现,测算其时间和空间开销
缺陷:编写程序将算法实现要花费较多的时间和精力,所得结果依赖于计算机的软硬件等环境因素,掩盖算法本身的优劣。
-
事前分析
对算法所消耗资源的一种估算方法。
算法的运行时间=一个简单操作锁续的时间*简单的操作次数
但是每条语句的执行时间和很多因素相关联例如:机器的性能、速度、使用的编程语言不一样等都会对语句的运行时间所产生影响
所以我们只需要关注这条语句锁运行的频度就可以了例如:
for(int i=1;i<=n;i++){ //执行n+1次 for(int j=1;j<=n;j++){ //执行n(n+1)次 c[i][j]=0; //执行n*n次 for(int k=0;k<n;k++){ //执行n*n*(n+1)次 c[i][j]=c[i][j]+a[i][k]+b[k][i] //执行n*n*n次 } } }
T(n)=2n^3+3n^2+2n+1
但是我们每一层都要数代码太麻烦了,所以我们可以直接比较数量级例如:T1(n)=10n^2,T2(n)=5n^3我们来比较数量级所以T1(n)要优于T2(n)
若有某个辅助函数f(n),使得当n趋近于无穷大时,1(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n))称O(f(n))为算法的渐进时间复杂度(O是数量级的符号),简称时间复杂度。
所以上面程序的复杂度为T(n)=O(n^3)
一般情况下我们只考虑基本操作的执行次数
算法时间复杂度:
-
最坏时间复杂度(指在最坏情况下,算法的时间复杂度)
-
平均时间复杂度(指在所有可能输入实例在等概率出现的情况下,算法的期望运行时间。)
-
最好时间复杂度(指在最好情况下,算法的时间复杂度)。
一般总是考虑在最坏情况下的时间复杂度,以保证算法的运行时间不会比它更长。
对于复杂算法的处理:
对于求复杂算法的时间复杂度往往比较麻烦,可以将它分成几个容易估算的部分,然后利用O的加法法则和乘法法则计算时间复杂度。
加法规则:T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n)))
最后一步可以理解为在拆分出来的算法中找一个时间复杂度高的为结果
乘法规则:T(n) = T1(n) x T2(n) = 0(f(n)) x 0(g()) = 0(f(n) *g(n))
算法复杂度的比较:
当n去的越大,指数时间算法和多项式时间算法在锁需要时间上非常悬殊。
在我们程序设计时尽量使用时间复杂度较低的算法。
渐进空间复杂度
记作:S(n)=O(f(n))
算法要占据的空间:
-
算法本身要占据的空间,输入/输出,指令,常数,变量等
-
算法要使用发辅助空间
辅助空间:
程序
程序是用某种设计语言对算法的具体实现。
程序=数据结构+算法