数据结构总复习.docx
《数据结构总复习.docx》由会员分享,可在线阅读,更多相关《数据结构总复习.docx(23页珍藏版)》请在冰豆网上搜索。
数据结构总复习
第一章绪论
数据结构是一门研究非数值计算的程序设计问题中的操作对象以及它们之间的关系和操作的学科。
P3
1、数据(data)是对客观事物的符号表示。
2、数据元素(dataelement)是数据的基本单位,在计算机程序中做为一个整体进行考虑和处理。
3、数据项(dataitem)具有独立意义的、不可分割的数据的最小单位。
4、数据对象(dataobject)性质相同的数据元素的集合,是数据的一个子集。
5、数据结构(datastructure)数据结构是相互之间存在一种或多种特定关系的数据元素的集合。
数据结构:
带有结构和操作的数据元素集合
数据结构关心的是数据元素之间的相互联系和组织方式,以及对其施加的运算及运算规则,并不涉及数据元素的内容是什么。
数据之间的结构关系,是具体关系的抽象。
数据的存储结构:
数据结构在计算机内存中的表示。
顺序存储结构:
用一组连续的内存单元存放数据元素,用元素相对的存储位置表示元素之间的结构关系;
链式存储结构:
用任意一组存储单元存储数据元素,对每个数据元素除了保存自身信息外,还保存相关元素的存储位置。
数据结构基本操作的实现:
基本操作在计算机上的实现(方法)
6、数据结构的内容
(1)逻辑结构:
反映数据元素之间逻辑关系。
a.集合关系:
数据元素属于同一个集合;
b.线性关系:
数据元素属于一对一关系;
c.树形关系:
数据元素属于一对多关系;
d.图状关系:
数据元素属于多对多关系。
(2)存储结构:
是逻辑结构在计算机中的存储,其中包括数据元素的表示和关系的表示。
A、顺序映像(顺序存储结构)
B、非顺序映像(链式存储结构)
7、算法特性:
输入,输出,有穷性,确定性,可行性。
第二章线性表
一、线性表的概念
说明:
设A=(a1,a2,...,ai-1,ai,ai+1,…,an)是一线性表
1)线性表的数据元素可以是各种各样的,但同一线性表中的元素必须
是同一类型的;
2)在表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前趋,ai+1是ai的直接后继;
3)在线性表中,除第一个元素和最后一个元素之外,其他元素都有且仅有一个直接前趋,有且仅有一个直接后继,具有这种结构特征的数据结构称为线性结构。
线性表是一种线性数据结构;
4)线性表中元素的个数n称为线性表的长度,n=0时称为空表;
5)ai是线性表的第i个元素,称i为数据元素ai的序号,每一个元素在线性表中的位置,仅取决于它的序号;
线性表的顺序存储结构,就是用一组连续的内存单元依次存放线性表的数据元素。
顺序存储用一组地址连续的存储单元依次存储线性的数据元素,由于逻辑上相邻的数据元素在物理位置上也相邻。
优点:
存储密度大,存储空间利用率高。
缺点:
插入或删除元素时不方便。
链式存储用一组任意的存储单元存储线性表的数据元素相,邻数据元素可随意存放,
优点:
插入或删除元素时很方便,使用灵活。
缺点:
存储密度小,存储空间利用率低。
顺序表适宜于做查找这样的静态操作;链表宜于做插入、删除这样的动态操作。
第3章栈和队列
定义:
栈是限定仅能在表尾一端进行插入、删除操作的线性表
栈的特点:
后进先出
1栈是限定仅能在表尾一端进行插入、删除操作的线性表;
2表尾称为栈顶,表头称为栈底;
3栈的具有后进先出的特点;
4栈顶元素的位置由一个栈顶指针指示;
5进栈、出栈操作要修改栈顶指针;
6一个栈的输入序列为a,b,c,则所有可能的出栈序列为:
abc,acb,bac,bca,cba
队列是限定仅能在表头进行删除,表尾进行插入的线性表
1队列是限定仅能在表尾一端插入,表头一端删除操作的线性表;
2表尾称为队头,表头称为队尾
3队头、队尾元素的位置分别由队头指针和队尾指针指示;
4队列具有先进先出的特点
5入队操作要修改队尾指针,出队操作要修改队头指针;
说明线性表、栈与队的异同点。
答:
相同点:
都是线性结构,都可以用顺序存储或链表存储;栈和队列是的基本操作是线性表操作的子集。
不同点:
线性表为随机存取;
栈是限定仅能在表尾一端进行插入、删除操作,因而是后进先出的线性表;
队列是限定仅能在表头进行删除,表尾进行插入,因而是先进先出的线性表。
六、算法设计(每小题5分,共15分。
至少要写出思路)
1.【李春葆及严题集3.19④】假设一个算术表达式中包含圆括弧、方括弧和花括弧三种类型的括弧,编写一个判别表达式中括弧是否正确配对的函数correct(exp,tag);其中:
exp为字符串类型的变量(可理解为每个字符占用一个数组元素),表示被判别的表达式,tag为布尔型变量。
答:
用堆栈st进行判定,将(、[或{入栈,当遇到}、]或)时,检查当前栈顶元素是否是对应的(、[或{,若是则退栈,否则返回表示不配对。
当整个算术表达式检查完毕时,若栈为空表示括号正确配对,否则不配对。
答:
算术表达式中右括号和左括号匹配的次序正好符合后到的括号要最先被匹配的“后进先出”堆栈操作特点。
因此,可以借助一个堆栈来进行判断。
括号匹配共有四种情况:
(1)左右括号配对次序不正确;
(2)右括号多于左括号;
(3)左括号多于右括号;
(4)左右括号匹配正确。
编程后的整个函数如下(李书P31—32)
#definem0100/*m0为算术表达式中最多字符个数*/
correct(exp,tag)
charexp[m0];
inttag;
{charst[m0];
inttop=0,i=1;
tag=1;
while(i<=m0&&tag)
{if(exp[i]==‘(‘||exp[i]==’[‘||exp[i]==’{‘)/*遇到‘(‘、’[‘或’{‘,则将其入栈*/
{top++;
st[top]=exp[i];
}
if(exp[i]==’)’)/*遇到’)’,若栈顶是‘(‘,则继续处理,否则以不配对返回*/
if(st[top]==‘(‘)top--;
elsetag=0;
if(exp[i]==’)’)/*遇到’]’,若栈顶是‘[‘,则继续处理,否则以不配对返回*/
if(st[top]==‘[‘]top--;
elsetag=0;
if(exp[i]==’)’)/*遇到’}’,若栈顶是‘{‘,则继续处理,否则以不配对返回*/
if(st[top]==‘{‘top--;
elsetag=0;
i++;
}
if(top>0)tag=0;/*若栈不空,则不配对*/
}
严题集对应答案:
3.19
StatusAllBrackets_Test(char*str)//判别表达式中三种括号是否匹配
{
InitStack(s);
for(p=str;*p;p++)
{
if(*p=='('||*p=='['||*p=='{')push(s,*p);
elseif(*p==')'||*p==']'||*p=='}')
{
if(StackEmpty(s))returnERROR;
pop(s,c);
if(*p==')'&&c!
='(')returnERROR;
if(*p==']'&&c!
='[')returnERROR;
if(*p=='}'&&c!
='{')returnERROR;//必须与当前栈顶括号匹配
}
}//for
if(!
StackEmpty(s))returnERROR;
returnOK;
}//AllBrackets_Test
2001级通信6班张沐同学答案(已上机通过)
#include
#include
voidpush(charx);
voidpop();
voidcorrect(enumBoolean&tag);
//原来的定义是voidcorrect(structStack*head,enumBoolean&tag);
typedefstructStack
{
chardata;
structStack*next;
};
structStack*head,*p;
enumBoolean{FALSE,TRUE}tag;
voidmain()
{
head=(structStack*)malloc(sizeof(structStack));
head->data='S';
head->next=NULL;
//head'sdatahasnotbeeninitialized!
!
correct(tag);
if(tag)
printf("Right!
");
else
printf("Wrong!
");
}
voidpush(charx)
{
p=(structStack*)malloc(sizeof(structStack));
if(!
p)
printf("There'snospace.\n");
else
{
p->data=x;
p->next=head;
head=p;
}
}
//ifyoudefinethe"Correct"functionlikethat
//DebugwillshowthatthePushactiondoesn’ttakeeffection
voidpop()
{
if(head->next==NULL)
printf("Thestackisempty.\n");
else
{
p=head;
head=head->next;
free(p);
}
}
//voidcorrect(structStack*head,enumBoolean&tag)
voidcorrect(enumBoolean&tag)
{
inti;
chary;
printf("Pleaseenterabds:
");
for(i=0;y!
='\n';i++)
{
scanf("%c",&y);
if((y==')'&&head->data=='(')||(y==']'&&head->data=='[')||(y=='}'&&head->data=='{'))
pop();
elseif((y=='(')||(y=='[')||(y=='{'))
push(y);
/*调试程序显示,y并没有被推入堆栈中。
即head->data的值在Push中显示为y的值,但是出Push函数。
马上变成Null。
*/
else
continue;
}
if(head->next==NULL)//原来的程序是if(head==NULL)tag=TRUE;
tag=TRUE;
else
tag=FALSE;
}
/*总结:
由于head为全局变量,所以不应该将其再次作为函数的变量。
因为C语言的函数变量是传值机制,所以在函数中对参数进行了拷贝复本,所以不能改变head的数值。
*/
2.【统考书P604-15】假设一个数组squ[m]存放循环队列的元素。
若要使这m个分量都得到利用,则需另一个标志tag,以tag为0或1来区分尾指针和头指针值相同时队列的状态是“空”还是“满”。
试编写相应的入队和出队的算法。
解:
这就是解决队满队空的三种办法之①设置一个布尔变量以区别队满还是队空(其他两种见简答题);
思路:
一开始队空,设tag=0,若从rear一端加到与front指针相同时,表示入队已满,则令tag=1;
若从front一端加到与rear指针相同时,则令tag=0,表示出队已空。
3.【严题集3.31③】试写一个算法判别读入的一个以‘@’为结束符的字符序列是否是“回文”。
答:
编程如下:
intPalindrome_Test()//判别输入的字符串是否回文序列,是则返回1,否则返回0
{
InitStack(S);InitQueue(Q);
while((c=getchar())!
='@')
{
Push(S,c);EnQueue(Q,c);//同时使用栈和队列两种结构
}
while(!
StackEmpty(S))
{
Pop(S,a);DeQueue(Q,b));
if(a!
=b)returnERROR;
}
returnOK;
}//Palindrome_Test
第六章树和二叉树
定义:
树是n个结点的有限集合。
在任一棵非空树中:
(1)有且仅有一个称为根的结点;。
(2)其余结点可分为m个互不相交的有限集合,而且这些集合中的每一集合本身又是一棵树,称为根的子树。
从逻辑结构看:
1)树中只有根结点没有前趋;
2)除根外,其余结点都有且仅一个前趋;
3)树的结点,可以有零个或多个后继;
4)除根外的其他结点,都存在唯一条从根到该结点的路径;
5)树是一种分枝结构
树的深度:
树中所有结点的最大层数
题:
C的结点类型定义如下:
structnode
{chardata;
structnode*lchild,rchild;
};
C算法如下:
voidtraversal(structnode*root)
{if(root)
{printf(“%c”,root->data);
traversal(root->lchild);
printf(“%c”,root->data);
traversal(root->rchild);
}
}
2.设如下图所示的二叉树B的存储结构为二叉链表,root为根指针,结点结构为:
(lchild,data,rchild)。
其中lchild,rchild分别为指向左右孩子的指针,data为字符型,root为根指针,试回答下列问题:
1.对下列二叉树B,执行下列算法traversal(root),试指出其输出结果;
二叉树B
答:
ABCCEEBADFFDGG
3.【类似严题集6.27③】给定二叉树的两种遍历序列,分别是:
前序遍历序列:
D,A,C,E,B,H,F,G,I;中序遍历序列:
D,C,B,E,H,A,G,I,F,
试画出二叉树B,并简述由任意二叉树B的前序遍历序列和中序遍历序列求二叉树B的思想方法。
答:
由前序先确定root,由中序可确定root的左、右子树。
然后由其左子树的元素集合和右子树的集合对应前序遍历序列中的元素集合,可继续确定root的左右孩子。
将他们分别作为新的root,不断递归,则所有元素都将被唯一确定。
五、阅读分析题(每题5分,共20分)
1.试写出如图所示的二叉树分别按先序、中序、后序遍历时得到的结点序列。
答:
DLR:
ABDFJGKCEHILM
LDR:
BFJDGKACHELIM
LRD:
JFKGDBHLMIECA
2.
把如图所示的树转化成二叉树。
六、算法设计题(前5题中任选2题,第6题必做,每题8分,共24分)
6.【严题集6.26③】假设用于通信的电文仅由8个字母组成,字母在电文中出现的频率分别为0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10。
试为这8个字母设计哈夫曼编码。
使用0~7的二进制表示形式是另一种编码方案。
对于上述实例,比较两种方案的优缺点。
答:
先将概率放大100倍,以方便构造哈夫曼树。
w={7,19,2,6,32,3,21,10}
二叉树性质
性质1在二叉树的第i层上最多有2i-1个结点(i>=1)
性质2一棵深度为k的二叉树中,最多有2k-1个结点,最少有k个结点。
在一棵二叉树中,如果叶子结点数为n0,度为2的结点数为n2,则有:
n0=n2+1。
性质4具有n个结点的完全二叉树的深度为log2n+1。
满二叉树:
如果深度为k的二叉树,有2k-1个结点则称为满二叉树;
完全二叉树:
深度为K,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点都一一对应时,称之为完全二叉树
完全二叉树的特点
1.叶子结点只能出现在最下两层;
2.完全二叉树中如果有度为1的结点,只可能有一个,且该结点只有左孩子。
3.深度为k的完全二叉树在k-1层上一定是满二叉树。
二叉树的顺序存储结构一般仅存储完全二叉树和满二叉树。
二叉树:
或为空树,或由根及两颗不相交的左子树、右子树构成,并且左、右子树本身也是二叉树。
1、二叉树的遍历
①访问根结点;
②先序遍历根结点的左子树;
③先序遍历根结点的右子树
先序遍历序列:
ABDGCEF
2、中序(根)遍历
①中序遍历根结点的左子树;
②访问根结点;
③中序遍历根结点的右子树。
中序遍历序列:
DGBAECF
3、后序(根)遍历
①后序遍历根结点的左子树;
②后序遍历根结点的右子树;
③访问根结点。
后序遍历序列:
GDBEFCA
13.图的BFS生成树的树高比DFS生成树的树高小或相等。
14.用普里姆(Prim)算法求具有n个顶点e条边的图的最小生成树的时间复杂度为O(n^2);用克鲁斯卡尔(Kruskal)算法的时间复杂度是O(elog2e)。
三、简答题(每题6分,共24分)
1.【严题集7.1①】已知如图所示的有向图,请给出该图的:
(1)
顶点
1
2
3
4
5
6
入度
3
2
1
1
2
2
出度
0
2
2
3
1
3
每个顶点的入/出度;
(2)邻接矩阵;
(3)邻接表;
(4)逆邻接表。
邻接矩阵
邻接表
逆邻接表
2.【严题集7.7②】请对下图的无向带权图:
(1)写出它的邻接矩阵,并按普里姆算法求其最小生成树;
(2)
写出它的邻接表,并按克鲁斯卡尔算法求其最小生成树。
(1)邻接矩阵最小生成树
(2)邻接表
0
1
2
3
4
5
6
7
^
a
最小生成树
{(f,g)}
{(f,g),(e,f)},
{(f,g),(e,f),(a,c)},
{(f,g),(e,f),(a,c),(a,b)},
{(f,g),(e,f),(a,c),(a,b),(d,h)},
{(f,g),(e,f),(a,c),(a,b),(d,h),(d,g)},
{(f,g),(e,f),(a,c),(a,b),(d,h),(d,g),(b,d)},
{(f,g),(e,f),(a,c),(a,b),(d,h),(d,g),(b,d),}
4.【严题集7.11②】试利用Dijkstra算法求图中从顶点a到其他各顶点间的最短路径,写出执行算法过程中各步的状态。
S={A,C}
A→B:
(A,B)15
A→C:
(A,C)2
A→C:
(A,C,E)10
A→D:
(A,D)12
A→F:
(A,C,F)6
A→G:
(A,G)∞
S={A}
A→B:
(A,B)15
A→C:
(A,C)2
A→D:
(A,D)12
A→E:
(A,E)∞
A→F:
(A,F)∞
A→G:
(A,G)∞
S={A,C,F,E}
A→B:
(A,B)15
A→C:
(A,C)2
A→D:
(A,C,F,D)11
A→C:
(A,C,E)10
A→F:
(A,C,F,G)16
S={A,C,F}
A→B:
(A,B)15
A→C:
(A,C)2
A→D:
(A,C,F,D)11
A→C:
(A,C,E)10
A→F:
(A,C,F,G)16
S={A,C,F,E,D,G}
A→B:
(A,B)15
A→C:
(A,C)2
A→D:
(A,C,F,D,G)14
A→C:
(A,C,E)10
S={A,C,F,D,B}
A→B:
(A,B)15
A→C:
(A,C)2
A→D:
(A,C,F,D,G)14
A→C:
(A,C,E)10
S={A,C,F,E,D}
A→B:
(A,B)15
A→C:
(A,C)2
A→D:
(A,C,F,D,G)14
A→C:
(A,C,E)10
四、给定下列网G:
(10分)
1试着找出网G的最小生成树,画出其逻辑结构图;
2用两种不同的表示法画出网G的存储结构图;
邻接表:
邻接矩阵:
3用C语言(或其他算法语言)定义其中一种表示法(存储结构)的数据类型。
#defineMAX_VERTEX_NUM20
typedefenum{DG,DN,UDG,UDN}GraphKind;//图的类型定义
typedefcharVertexData;//假设顶点数据为字符型
typedefstructArcCell{
AdjTypeadj;//无权图用1和0表示是否相邻,对带权图为权值
InfoType*info;
}ArcCell;
typedefstruct{
VertexDatavexs[MAX_VERTEX_NUM];//顶点向量
ArcCellarcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
intvettex,arcnum//图的顶点数和边(弧)数
GraphKindkind;//前面图示没有反映出
}MGraph;