数据结构复习资料.docx
- 文档编号:4856289
- 上传时间:2022-12-10
- 格式:DOCX
- 页数:30
- 大小:2.73MB
数据结构复习资料.docx
《数据结构复习资料.docx》由会员分享,可在线阅读,更多相关《数据结构复习资料.docx(30页珍藏版)》请在冰豆网上搜索。
数据结构复习资料
数据结构的定义
数据结构是一门讨论“描述现实世界实体的数学模型(非数值计算)及其上的操作在计算机中如何表示和实现”的学科。
数据结构:
是指数据以及数据元素相互之间的联系,可以看作是相互之间存在着某种特定关系的数据元素的集合。
对数据结构的内容包括以下几个方面:
1数据的逻辑结构,指数据元素之间的逻辑关系。
2数据的存储结构,指数据元素及其关系在计算机存储器中的存储方式,也称为数据的物理结构。
3数据运算,指施加在数据上的操作。
算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中,每一条指令表示一个或多个操作。
粗略地说,算法是为了求解问题而给出的一个指令序列,程序是算法的一种具体实现。
一个算法必须满足以下五个重要特性:
1.有穷性2.确定性3.可行性4.有输入5.有输出
算法的重要特征
(1)有穷性:
算法在有穷步之后结束,每一步在有穷时间内完成。
(2)确定性:
算法中的每一条指令有明确的含义,无二义性。
(3)可行性:
可通过已经实现的基本运算执行有限次来实现算法中的所有操作。
算法分析的两个主要方面是分析算法的时间复杂度和空间复杂度。
算法的执行时间主要与问题的规模有关。
问题规模是一个与输入有关的量。
语句频度是指算法中该语句被重复执行的次数。
算法中所有语句的频度之和记作T(n),是该算法所求解问题规模的函数。
当问题规模趋向无穷大时,T(n)的数量级称为渐进时间复杂度,简称时间复杂度,记作T(n)=O(f(n))。
通常采用算法中表示基本运算的语句的频度来分析算法的时间复杂度。
例题:
1.数据结构中的逻辑结构是指( ),物理结构是指( )。
2.算法的基本特征包括有穷性、()、()、有输入和输出。
3.算法的有穷性是指( )。
4.算法的确定性是指( )。
5.算法的可行性是指( )。
6.算法分析的两个主要方面是分析算法的( )和空间复杂度。
7.语句频度是指(算法中该语句被重复执行的次数)。
8.设n为正整数,对下面的程序段,写出语句①、②、③的频度及该程序段的时间复杂度。
for(i=1;i<=n;i++)
{
s=0;①n
for(j=1;j<=n;j++)
s=s+i×j;②n2
if(s%2)③n
print(s);
}
第二章线性表
本章内容:
2.1线性表的基本概念
☞一个线性表是有n个数据元素的有限序列:
(a1,a2,…,ai,…,an)
2.2线性表的顺序存储结构
☞线性表的顺序存储指用一组地址连续的存储单元依次存储线性表的数据元素。
这称为顺序表。
特点:
Ø存储单元地址连续(需要一段连续空间)
Ø逻辑上相邻的数据元素其物理位置也相邻
Ø存储密度大(100%)
Ø随机存取,元素的存储位置存在如下关系:
Loc(ai)=Loc(a1)+(i-1)*d(1≤i≤n)
2.3线性表的链式存储结构
☞线性表的链式存储指用任意的存储单元存放线性表中的元素,每个元素与其直接前驱和(或)直接后继之间的关系用指针来表示。
这称为链表。
☞头指针是指向链表第一个结点的指针。
☞头结点是链表中的第一个结点但是头结点中不存放数据元素。
单链表、循环链表的类型定义
typedefstructLNode{
ElemTypedata;/*存储数据元素*/
structLNode*next;/*指向后继结点*/
}SLink,*LinkList;
LinkListhead,tail;
例题
1.顺序表中,逻辑上相邻的数据元素在物理位置上(也相邻)。
线性表L=(a1,a2,...,an)采用顺序存储,假定在不同的n+1个位置上的插入概率相同,则插入一个新元素平均需要移动的元素个数是(n/2)。
2.在一个长度为n的顺序表中,在第i个元素(1in)之前插入一个新元素时,需向后移动(n-i+1)个元素。
3.在表长为n的单链表中,取得第i(1in)个数据元素必须从(头指针)出发开始寻找。
4.在一个具有n个结点的有序单链表中,插入一个新结点并保持链表有序的算法时间复杂度为(O(n))。
5.解释头指针和头结点。
6.请对线性表进行顺序存储和链式存储的特点作比较。
基于空间的考虑:
顺序表的存储空间是静态分配的,而链表的存储空间是动态分配的。
因此,当线性表的长度变化较大,难以估计其存储空间规模时,宜采用动态链表作为存储结构。
反之,则采用顺序表作为存储结构。
另外,存储密度越大,则存储空间的利用率越高。
显然,顺序表的存储密度为1,而链表的存储密度小于1。
因此,当线性表的长度变化不大,易于事先确定其大小时,为了节省空间,采用顺序表为宜。
基于时间的考虑:
顺序表是由向量实现的,它是一种随机存取结构,而链表是一种顺序存储结构。
因此,若线性表的操作主要是进行查找,很少进行插入和删除操作时,采用顺序表作存储结构为宜。
反之,则采用链表作为存储结构。
7.编写算法,将一个带头结点的单链表就地逆置。
(请先说明算法思路,再用类高级语言编写算法。
)
☞将原链表看成由两部分组成:
已经完成逆置的部分和未完成逆置的部分。
☞设置两个指针p和s,p指向已完成逆置部分链表的第一个结点,s指向未逆置部分的第一个结点。
☞初始时令指针p指向第一个元素结点,s指向p所指结点的后继。
将第一个元素结点的指针域置为空。
☞将未逆置部分的结点逐个插入到头结点之后。
p=head->next;
if(p)
s=p->next;
p->next=NULL;
p=s;
s=s->next;
p->next=
head->next;
head->next=p;
p=s;
s=s->next;
p->next=
head->next;
head->next=p;
☞将原链表看成由两部分组成:
已经完成逆置的部分和未完成逆置的部分。
☞设置两个指针p和s,p指向已完成逆置部分链表的第一个结点,s指向未逆置部分的第一个结点。
☞初始时令指针p指向第一个元素结点,s指向p所指结点的后继。
将第一个元素结点的指针域置为空。
☞将未逆置部分的结点逐个插入到头结点之后。
算法:
voidreverse(LinkListhead)
{//带头结点的单链表逆置
p=head->next;if(!
p)return;
s=p->next;p->next=NULL;
while(s){
p=s;s=s->next;p->next=head->next;head->next=p;
}
}
第三章栈和队列
☞栈是后进先出的线性表,队列是先进先出的线性表;
☞在应用中,栈和队列都是容器,因此需要判断是否“栈空”或“队空”;
☞采用顺序存储结构时,栈和队列都可能存在“溢出”问题,分别称为“栈满”、“队满”;
☞采用顺序结构的队列常见形式是循环队列。
☞栈的运算演示
(1)A、B、C、D四个元素依次进入一个栈,再依次出栈,得到一个输出序列DCBA。
例题
1.用S、X分别表示入栈、出栈操作,若元素入栈顺序为1、2、3、4,为得到出栈序列1、3、4、2,则相应的S和X操作串是(SXSSXSXX)。
2.若push、pop分别表示入栈、出栈操作,初始栈为空且元素a、b、c依次进栈,则经过操作序列push、push、pop、pop、push、pop之后,得到的出栈序列为(bac)。
3.如果进栈的序列为1、2、3,则不能得到的出栈序列为(312)。
¯令队列空间中的一个单元闲置,使得在任何时刻,保持Q.rear和Q.front之间至少间隔一个空闲单元
MAXSIZE=8
☞队列满(full):
(Q.rear+1)%MAXSIZE==Q.front
☞队列空:
Q.rear==Q.front
☞队列长度:
(Q.rear-Q.front+MAXSIZE)%MAXSIZE
例题
1.在循环队列结构中(队列空间容量为M),Q.rear指向队尾元素所在位置,Q.front指向队头元素所在位置,则队列的长度为((Q.rear-Q.front+1+M)%M)。
2.用循环链表表示的队列长度为n,若只设头指针,则出队和入队的时间复杂度分别是(O
(1))和(O(n));若只设尾指针,则出队和入队的时间复杂度分别是(O
(1))和(O
(1))。
1.若以域变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。
请完善下面的入队列和出队列的算法。
#defineMAXSIZE100//最大队列长度
typedefstruct{
Qelemtype*base;//base为队列所在存储区域的首地址
intlength;//队列长度
intrear;//队尾元素位置
}SqQueue;
1.若以域变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。
请完善下面的入队列和出队列的算法。
#defineMAXSIZE100//最大队列长度
typedefstruct{
Qelemtype*base;//base为队列所在存储区域的首地址
intlength,rear;//队列长度和队尾元素位置
}SqQueue;
StatusEnQueue(SqQueue&Q,Qelemtypee)
{//将元素e插入队列Q
if(
(1))returnERROR;//队列满,无法插入
Q.rear=
(2);//计算元素e的插入位置
(3)=e;//在队尾加入新的元素
Q.length++;//队列长度加1
returnOK;
}
//
(1)Q.length>=MAXSIZE
(2)(Q.rear+1)%MAXSIZE(3)Q.base[Q.rear]
第四章串
1.了解串的基本运算
2.了解串的模式匹配算法
第六章树和二叉树
二叉树或者是一棵空树;或者由一个根结点和两棵互不相交的称为左子树和右子树的二叉树组成
满二叉树中所有分支结点都有左孩子和右孩子,叶结点都集中在二叉树的最后一层。
满二叉树结点的编号:
从树根为1开始,按照层数从小到大、同一层从左到右的次序进行。
完全二叉树中,最多只有最下面两层的结点的度数可以小于2,最下面一层的叶结点都排列在该层最左边的位置上。
完全二叉树结点的编号:
从树根为1开始,按照层数从小到大、同一层从左到右的次序进行。
例题
1.一棵满二叉树中共有n个结点,其中有m个叶子结点,则n和m的关系为(n=2m-1)。
2.在完全二叉树中,若一个结点没有左孩子子结点,则它一定没有(B)。
A.父结点B.右孩子结点
C.左兄弟结点D.右兄弟结点
性质1非空二叉树上第i层上至多有2i-1个结点i≥1。
性质2高度为h的二叉树至多有2h-1个结点(h≥1)。
性质3非空二叉树上叶结点数(度为0)等于双分支结点数(度为2)加1。
性质4对完全二叉树中编号为i的结点(1≤i≤n,n≥1,n为结点数),可以算出其左孩子结点、右孩子结点和父结点的编号(若这些结点存在)。
性质5具有n个(n>0)结点的完全二叉树的高度为log2(n+1)或log2n+1。
☞二叉树的顺序存储指的是用元素在数组中的下标表示一个结点与其孩子和父结点的关系.
☞一般用二叉链表存储二叉树(每个结点有两个指针域)
☞树的遍历是访问树中每个结点仅一次的过程。
可以认为遍历是把所有的结点放在一条线上,或者将一棵树进行线性化的处理。
☞先序遍历DLR、中序遍历LDR、后序遍历LRD
☞层序遍历
☞先序遍历DLR:
访问根结点、先序遍历左子树、先序遍历右子树
☞中序遍历LDR:
中序遍历左子树、访问根结点、中序遍历右子树
☞后序遍历LRD:
后序遍历左子树、后序遍历右子树、访问根结点
☞先序遍历:
访问根结点、先序遍历左子树、先序遍历右子树。
下图的先序遍历序列为ABDEGCF。
☞中序遍历:
中序遍历左子树、访问根结点、中序遍历右子树。
下图的中序遍历序列为DBGEACF。
☞后序遍历:
后序遍历左子树、后序遍历右子树、访问根结点。
下图的后序遍历序列为DGEBFCA。
☞层序遍历:
先根后子树、先左子树后右子树。
下图的层序遍历序列为ABCDEFG。
例题
1.在有n个结点的二叉树的二叉链表中必定存在(n+1)个空链域。
2.前序遍历序列与中序遍历序列相同的二叉树为(D)。
A.根结点无左子树的二叉树
B.根结点无右子树的二叉树
C.只有根结点的二叉树或非叶子结点只有左子树的二叉树
D.只有根结点的二叉树或非叶子结点只有右子树的二叉树
3.已知一棵二叉树的先序遍历序列为ABDGCEF,中序遍历序列为DGBAECF,画出此二叉树。
树(森林)采用孩子兄弟链存储结构。
可以将一棵树或一个森林转换为一棵二叉树,反之亦然。
树的孩子兄弟链存储结构是指在一个结点中既指出当前结点的第一个孩子,也指示出当前结点的兄弟。
下图(a)的树对应的孩子兄弟链存储结构如图(b)所示。
森林转换为二叉树的过程:
左指针:
父子关系右指针:
兄弟关系
线索二叉树
☞对于具有n个结点的二叉树,采用二叉链存储结构时,每个结点有两个指针域,总共有2n个指针域,又由于只有n-1个结点被有效指针所指向(n个结点中只有树根结点没有被有效指针域所指向),则共有2n-(n-1)=n+1个空链域。
遍历二叉树的结果是一个结点的线性序列。
可以利用这些空链域存放指向结点的前驱和后继结点的指针。
这些指向结点在某种遍历序列中的“前驱”和“后继”的指针,称作线索
哈夫曼树
☞哈夫曼树(或最优二叉树)是一类带权路径长度最短的树,这种树的叶子结点带有权值。
☞路径和路径长度
¯从树中的一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目称作路径长度。
☞结点的带权路径长度
¯从根到该结点的路径长度与该结点权的乘积称为结点的带权路径长度
☞树的带权路径长度
¯树中所有叶子的带权路径长度之和称为树的带权路径长度,记作
树的带权路径长度
WPL=7*2+5*2+2*2+4*2=36
WPL=4*2+7*3+5*3+2*1=46
☞设有四个叶子a、b、c和d的二叉树中,对应的权值分别为7、5、2和4,构造哈夫曼树。
练习题
1.设n为某棵哈夫曼树的叶子结点数目,则该哈夫曼树共有(2n-1)个结点。
2.已知组成电文的字符集D及其概率分布W为:
D={a,b,c,d,e}
W={0.25,0.30,0.12,0.25,0.08}
用哈夫曼算法为该字符集中的字符编码,画出哈夫曼树。
1.二叉树第i层上的结点数目最多为(2i-1)。
2.在n个结点的线索二叉树中,线索的数目是(n+1)。
3.假设二叉树中所有非叶子结点都有左、右子树,则对有m个叶子结点的此类二叉树,结点总数为(2m-1)。
4.已知二叉树T的后序遍历序列和中序遍历序列分别为HCDFIGBAE和DHCEFBGIA。
(1)试画出二叉树T;
(2)画出与二叉树T对应的中序线索二叉树;
(3)画出与该二叉树对应的树(森林)。
第七章图
存储
1.邻接矩阵
顶点之间相邻关系用矩阵表示。
1.邻接矩阵
顶点之间相邻关系用矩阵表示。
2.邻接链表
顶点:
通常按编号顺序将顶点数据存储在一维数组中
关联同一顶点的边:
用线性链表存储
☞从图的某个顶点出发,访问图中的所有顶点,且使每个顶点仅被访问一次。
这一过程叫做图的遍历。
☞遍历方法:
深度优先遍历和广度优先遍历
☞生成树
Ø一个连通图的生成树是一个极小连通子图,它含有图中全部顶点,但只有足以构成一棵树的n-1条边。
☞生成树的代价等于其边上的权值之和,我们把具有权值最小的生成树称为最小生成树。
☞普里姆算法和克鲁斯卡尔算法是两种常用的构造最小生成树的方法。
❑拓扑排序方法:
1)在有向图中选一个无前趋的顶点v,输出之;
2)从有向图中删除v及以v为尾的弧;
3)重复1)、2),直接全部输出全部顶点或有向图中不存在无前趋的结点时为止。
最短路径问题
1.单源点最短路径问题:
从一个顶点到其余各顶点的最短路径(迪杰斯特拉算法)
2.每一对顶点间的最短路径问题(弗洛伊德算法)
问题:
给定一个带权有向图G与源点v,求从v到G中其他顶点的最短路径,并限定各边上的权值大于或等于0。
迪杰斯特拉算法以路径长度递增的方式解单源点最短路径问题。
例题
1.对于有n个顶点的完全无向图,其边数e等于(n(n-1)/2)。
2.一个连通图的生成树是一个(极小)连通子图,n个顶点的生成树有(n-1)条边。
3.假设含n个结点的无向图形成一个环,则它的生成树为(n)个。
4.单源最短路径的Dijkstra算法是按路径长度(路经长度递增的次序)依次求解的。
5.在一个无向图的邻接表中,若表结点的个数是m,则图中边的条数是(m/2)条。
6.已知一赋权有向图如下:
1.写出该图的邻接矩阵表示并据此给出从顶点v1出发的深度优先遍历序列;
2.说明该有向图是否强连通;
3.给出该图的两个拓扑序列;
4.若将该图视为无向图,用克鲁斯卡尔算法求最小生成树
●已知一赋权有向图如下:
1.写出该图的邻接矩阵表示并据此给出从顶点v1出发的深度优先遍历序列;
2.说明该有向图是否强连通;
深度优先遍历序列:
v1v2v3v5v7v4v6
该图不是强连通图,例如,存在v1至v2的路径,反之则没有。
第9章查找
二分查找(折半查找)
❑折半查找判定树是描述折半查找过程的二叉树
若有序顺序表为:
a1 则其判定树((low+high)/2)如下: ❑二分查找判定树: 描述二分查找过程的二叉树 ☞若有序顺序表为: a1 则其判定树((low+high)/2)如下: 二叉排序树 ☞二叉排序树(二叉检索树、二叉查找树)定义 Ø二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: Ø若其左子树不空,则左子树上所有结点的值均小于它的根结点的值; Ø若其右子树不空,则右子树上所有结点的值均大于它的根结点的值 Ø其左、右子树也分别为二叉排序树 ☞查找: 查找键值等于key的记录 Ø若二叉排序树为空树,则查找失败,返回;若根结点的键值等于key,则查找成功,返回;若根结点的键值大于key,则到根的左子树上继续查找;否则,到根的右子树上继续查找; BSTNode*BSTSearch(BSTNode*bt,KeyTypekey){ //在T指向根的二叉排序树中递归地查找关键字等于key的数据元素 //若找到,返回指向该结点的指针,否则返回NULL if(bt==NULL)returnNULL; elseif(bt->key==key)returnbt; elseif(key returnBSTSearch(bt->lchild,key); else returnBSTSearch(bt->rchild,key); }//BSTSearch 二叉排序树的查找性能分析 ☞若查找成功,则走了一条从根结点到某结点的路径,若查找失败,则走到一棵空的子树时为止。 因此,最坏情况下,其平均查找长度不会超过树的高度。 二叉排序树的构造 平衡二叉树 四种平衡处理 ☞在平衡二叉排序树上插入结点时,其祖先结点的平衡因子可能发生变化,离插入结点最近且平衡因子变为2或-2的祖先结点作为根的子树称为最小不平衡子树。 ☞一般情况下,假设由于在二叉排序树上插入结点而失去平衡的最小子树根结点的指针为a,则失去平衡后进行调整的规律可归纳为以下四种情况: RR型左旋平衡处理 LL型右旋平衡处理 LR型先左后右旋转平衡处理 RL型先右后左旋转平衡处理 哈希表查找 ☞一个散列结构是一块地址连续的存储空间,它与一个称为散列(哈希)函数的函数相关联,该函数是数据记录的关键字到地址空间的映射。 Hash: 关键字→哈希地址 ☞这种存储空间的使用方式,使得 (1)存储记录时,通过散列函数计算出记录的存储位置并按此存储位置存储记录 记录位置=Hash(记录的关键字) (2)访问记录时,同样利用散列函数计算存储位置,然后根据所计算出的存储位置访问记录 ☞散列技术中的主要问题 表面上看,设置了散列函数后,只需作简单的函数计算就可以实现元素的定位及查找操作,但事实上没有这么简单,概括起来,主要有以下两个问题: (1)冲突及解决 一般情况下,设计出的散列函数很难是单射的,即不同的关键字会对应到同一个存储位置,这样就造成了冲突(碰撞)。 此时,发生冲突的关键字互为同义词。 (2)散列函数的设计 设计一个简单、均匀、存储空间利用率高、冲突少的散列函数是关键。 构造哈希函数的常用方法 1.直接定址法 2.数字分析法 3.平方取中法 4.折叠法 5.除留余数法该方法的散列函数形式为: Hash(key)=key%p 其中,p为不大于散列表表长m的整数 6.随机法 常用的冲突解决方法 1.开放地址法 开放定址法利用下列公式求“下一个”空地址 Hi=(H(key)+di)MODmi=1,2,…K(K<=m-1) 其中H(key)为散列函数,m为散列表长度,di为增量序列 根据di的取法,解决冲突时常使用下面一些方法: (1)线性探测再散列 (2)二次探测再散列 (3)伪随机探测再散列 假设哈希表的地址为0~m-1,则哈希表的长度为m。 若一个关键字在地址d处发生冲突,则依次探查d+1,d+2,…,当达到表尾m-1时,又从0,1,2,….开始探查,直到找到一个空闲位置来存储冲突的关键字,将这一种方法称为线性探测再散列。 Hi=(H(key)+di)MODmi=1,2,…,k(k≤m-1) 其中,H(key)为关键字key的哈希函数值,di=1,2,3,…,m-1 例如: 给定关键字序列如下,散列函数为H(k)=k
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 复习资料
![提示](https://static.bdocx.com/images/bang_tan.gif)