一.栈结构
1.意义:栈是一种特殊的数据结构,在中断处理特别是重要数据的现场保护有着重要意义。
2.栈结构其实就是一种线性结构,包括两类:
- 顺序栈结构:一组连续的内存单元依次保存栈中的数据,比如数组,0号元素为栈底,定义变量top为栈顶。
- 链式栈结构:使用链表保存数据,首部为栈顶,尾部为栈底。
3.从数据运算的角度来看,栈的操作操作栈顶,所以栈结构是按“先进先出(LIFO)”的原则处理结点数据的。
4.栈的基本操作:
- 入栈:将数据保存到栈顶的操作。入栈前先修改栈顶引用,使其向上移动一个元素,然后将数据保存到栈顶引用所指的位置。
- 出栈:将栈顶数据弹出的操作。修改栈顶引用使其指向栈中下一个元素。
5.示例代码见Github:https://github.com/flakkaqi/DataStructure_and_Algorithms.git
二.队列结构
1.对列结构也是一种线性结构,包括两类:
- 顺序队列结构:使用一组地址连续的内存单元保存队列中的数据
- 链式队列结构:使用链表形式保存队列中个元素的值
2.典型的对列结构允许对两端进行操作,但一端只能进行删除(队头),另一端只能进行插入(队尾)
3.空队列:即队列中没有元素
4.从运算角度分析,队列的结构按照“先进先出(FIFO)”的原则处理结点的数据。
5.队列的操作:
- 入队列:将一个元素添加到队尾(排队)
- 出队列:将对头的元素取出,同时删除该元素,使后一个元素成为对头。
6.示例代码见Github:https://github.com/flakkaqi/DataStructure_and_Algorithms.git
三.树结构
1.什么是树结构:树结构是一种描述非线性层次关系的数据结构。树是n个数据结点的集合,在该集合中包含一个根节点,根节点之下包分布着很多互不交叉的子集合,这些子集合也就是根结点的子树。
2.树结构的特征:
- 在一个树结构中,有且仅有一个结点没有直接前驱,这个结点就是树的根节点。
- 除根节点外每个结点都有且仅有一个直接前驱。
- 每个结点可以有任意多个直接后继。
3.树具有一种层次结构的性质,从数学角度来看,树具有一种递归的特性。在树的每个结点及其之后的所有结点构成一个子树,这个子树也包括根节点。
4.树的基本概念
- 父节点和子节点:直接的前驱结点称为父节点,直接的后继结点称为子节点
- 兄弟结点:具有同一个父结点的子节点
- 结点的度:一个结点所包含子树的数量
- 树的度:该树中所有结点中最大的度
- 叶结点:树中度为0的结点称为叶结点或者终端结点
- 分支结点:树中度不为0的结点称为分支结点或者非终端结点
- 结点的层数:结点的层数从树根开始算起,每个结点都处在一定的层次上
- 树的深度:树中结点的最大层数
- 有序树:若树中各结点的子树(兄弟结点)是按一定的次序从左到右安排的,称为有序树。
- 无序树:若树中各结点的子树(兄弟结点)不是按一定的次序从左到右安排的,称为无序树。
- 森林:n(n>0)棵互不相交的树的集合
5.树结构
右图为一个基本的树结构。其中A为根节点。结点A有3个子结点,因此,结点A的度为3.同理,结点E有两棵子树,结点E的度就为2.所有结点中,结点A的度为3最大,所以整棵树的度为3.结点E是结点K和结点L的父结点,结点K和结点L是结点E的子节点,结点K和结点L之间是兄弟结点。在这个树中,结点G、H、K、J、N、O、P和Q都是叶结点。其余都是分支结点,整棵树的深度为4。除去根节点A,留下的子树就是一个森林。
6.因为树结构不是不是一种线性结构,所以很难用数学式子表示,常采用层次括号法。规则
- 根节点放入一对圆括号中;
- 根节点的子树从左到右的顺序放入括号中;
- 对子树做上述同理的操作
- 右图的括号法表示为:(A(D((I(N,(M(Q,P)))),H)),(C(G,(F(J)))),(B(E((L(O)),K))))
四.二叉树
1.概述:
- 在树结构中,二叉树是最简单的一种形式,而且任意树都可以转为对应的二叉树,因此二叉树是所有树的基础。
2.什么是二叉树:
- 二叉树是树的一种特殊形式,其中n个结点的集合,每个结点最多只能有两个子结点。二叉树的子树任然是二叉树,结点上的两个子树分别称为左子树和右子树,因为子树有左右之分,所以二叉树是有序树。
- 二叉树最大度为2 ,有左右子树的区分
3.二叉树的分类:
- 满二叉树:除最 下一层叶子结点外,每层结点都有两个子节点。
- 完全二叉树:除二叉树最后一层外,其他各层的结点数都达到最大个数,而且最后一层叶子结点按照从左到右的顺序连续存在,只缺最后一层若干结点。
4.完全二叉树的性质:
完全二叉树中,如果树中包含n个结点,假设这些结点按照顺序方式存储,那么对于任意一个结点m来说,具有如下性质:
- 如果m != 1,则结点m的父结点编号为m/2;
- 如果2*m n ,则结点m的右子树根节点的编号为2*m;若2*m > n,则无左子树,进一步也就没有右子树;
- 如果2*m+1 n,则结点m的右子树根结点编号为2*m+1;若2*m+1>n,则无右子树。
- 深度为[log2n]+1
5.树结构的存储分为:
- 1.二叉树的顺序存储结构:
1.1 树结构的顺序存储一般也采用以为结构数组来表示,关键是定义合适的次序来存放各个层次的数据。
1.2 每个结点的数据为字符类型,如果安照顺序存储,我们可以按层存储。即先保存根节点,然后从左到右一次存储下一层结点的数据,......直到所有的结点数据完全存储。如图2-18所示的这种存储形式。
1.3 位置的推算:位置的推算可以根据前面完全二叉树的性质进行推算
- 对于结点D,其位于数组的第4个位置,则其父结点的编号为4/2=2,也就是B结点;
- 结点D左子结点的编号为2*4=8,也就是结点H;
- 结点D右子节点的编号为2*4+1=9,也就是结点I。
对于一个非完全二叉树的存储要稍微复杂一些,为了任然可以使用上述方法,我们通常将一个非完全二叉树用空数据结点填充为一个完全二叉树。但这种方法有一个很大的缺点,浪费存储空间。所以一般顺序存储只适用于完全二叉树的存储。
- 2.二叉树的链式存储结构:
2.1 与线性结构的链式存储类似,二叉树的链式存储结构包含结点元素以及分别指向左子树和右子树的引用。
2.2 有时为了后续计算的方便也会保存一个父节点的引用。
6.二叉树的遍历
- 先序遍历(DLR,先根次序遍历):中左右
- 中序遍历(LDR,中根次序遍历):左中右
- 后序遍历(LRD,后根次序遍历):左右中
- 总体观察就是中的位置发生了变化
- 好处:方便利用递归的思想实现遍历
7.实例代码见Github:https://github.com/flakkaqi/DataStructure_and_Algorithms.git
五.图结构
1.概述:
- 图结构是一种非线性数据结构,图结构的组织形式要比树更为复杂。
2.什么是图结构:
- 每个元素之间可以任意关联,就构成了图结构,正是这种任意关联性,导致了图结构中数据关系的复杂性。研究图结构的一个专门工具就是图论。
3.一个典型的图结构包含两部分:
- 顶点(Vertex):图中的数据元素
- 边(Edge):图中连接这些顶点的线
所有的顶点构成一个顶点集合,所有的边构成一个边集合,一个完整的图结构就是由顶点集合和边集合构成的,图结构一般在数学上记为一下形式:
G=(V,E)
或者
G=(V(G),E(G))
其中 V(G)表示图结构中所有顶点的集合,顶点可以用不同的数字和字母表示。E(G)是图中所有边的集合,每条边由所连接的连个顶点表示。
注意:V(G)必须为非空,E(G)可以为空
eg:
V(G)={V1,V2,V3,V4,V5,V6}
E(G)={(V1,V2),(V2,V3),(V5,V6),(V4,V5)}
4.图的基本概念
- 无向图: 如果一个图结构中所有的边都没有方向性,即为无向图。表示边的时候两个顶点无顺序要求
- 有向图:如果一个图结构中,边是有方向的,即为有向图。表示边的时候两个顶点就有顺序要求。
- 顶点的度:连接顶点的边的数量称为顶点的度
- 无向图中:就是连接该点的边条数,记为D(V)
- 有向图中:根据连接顶点V的边的方向性分为入度和出度
- 入度:指向顶点V的边的数量,记为ID(V)
- 出度:从顶点V射出的边的数量,记为OD(V)
- 总度: D(V)=ID(V)+OD(V)
4. 邻接顶点: 图结构中一条边的两个顶点.
- 无向图中: 两个相邻的顶点互为邻接顶点,可以有多个邻接顶点
- 有向图中:根据连接顶点V的方向性,两个顶点分别成为起始顶点(起点) 和 结束顶点(终点)
- 入边邻接顶点: 连接该点的边的起始顶点
- 出边邻接顶点: 连接该点的边的结束顶点
5.无向完全图:
- 在一个无向图中每个顶点之间都存在一个边。对于一个包含N个顶点的无向完全图,总无向边总数为N(N-1)/2。
6.有向完全图:
- 如果在一个有向图中,每两个顶点之间都存在方向相反的两条边,即为有向完全图。对于一个包含N个顶点的有向完全图,总边数为N(N-1)
7.子图:
- 子图的概念类似于子集合,由于一个完整的图结构包括顶点和边,因此一个子图的顶点和边都应该是另一个图结构的子集合。
- 只有顶点集合是子集的和只有边集合是子集的,都不是子图。
8.路径:
- 路径就是图结构中两点之间的连线,路径上边的条数叫做路径长度。两点之间的路径不止一条,所以路径长度也不唯一。
- 路径的分类:
- 简单路径:在图结构中,如果一条路径上的顶点不重复出现,称为简单路径
- 环: 在图结构中,如果路径的第一个顶点和最后一个顶点相同,则为环,也叫回路。
- 简单回路:在图结构中,如果除第一个顶点和最后一个顶点相同,其余个点都不重复的回路。
9.连通、连通图、连通分量
- 如果图结构中两个顶点之间有路径,则称这两个顶点是连通的。只要路径连接即可,可以连接多个路径。
- 如果无向图中任意两个顶点都是连通的,那么这个图便为连通图。有任意顶点不连通就是非连通图。
- 无向图的极大连通子图称为该图的连通分量。(对于一个连通图,其连通分量就是自己本身。非连通图可能存在多个连通分量)
10.强连通图、强连通分量
- 有向图中的两个连通的概念:
- 在有向图中,如果两个顶点之间有路径(注意方向),也称这两个结点是连通的。
- 在有向图中,任意两点都(注意都)是连通的,则称该图为强连通图。
- 有向图的极大强连通图称为该图的强连通分量
11.权
- 在实际应用中往往需要将边表示为某种数值,这个数值便是该边的权。无向图加入权值,称为无向带权图。有向图加入权值,称为有向带权图。
12.网
- 网就是边上带有权值的图的另一种名称。网的概念与实际更为贴切。
5.图结构的存储
在实际中通常采用结构数组的形式来单独保存定点的信息,然后采用二维数组的形式保存顶点之间的关系。这种保存顶点关系的数组称为邻接矩阵。
无向图:邻接矩阵是一个对称矩阵,连接的记为1,未连接的记为0
有向图:邻接矩阵连接有方向的记为1,未连接和连接没有方向的记为0
带权图:存在的记为权值,不存在的记为Z(一般用比所有权重和都大的值代替)
6.图的遍历
1.遍历图就是逐个去访问图中的所有顶点。图结构复杂存在多对多的特点,会出现顺着一条路遍历出现回到原点的情况。
2.常用的图遍历的方法:
- 广度优先法:
- 深度优先法:深度优先遍历特点是,选定一个出发点后进行遍历,能前进则前进,若不能前进,回退一步再前进,或再回退一步后继续前进。依此重复,直到所有与选定点相通的所有顶点都被遍历。类似于树的先序遍历,是一个递归的过程。
7.示例代码见Github:https://github.com/flakkaqi/DataStructure_and_Algorithms.git