数据结构复习.docx
- 文档编号:24655935
- 上传时间:2023-05-29
- 格式:DOCX
- 页数:36
- 大小:1.95MB
数据结构复习.docx
《数据结构复习.docx》由会员分享,可在线阅读,更多相关《数据结构复习.docx(36页珍藏版)》请在冰豆网上搜索。
数据结构复习
树
1、定义:
是n各节点的有限集,在任意一棵非空树中:
有且仅有一个根节点;当n大于1时,其余节点又可以分为m个互不相交的树,并称为根的子树。
2、结点的度:
结点拥有的子树的个数;树的度:
树内各节点度的最大值
3、树的深度:
树中节点的最大层次
4、树的存储结构的表示:
双亲表示法,孩子表示法,孩子兄弟表示法
(1)双亲表示法:
除了数据域,还有一个表示双亲的parent域,是顺序存储结构,如果还想表示孩子,还可以加上一个孩子域,下图的结构体是一个节点的结构
(2)孩子表示法:
把每个节点的孩子节点排列起来,以单链表做存储结构,然后n个头指针又组成一个线性表,采用顺序存储结构,放在一个一维数组里,下图的结构体是一个节点的结构。
也可以加上一个parent域构成双亲孩子表示法。
另外补充一个树的多重链表表示法:
每个节点包括一个数据域和多个指针域,指针域指向结点的孩子。
可以用树的度表示指针域个数(适用于各结点的度数相差不大的情况),还可以在弄一个度域存放结点的度
(3)孩子兄弟表示法:
一个数据域,两个指针域,一个指向第一个孩子,也就是最左边的孩子,另一个指向右边的第一个兄弟。
5、树的遍历:
先根遍历,后根遍历
先根:
后根:
6、二叉树:
二叉树是每个节点最多只有两棵子树的树,有左右子树之分。
使用二叉树可以极大提高查找的效率,但是一般只适用于结果只有两种的情况下。
(1)分类:
完全二叉树,满二叉树,斜树
(2)性质:
第i层至多有2的i-1次方个结点,i大于等于1;深度为k的结点至多有2的k次方-1个结点;n0=n2+1;具有n个结点的完全二叉树深度为logn+1(logn为不超过logn的最大整数);n个结点的二叉树按层序从1开始编号,第i个结点的父节点为i/2,如果2i大于n则节点无左孩子,否则左孩子为2i,如果2i+1大于n则节点无右孩子,否则右孩子为2i+1。
(3)二叉树的存储结构:
顺序存储结构:
由于二叉树的特殊性,他可以使用一个一维数组存储,但是一般只用与完全二叉树,否则如果是右斜树,会导致空间极大浪费;二叉链表:
由一个数据域和左右指针域组成,指针域指向左右两个孩子。
(4)二叉树的遍历:
从根结点出发按照某种次序依次访问二叉树中的所有节点,使得所有节点被访问一次,且仅被访问一次
前序遍历:
遍历顺序:
根左右,先节点后叶子
中序遍历:
顺序:
左根右
后序遍历:
顺序:
左右根,先叶子后节点
递归思想:
后序遍历左子树;按后序遍历右子树;访问根。
层序遍历:
从上层开始访问,同层从左到右
根据中序和另一个遍历推导出剩下的遍历:
方法是找根节点
(5)二叉树的建立:
也是递归的思想,不过将函数换成create,将原来打印节点的地方换成生成结点、给结点赋值
(6)线索二叉树:
为了充分能利用叶子结点的空指针,将左右空指针分别指向结点的前驱和后继(不同遍历顺序的前驱和后继是不同的)。
把这种指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树树称为线索二叉树。
另外需要加上一个指示是线索还是左右孩子。
可以降低遍历的时间空间复杂度。
适用于需要经常查找和遍历的二叉树。
(7)树与二叉树的转换
树转换为二叉树:
1树中所有相邻兄弟之间加一条连线;(加线)
2对树中的每个结点,只保留它与第一个孩子结点之间的连线,删去它与其他孩子结点之间的连线;(去线)
3以树的根结点为轴心,将整棵树顺时针转动一定的角度,使之结构层次分明。
(层次调整)
二叉树转换为树:
加2去掉的线,去1加上的线,层次调整
可以证明,二叉树的先序遍历相当于树的先根遍历,二叉树的中序遍历相当于树的后根遍历。
(8)哈夫曼树:
记每个叶子节点的权值为w,路径长度为l,则结点带权路径长度记为w*l,我们称树的带权路径长度WPL值(所有节点的带权路径长度和)最小的二叉树为赫夫曼树。
哈夫曼树的所有有用结点都在叶子节点上。
构造:
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。
n个权值分别设为w1、w2、…、wn,哈夫曼树的构造规则为:
1.将w1、w2、…,wn看成是有n棵树的森林(每棵树仅有一个结点);
2.在森林中选出根结点的权值最小的两棵树进行合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
3.从森林中删除选取的两棵树,并将新树加入森林;
4.重复(02)、(03)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
目的:
哈夫曼树的目的是为了压缩通信中需要传输的数据量,根据字母出现的频次(权值)构造哈夫曼树,左子树为0,右子树为1,可以减少编码所需的总码长,所以也称哈夫曼压缩。
不等长编码需要注意编码的二义性问题,保证任何一个字符的编码都不是另一个字符编码的前缀。
图
1、定义:
由顶点的有穷非空集合和边的顶点之间的边的集合组成,通常表示为G(V,E),其中G表示图,V是顶点的集合,E是边的集合
2、一些概念
(1)无向边:
表示顶点vi到vj之间的边没有方向,用无序偶对(vi,vj)表示。
(2)有向边:
有方向,也称为弧,用
图中任意两条边都是有向边的图称为有向图。
(3)简单图:
图中不存在顶点到自身的边,也不存在重复的边
(4)无向完全图:
任意两个顶点之间都存在边,n个顶点的无向完全图有n*(n-1)/2条边。
(5)有很多条边的图称为稠密图,反之称为稀疏图;带权的图称为网。
(6)子图:
假设两个图G=(v,{E})和G1=(v1,{E1}),如果v1属于v,且E1属于E,则称G1为G的子图。
(7)图的顶点和边的关系:
邻节点:
(v1,v2)属于E,则v1和v2互为邻节点;入度:
以顶点v为头的弧的数目称为顶点v的入度;出度:
以顶点v为尾的弧的数目称为顶点v的出度;顶点的度=出度+入度;无向图中从v到v1的路径是一个顶点的序列;路径的长度就是路径上边或弧的数目。
第一个顶点和最后一个顶点相同的路径称为环或回路。
(8)连通图:
在无向图G中,如果从顶点v到v1有路径,则称v和v1是连通的,如果对于图中任意两个结点vi和vj都是连通的,则称G是连通图。
无向图的极大连通子图称为连通分量。
强连通图:
正反向都存在路径的图。
连通图的生成树是一个极小的连通子图,它含有图中全部的n个顶点,但只有构成一棵树的n-1条边。
3、图的存储结构:
一个图的信息包括两部分:
图中顶点的信息;描述顶点之间关系——边或者弧的信息。
(1)邻接矩阵:
在邻接矩阵表示中,除了存放顶点本身信息外,还用一个矩阵表示各个顶点之间的关系。
对于n个顶点的图G=(V,E),若(vi,vj)或
图的邻接矩阵定义为:
1若(vi,vj)∈E(G)或
A[i,j]=
1其它情形
邻接矩阵存储方法的特点:
(1)无向图的邻接矩阵一定是一个对称矩阵。
因此,在具体存放邻接矩阵时只需存放上(或下)三角矩阵的元素即可;
(2)对于无向图,邻接矩阵第i行(或第i列)中非∞元素的个数正好等于第i个顶点的度;
(3)对于有向图,邻接矩阵第i行(或第i列)中非∞元素的个数正好等于第i个顶点的出度(或入度);
(4)很容易确定图中任意两个顶点之间是否有边或弧相连;但是,所花费的时间代价很大。
网图的邻接矩阵:
(2)邻接表:
邻接表(AdjacencyList)是图的一种顺序存储与链式存储相结合的存储方法。
对于图G中的每个顶点vi,将所有邻接于vi的顶点vj链成一个单链表,这个单链表就称为顶点vi的邻接表;再将所有顶点的邻接表表头放到数组中,就构成了图的邻接表。
(3)其他表示方法:
十字链表,邻接多重表,边集数组(由两个一维数组组成,一个存储顶点信息,一个存边信息:
边信息由起点下标,终点下标,权组成)
4、图的遍历:
图的遍历是从某个顶点出发,沿着某条搜索路径对图中所有顶点各作一次访问。
根据搜索路径的方向不同,图的遍历有两种方法:
深度优先搜索遍历(DFS)和广度优先搜索遍历(BFS)。
(1)深度优先搜索
v搜索思想
在图G中任选一个顶点i作为遍历的初始点,则深度优先搜索遍历定义如下:
(1)首先访问顶点i,并将其访问标记置为访问过,即visited[i]=1;
(2)然后搜索与顶点i有边相连的下一个顶点j,若j未被访问过,则访问它,并将j的访问标记置为访问过,visited[j]=1,然后从j开始重复此过程,若j已访问,再看与i有边相连的其它顶点;
(3)若与i有边相连的顶点都被访问过,则回溯到前一个访问顶点并重复刚才过程,直到图中所有顶点都被访问完止。
(2)广度优先搜索:
v搜索的思想
广度优先搜索遍历类似于树的按层次遍历。
设图G的初态是所有顶点均未访问,在G中任选一顶点vi作为初始点,则广度优先搜索的基本思想是:
(1)首先访问顶点vi,并将其访问标志置为已被访问,即visited[vi]=1;
(2)接着依次访问与顶点vi有边相连的所有顶点W1,W2,…,Wt;
(3)然后再按顺序访问与W1,W2,…,Wt有边相连又未曾访问过的顶点;
依此类推,直到图中所有顶点都被访问完为止。
6、最小生成树:
把构造连通网的最小代价生成树称为最小生成树
7、prim算法:
图论中的一种算法,可在加权连通图里搜索最小生成树。
即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:
Vertex(graphtheory)),且其所有边的权值之和亦为最小。
一直在重复这样一个过程:
在那些一个端点在生成树里,另一个端点不在生成树里的边中,选取一条权最小的边,将它和另一个端点加进生成树
(1)算法描述:
1).输入:
一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:
Vnew={x},其中x为集合V中的任一节点(起始点),Enew={},为空;
3).重复下列操作,直到Vnew=V:
a.在集合E中选取权值最小的边,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将边加入集合Enew中;
4).输出:
使用集合Vnew和Enew来描述所得到的最小生成树。
(2)方法:
从指定顶点开始将它加入集合中,然后将集合中的顶点与集合外的顶点所构成的所有边中选取权值最小的一条边作为生成树的边,并将集合外的那个顶点加入集合中,表示该定点已连通。
再用集合内的顶点与集合外的顶点构成的边中找出最小的边,并将相应的顶点加入集合,直到所有顶点都加入到集合中。
即得最小生成树。
8、kruskal算法:
将图中边按其权值由小到大的次序顺序排列,若选边后不形成回路,则保留作为一条边,若形成回路则除去,依次选够n-1条边,即得最小生成树(n为顶点数)
(1)prim算法与kruskal算法的比较:
prim算法以某顶点为起始点,逐步找到各顶点上最小权值的边;kruskai算法直接以边为目标构建最小生成树,先找权值最小的边,不过要考虑构成环路的问题。
Kruskal算法主要针对边来展开,边少时(稀疏图)时效率会高,prim算法主要针对顶点展开,边多时(稠密图)会好些。
9、最短路径问题:
旨在寻找图中两节点之间的最短路径,常用的算法有:
floyd算法和dijkstra算法。
10、floyd算法(多源最短路径):
是最简单的最短路径算法,可以计算图中任意两点间的最短路径 folyd算法的时间复杂度是O(N3),如果是一个没有边权的图,把相连的两点 间的距离设为dist[i][j]=1,不相连的两点设为无穷大,用floyd算法可以判断i,j两点是否有路径相连。
(1)基本思想:
从顶点i到顶点j的最短路径可以有两种情况。
从i直接到j;从i中间经过若干条边再到j。
所以可以先假设D[i][j]是顶点i到顶点j的最短路径距离,对于每一个结点k,检查D[i][k]+D[k][j] (2)算法描述: 从任意一条单边路径开始,所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大;对于每一个顶点i,j看看是否存在一个顶点k使得从i到k再到j比已知路径更短,若是则更新他。 11、Dijkstra算法(单源最短路径): 用于计算一个顶点到其他所有顶点的最短路径。 主要特点是以起始点为中心向外层扩散,直到扩展到终点为止。 (1)算法思想: 把一个带权有向图中的顶点集合v分成两组,第一组为已求出最短路径的顶点集合(用s表示,初始时s中只有一个源点,以后每求出一条最短路径,就将加入到集合s中,直到全部顶点都加入到s中,算法就结束了)。 第二组为其余未确定最短路径的顶点集合(用u表示),按最短路径长度的递增次序把第二组的定点加入到s中,在加入的过程中,总保持从源节点v到s中各定点的最短路径长度不大于从源点v到u中任何顶点的最短路径长度。 此外,每个顶点对应一个距离,s中的顶点的距离就是从v到此顶点的最短路径长度,u中的定点距离,是从v到此顶点只包括s中的顶点为中间顶点的当前最短路径长度。 (2)步骤: (1)初始时,S只包含源点,即S=,v的距离为0。 U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边)或)(若u不是v的出边邻接点)。 (2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。 (3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u(uU)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。 (4)重复步骤 (2)和(3)直到所有顶点都包含在S中。 12、拓扑排序: 就是对一个有向图构造拓扑序列的过程 (1)AOV网: 在一个有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网 (2)图中顶点的集合为v,如果满足顶点i到j有一条路径,则在顶点序列中顶点i必在j之前,称这样的序列为拓扑序列。 (3)基本思想: 从AOV网中选择一个入度为0的顶点输出,然后删除此顶点,并删除以此顶点为尾的弧,继续重复此步骤,直到输出全部顶点或者AOV网中不存在入度为0的顶点为止。 13、关键路径 (1)AOE网: 在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示的网叫做AOE网。 (2)我们把路径上的各个活动所持续的时间之和称为路径长度,从源点到汇点具有最大长度的路径叫做关键路径,在关键路径上的活动叫做关键活动。 (3)AOE与AOV的对比: AOV网是顶点表示活动的网,只描述活动之间的制约关系;AOE是边表示活动的网,建立在活动之间制约关系没有矛盾的基础之上,再来分析整个工程需要多少时间。 查找 1、查找概论 (1)查找表: 是由同一类型的数据元素或记录构成的集合。 (2)关键字: 是数据元素中某个数据项的值。 (3)主关键字: 如果一个关键字可以唯一标识一个记录。 (4)查找定义: 就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素或记录。 (5)查找表分类: 静态查找表: 只做查找操作的查找表;动态查找表: 在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。 (6)查找结构: 为了提高查找效率专门为查找操作设置的数据结构。 对于静态查找表可以用线性表结构,动态查找表可以用二叉排序树或散列表结构。 2、顺序表查找 (1)过程: 从表的第一个(或最后一个)记录开始,逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功,找到所查的记录;如果直到最后一个记录,其关键字和给定值比较都不相等时,则表中没有所查的记录,查找不成功。 (2)顺序表查找的优化: 设置a[0]=key,当找到i为0时,说明查找失败,否则查找成功。 3、有序表查找 (1)折半查找: 也称为二分查找,前提: 线性表中的记录是关键码有序的,线性表必须采用顺序存储。 基本思想: 在有序表中,取中间记录作为比较对象,若给定值与中间记录得关键字相等,则查找成功,若给定值小于中间记录的关键字,则在中间记录的左半区间继续查找,大于则在右边。 不断重复上诉过程,直到查找成功,若查找区域无该记录,则查找失败。 (2)插值查找: 适合表长脚大,关键字分布比较均匀的查找表,本质上与二分查找差不多,或者说,二分查找是一种特殊的插值查找。 改变mid为 (3)斐波那契查找: 斐波那契数列: 从1,1开始前面两个数相加等于后面一个数组成的数列。 基本思想: 运用黄金比例的概念在数列中查找点进行查找,提高查找效率。 要求: 开始表中记录的个数为某个斐波那契数小1,即n=F(k)-1,mid=low+F(k-1)-1 比较过程: 开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1),比较结果也分为三种1)相等,mid位置的元素即为所求;2)>,low=mid+1,k-=2;说明: low=mid+1说明待查找的元素在[mid+1,high]范围内,k-=2说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,所以可以递归的应用斐波那契查找。 3)<,high=mid-1,k-=1。 说明: low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1说明范围[low,mid-1]内的元素个数为F(k-1)-1个,所以可以递归的应用斐波那契查找。 4、线性索引查找: (1)稠密索引: 是指在线性索引中,将数据集中的每个记录对应一个索引项。 对于稠密索引的索引表来说,索引项一定是按照关键码有序排列的。 索引项结构: 下标,关键码,指针 (2)分块索引: 把数据集的记录分成若干块,并且这些快需要满足: 块内无需;块间有序。 索引项结构: 最大关键码,块长,指向块首的指针。 查找步骤: 块间可以用有序查找的方法,块内只能顺序查找。 (3)倒排查找: 5、二叉排序树(也叫二叉搜索树): (1)性质: 可以是一颗空树;或者若他的左子树不空,则左子树上所有结点的值均小于他的根结构的值;或者若他的右子树不空,则右子树上所有结点的值均大于他的根结构的值;他的左右子树也分别是二叉排序树 (2)目的: 构造一棵二叉排序树不仅可以排序,还可以提高查找和插入删除关键字的速度。 (3)操作: 插入,删除,查找 查找: 插入: 删除: 一: 该节点是叶子节点,这个删除是最简单的,将其改为空,并修改父节点即可; 二: 该节点只有一个孩子(左孩子或右孩子,这个在具体实现时不同操作),这时只要将该节点的孩子节点放在该节点上,同时修改该节点的父节点即可; 三: 该节点有两个孩子,用另一结点替代被删除结点: 右子树的最小元素或者左子树的最大元素 6、平衡二叉树(AVL树): (1)定义: 是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多为1. (2)平衡因子BF: 二叉树结点的左子树深度减去右子树深度的值 (3)最小不平衡子树: 距离插入节点最近的,切平衡因子的绝对值大于1的结点为根的子树 (4)操作: 创建一个平衡二叉树就是要在插入节点的同时不断调整为平衡二叉树,删除也是一样。 调整过程大概可以分为四类: 左左旋转,右右旋转,左右旋转,右左旋转 7、多路查找树(B树) (1)定义: 每个节点的孩子数可以多于两个,且每一个结点处可以存储多个元素。 (2)特殊形式: 2-3树,2-3-4树,B树,B+树 (3)2-3树: 树中的每一个节点都具有两个孩子或三个孩子(分别称为2结点和3结点),一个二结点包括一个元素和两个孩子,要么没有孩子,要么有两个孩子;一个三结点包括两个元素和三个孩子,要么没有孩子,要么就有三个孩子,并且大小是有序的;2-3树所有叶子结点都在同一个层次 (4)B树: 是一种平衡的多路查找树,2-3树是B树的特例,结点最大的孩子数目称为B树的阶。 因此2-3树是3阶B树 (5)B+树: 在B树的基础上扩展而来,出现在分支节点中的元素会被当作他们在改分支节点位置的中序后继者(叶子节点)中再次列出,每一个叶子节点都会保存一个指向后一个叶子节点的指针。 8、散列表查找(哈希表) (1)散列技术: 是在记录的存储位置和他的关键字之间建立一个确定的对应关系f(称为散列函数),使得每个关键字key对应一个存储位置,查找时根据这个确定的对应关系找到每个关键字key的映射f(key),就能找到对应的位置。 (2)散列表: 采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间就称为散列表或哈希表。 关键字对应的记录地址称为散列地址。 (3)散列表查找的步骤: 在存储时,通过散列函数计算记录的散列地址,并按此散列地址存储该记录;在查找记录时,通过同样的散列函数计算记录地址访问该记录。 (4)关系: 散列技术既是一种存储技术也是一种查找方法,但是他与线性表,图,又有所不同,即散列记录的记录之间不存在什么逻辑关系,他只与关键字有关联,但是主要面向查找。 散列技术最适合的求解问题是查找与给定值相等的记录。 (5)散列冲突: key1不等于key2,但是f(key1)=f(key2)的情况,并且key1和key2称为这个散列函数的同义词。 (6)散列函数的构造方法: 原则: 计算简单,散列地址分布均匀。 1)直接定址法: 取关键字的某个线性函数值作为散列地址f=ak+b 适合查找表较小且连续的情况。 2)数字分析法: 抽取关键字的一部分来计算散列存储位置的方法,适合关键字位数较多的情况,且关键字的若干位分布较均匀。 3)平方取中法: 将关键字平方,再取中间的几位数字,适合不知道关键字的分布,位数又不是特别多的情况。 4)折叠法: 将关键字从左到右等分成几部分,将这几部分叠加求和,并按散列表表长取最后几位作为散列表地址,适合关键字位数较多的情况。 5)除留余数法: f=keymodp(p<=m)m为散列表长度,不仅可以对key取模,还可以对key做一些处理后再取模。 P一般取小于或等于表长(最好接近表长)的最小质数。 6)随机数法: f=random(key) (7)处理散列冲突的方法 1)开放定址法: 发生冲突就去找下一个空的散列地址,f(key)=(f(key)+d)modm(d=1,2,3,。 。 。 m-1)。 还可以内分为线性探测法、二次探测法(防止关键字的堆积)、伪随机探测法 2)再散列函数法: 发生冲突就换一种散列函数 3)链地址法: 增加指针 4)公共溢出区法: 将冲突的关键字放在另一个溢出表中,查找时先找查找表,没有再找溢出表 (8)散列表的填装因子a=填入表中的记录个数/散列表长度,散列表的平均查找长度取决于散列表的填装因子。 9、总结: 查找这一章围绕查找,讲了查找表,静态查找表,动态查找表。 顺序查找表,针对无序表;插入查找,折半查找,斐波那契查找,主要是针对有序表;线性索引查找;二叉排序树是一种动态查找表,为了提高查找效率又有平衡二叉树,平衡二
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 复习
![提示](https://static.bdocx.com/images/bang_tan.gif)