returnOK;
}
)
4.中缀表达式转前缀表示式和后缀表达式:
(2分)
前缀表达式:
操作符在操作数的前面(从右往左看,从右往左写)
后缀表达式:
操作符在操作数的后面(从左往右看,从左往右写)
中缀表达式转换为后缀表达式的规则
1)建立运算符栈
2)设表达式的结束符和运算符栈的栈底为‘#’
3)从左向右读表达式
(1)若读取的是操作数,直接输出到后缀表达式;
(2)若读取的是‘(’,直接进栈
(3)若读取的是‘)’,连续输出栈顶运算符到后缀表达式,直到弹出‘(’为止;
(4)若读取的是非括号运算符,将之与栈顶运算符进行比较:
若比栈顶运算符的优先数高,则直接进栈;否则将栈顶运算符发送到到后缀表达式,再继续比较,直到栈为空或栈顶元素的优先级低于当前读取的运算符的优先级。
4)若表达式未读取完,重复3;若表达式读取完,而栈非空,则依次将栈中运算符发送给后缀表达式,直到栈空。
5.队列的特点:
先进先出的线性表。
只允许在表的一端进行插入,在另一端删除元素。
允许插入的一端称为队尾(rear),允许删除的一端称为队首(front)。
6.链队列的存储结构:
见本
*7.循环队列(环状的顺序队列)(6分):
特点:
用一组地址连续的存储单元依次存储从队首到队尾的元素,
front和rear分别指示队头元素和队尾元素的位置。
约定:
1.初始化,空队列front=rear=0。
2.插入新队尾元素时“尾指针rear增1”,删除队头元素时“头指针front增1”。
3.非空队列front始终指向队头元素,rear始终指向队尾元素的下一个位置(空位置)。
每出一次:
Q.front=Q.front+1;每入一次:
Q.rear=Q.rear+1;
Q.front=(Q.front+1)%InitSize;
Q.rear=(Q.rear+1)%InitSize;
判断队列空间的“空”与“满”:
(1)少用一个元素空间的循环队列Q的空满判断条件(常用判断方法)
为空:
Q.front=Q.rear
为满:
(Q.rear+1)%MAXSIZE=Q.front
(2)以标志位来区分循环队列Q为满判断条件:
(加临时长度)
为空:
Q.front=Q.rear,且length=0
为满:
Q.front=Q.rear,且length=MAXSIZE
队列的基本操作的功能和调用格式:
InitQueue(&Q):
构造一个空队列Q
DestroyQueue(&Q):
销毁已存在的队列Q
ClearQueue(&Q):
将已存在的队列Q清空
QueueEmpty(Q):
判断Q是否为空队列
QueueLength(Q):
计算队列Q的长度
GetHead(Q,&e):
用e返回Q的队头元素的值
EnQueue(&Q,e):
插入元素e作为新队尾元素(入队列)
DeQueue(&Q,&e):
删除Q的队头元素,用e返回元素值(出队列)
QueueTraverse(Q,visit()):
对Q中的每个数据元素按从队头到队尾的顺序调用函数visit()
第四章
1.串的基本操作的功能:
StrCopy(&T,S):
由串S复制得到串T
StrEmpty(S):
判断S是否为空
StrLength(S):
返回串S的长度
ClearString(&S):
将串S清空
Concat(&T,S1,S2):
连接串S1和S2,生成新串T
SubString(&Sub,S,pos,len):
返回串S中第pos个字符起长度为len的子串
Index(S,T,pos):
返回主串S中第pos个字符之后子串T第一次出现的位置
2.串的模式匹配next[j]的求法:
见本。
3.改进的串的模式匹配的基本思想:
匹配过程中出现比较不等(即si<>pj)时,不需回溯i指针,而是利用已
经得到的“部分匹配”的结果,立即确定模式右移的位数和继续比较
的字符,即主串中第i个字符应与模式中第k个字符比较。
程序见本。
4.练习:
1.空串与空格串有何区别,字符串中的空格符有何意义?
空串在串处理中有何作用?
2.设s=’IAMASTUDENT’,t=’GOOD’,q=‘WORKER’。
求:
StrLength(s);StrLength(t)
SubString(s,8,7);SubString(t,2,1)
Index(s,’A’),Index(s,t)
Replace(s,’STUDENT’,q)
Concat(SubString(s,6,2),Concat(t,SubString(s,7,8)))。
答案:
1.不含任何字符的串称为空串,其长度为0。
仅含有空格字符的串称为空格串,其长度为串中空格字符的个数。
空格符可用来分隔一般的字符,便于人们的识别和阅读,但计算串长时应包括这些空格符。
空串在串处理中可作为任意串的子串;
2.StrLength(s)=14,StrLength(t)=4,
SubString(s,8,7)=’STUDENT’,
SubString(t,2,1)=’O’,Index(s,’A’)=3,
Index(s,t)=0,
Replace(s,’STUDENT’,q)=’IAMAWORKER’,
Concat(SubString(s,6,2),Concat(t,SubString(s,7,8)))=’AGOODSTUDENT’
5.课后题:
(1)求出:
‘T=abcaabbabcabaacbacba’的next函数值。
j1234567891011121314151617181920
模式串abcaabbabcabaacbacba
next[j]01112231234532211211
(2)试写一在串的堆存储结构上实现串的替换操作
Replace(&S,T,V)的算法(可以直接调用串的基本操作)
voidReplace(HString&S,HStringT,HStringV)
{
k=index(S,T,1);
if(k)
{
StrAssign(temp,””);
n=StrLength(T);m=StrLength(S);
while(k){
StrAssign(temp,Concat(temp,SubString(S,1,k-1),V));
m-=(k-1)-n;
StrAssign(S,SubString(S,k+n,m));//S为每次替换后的剩余串
k=index(S,T,1);
}//while
StrAssign(S,Concat(temp,S));
}//endif
}
第五章
1.多维数组元素物理地址的求法:
对b1×b2×…×bnn维数组:
LOC(i1,i2,…,in)=LOC(0,0,…,0)+(b2×b3×…×bn×i1+b3×b4×…×bn×i2+…+bn×in-1+in)×L
N维数组的数据元素存储位置的计算公式:
LOC(j1,j2,…,jn)=LOC(0,0,…,0)+(b2…bnj1+b3…bnj2+…+bnjn-1+jn)L
=LOC(0,0,…,0)+
(1)
其中,cn=L,ci-1=bi*ci,1
(1)称为n维数组的
映象函数。
2.广义表;
(1)广义表(GeneralizedLists):
n(n>=0)个数据元素的有序序列,一般记为:
LS=(α1,α2,…,αn)
LS为广义表的名称,n是它的长度。
αi可以是单个元素或广义表,分别称为广义表LS的原子和子表。
广义表LS非空时,第一个元素α1为LS的表头(Head);其余元素组成的表(α2,α3,…,αn)是LS的表尾(Tail)(注:
表尾一定是个广义表)。
深度:
广义表所含括号的重数。
空表的深度为1,原子的深度为0。
广义表L的深度为L中各个子表深度的最大值加1。
长度:
广义表中数据元素的个数,空表的长度为0.
(2)求表头函数:
GetHead(L)
求表尾函数:
GetTail(L)
求表长函数:
GetLength(L)
3.课后作业:
1.假设按低下标优先存储整数数组A9×3×5×8时,第一个元素的字节地址是100,每个整数占四个字节。
问下列元素的存储地址是什么?
1)a0000 2)a1111 3)a3125 4)a8427
见本
第六章
1.孩子兄弟表示法:
以二叉链表作树的存储结构,结点的两个域分别指向该结点的第一
个孩子结点和下一个兄弟结点。
存储结构:
typedefstructCSNode {
TElemTypedata;
structCSNode*firstchild,*nextsibling;
}CSNode,*CSTree;
2.树与二叉树的转换方法:
(1)将树转换为二叉树:
关键是把n个分支变为两个分支,步骤如下:
1)保留所有结点与其第一个子结点的链接
2)打断所有结点原本与其他子结点(不是第一个孩子结点的结点)的链接,并连结所有兄弟结点(拥有同一个父节点的子结点)
3)将兄弟结点顺时钟转45度。
(2)将二叉树转换为树
1)二叉树的根即为树的根;
2)二叉树的左子树为树的左子树,从根开始一直向右,遇到的右子树则将其作为树的子树。
3)打断所有结点与其右结点的链接。
详细例题见本
3.森林与二叉树之间的转换方法:
对于任意一棵二叉树B=(LBT,Node(root),RBT)可按如下规则转换得
到由n棵子树构成的森林F={T1,T2,…,Tn},其中第一棵树T1由根结点
ROOT(T1)和子树森林{t11,t12,…,t1m}构成:
若二叉树B为空树,则与其对应的森林F为空集;否则,由二叉树的根
结点(root)复制得到森林中第一棵树的根结点ROOT(T1),由二叉树
中的左子树LBT转换构造森林中第一棵树的子树森林{t11,t12,…,t1m},由二叉
树中的右子树RBT转换构造森林中其余树构成的森林{T2,T3,…,Tn}。
步骤如下:
(1)二叉树的根即为森林中第一棵树的根;
(2)从二叉树的根开始向右,遇到右子树,剪断其连接,使根及其左子树,成
为第一棵树;如此往复处理其右子树。
(3)将每棵二叉树转换为树。
转换过程见本;
4.树的两种遍历方法:
(1)先根遍历:
先遍历树的根结点,然后依次先根遍历根的每棵树。
(对应二叉树的先序遍历)
(2)后根遍历:
先依次后根遍历每棵子树,然后访问根结点。
(对应二叉树的中序遍历)书P139
5.森林的两种遍历方法:
(1)先序遍历
若森林非空,则先访问森林中第一棵树的根结点,再先序遍历第
一棵树中根结点的子树森林,然后先序遍历除去第一棵树之后剩
余的树构成的森林。
(2)中序遍历
若森林非空,则先中序遍历第一棵树根结点的子树森林,再访问
第一棵树的根结点,然后中序遍历除去第一棵树之后剩余的树构成的森林
6.树、森林的每种遍历方法与二叉树三种遍历方法之间的对应关系
1)树和森林进行的各种操作均可通过对“二叉树”相应的操作来完成,但要注意:
此时的二叉树其左、右子树和根结点之间的关系不再是“左、右孩子”,而左子树是根的“孩子”,右子树是根的“兄弟们”。
2)当森林转化成二叉树时,其第一棵树的子树森林转化成左子树,剩余树的森林转换成右子树,则森林的先序和中序遍历即为其对应的二叉树的先序(前序)和中序遍历。
3)当树以二叉链表形式存储时,树的先根遍历和后根遍历可借用二叉树的先序(前序)和中序遍历的算法实现。
7.二叉树的五个特性:
二叉树有五种基本形态:
(1)空二叉树
(2)只有根结点的二叉树
(3)左子树为空的二叉树
(4)右子树为空的二叉树
(5)左、右子树都不为空的二叉树
8.两种特殊形态的二叉树:
(1)满二叉树
深度为k且有2k-1个结点的二叉树。
第一层20
第二层21
第三层22
满二叉树第i层有2i-1个结点;
(2)完全二叉树
定义:
深度为k,有n个结点的二叉树当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时,称为完全二叉树。
特点:
1)叶子结点只可能出现在层次最大的两层上,并且最下面一层的结点都集中在该层最左边的连续的若干位置上。
2)对任一结点,若其右分支下子孙的最大层次为i,则其左分支下子孙的最大层次必为i或i+1。
9.在完全二叉树上求叶子节点数的方法:
在二叉树上,分支总数B=2*n2+n1(n1,n2分别为度为1、2的结点个数)
结点总数:
n=B+1;n=2*n2+n1+1
因为n=n0+n1+n2,故n2=n0-1;所以n=2*n0+n1-1
(在完全二叉树上,度为1的结点的个数只可能为0或1。
当结点总数n
为奇数时,n1=0;当结点总数为偶数时,n1=1。
)
10.二叉树的两种存储结构:
(1)顺序存储:
1)完全二叉树的顺序存储:
用一组地址连续的存储单元依次自上而
下、自左至右存储完全二叉树上的结点元素。
即将完全二叉树上编号为i的结点元素存储在一维数组中下标为i的分量中。
2)一般二叉树的顺序存储
将其每个结点与完全二叉树上的结点编号相对照,存储在一维数组相应的分量中,根结点存储在1号单元。
若父节点编号为n,可以得到:
(1)左子节点的编号为父节点编号乘以2:
2*n
(2)右子节点编号为父节点编号乘以2加1:
2*n+1
(2)链式存储结构:
1.二叉链表
链结点的构造为
左指针域 数据域 右指针域
二叉链表的存储结构
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
11.二叉树的三种遍历方法的思想:
前序(先根)遍历:
(1)访问根结点
(2)前序遍历左子树
(3)前序遍历右子树
中序遍历二叉树:
(1)中序遍历左子树
(2)访问根结点
(3)中序遍历右子树
后序(根)遍历:
(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根结点
能够根据二叉树的遍历序列画出二叉树。
12.赫夫曼树(2分):
特点:
N个叶子结点的赫夫曼树供有2N-1个结点、权值最大的结点的层次值最小,且没有度为1的结点。
构造:
(1)根据给定的n个权值{w1,w2,…,wn}构成n棵二叉树的集合F={T1,T2,…,Tn},其中每棵二叉树Ti中只有一个带权为wi的根结点,其左右子树均空。
(2)在F中选取两棵结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。
(3)在F中删除这两棵树,同时将新得的二叉树加入F中。
(4)重复
(2)、(3),直至F只含一棵树为止。
这棵树便是赫夫曼树。
练习:
1.若二叉树用二叉链表作存贮结构,则在n个结点的二叉树链表中只有n-1个非空指针域。
2.一棵深度为6的满二叉树有31个分支结点和32个叶子。
(分支结点为度不为0的结点)
3.一棵含有n个结点的k叉树,可能达到的最大深度为n,最小深度为完全k叉树,。
4.设一棵完全二叉树具有1000个结点,则此完全二叉树有500个叶子结点,有499个度为2的结点,
有1个结点只有非空左子树,有0个结点只有非空右子树。
5.深度为的k完全二叉树至少有2k-1个结点;对于深度为k的满二叉树,如果从上到下、从左到右给结点编号(从1开始),则最大的叶子结点编号是2k-1。
作业
第七章
1.邻接矩阵
1)邻接矩阵的定义
设图G=(V,E),n(n≥1)是图的顶点个数,则G的邻接矩阵为一个n阶方阵arcs[n][n]。
arcs[i][j]=0(vi,vj)或<vi,vj>不存在
1(vi,vj)或<vi,vj>存在
当G为网时,
arcs[i][j]=weight(vi,vj)或<vi,vj>存在,
其权值为weight
∞(vi,vj)或<vi,vj>不存在
2)邻接矩阵的性质(*)
(1)当图中各顶点的序号确定后,图的邻接矩阵是唯一确定的。
(2)无向图和无向网的邻接矩阵是一个对称矩阵。
(3)无向图邻接矩阵中第i行(或第i列)非0元素的个数即为第i个顶点的度。
(4)有向图邻接矩阵中第i行非0元素个数为第i个顶点的出度,第i列非0元素个数为第i个顶点的入度,第i个顶点的度为第i行与第i列非0元素个数之和。
(5)无向图邻接矩阵中非0元素个数是边数的两倍,有向图邻接矩阵中非0元素个数与弧数相等。
3)邻接矩阵法的实现
邻接矩阵存储结构用两个数组来实现。
(1)一维数组
来存储数据元素的(顶点)的信息。
顶点可按任意顺序存放,通常把存放顶点元素的数组下标作为该顶点的编号。
(2)二维数组(即邻接矩阵)
用来存储数据元素之间的关系(边或弧)的信息。
有N个顶点的图,其邻接矩阵是N阶方阵,记为arcs[N][N]。
4)图的邻接矩阵存储表示(*)
typedefenum{DG,DN,UDG,UDN}GraphKind;//图的四种类型
typedefstructArcCell{
VRTypeadj; //顶点关系类型
infoType*info; //与该边(或弧)相关的信息
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct{
VertexTypevexs[MAX_VERTEX_NUM];//顶点向量
AdjMatrixarcs; //邻接矩阵
intvexnum,arcnum; //图的当前顶点数和弧数
GraphKind kind; //图的种类标志
}Mgraph;
5)图的基本操作的实现
2.邻接表
1)定义:
邻接表(AdjacencyList):
为图中每个顶点建立一个反映邻接关系的单链表,把该顶点的所有邻接顶点的序号及与边或弧相关的信息链接起来,第i个单链表中的结点表示依附于顶点vi的各条边(或弧)。
2)邻接表的表头结点包括两个域:
(1)顶点的名称或其它有关信息(data域)
(2)指向链表中第一个结点(firstarc域)
表头结点可以顺序存储,也可链式存储。
邻接表的表结点包括三个域:
(1)邻接点在图中的位置(adjvex域)
(2)指向下一个弧或边的指针(nextarc域)
(3)与弧或边相关的信息(info域)
adjvex
nextarc
info
2)图的邻接表存储表示
typedefstructArcNode{
intadjvex; //该弧(或边)指向的顶点的位置
structArcNode*nextarc; //指向下一条弧(或边)的指针
infoType*info; //该弧(或边)的相关信息
}ArcNode;
typedefstructVnode{
VertexTypedata; //顶点信息
ArcNode*firstarc;//指向第一条依附该顶点的弧(或边)的指针
}VNode,AdjList[MAX_VERTEX_NUM];
typedefstruct{
AdjListvertices;
intvexnum,arcnum;
intkind; //图的种类标志
}ALGraph; //邻接表
3)图的基本操作的实现
3.图顶点入度、出度、度的计算方法
在有向图中:
顶点v的入度(InDegree):
以顶点v为弧头的弧的数目,记为ID(v)。
顶点v的出度(OutDegree):
以顶点v为弧尾的弧的数目,记为OD(v)。
顶点v的度(Degree):
与顶点相关联的弧的数目,记为TD(v)。
TD(v)=ID(v)+OD(v)
具有n个顶点的有向图最多有n(n-1)条边。
在无向图中:
顶点v的度(Degree):
与顶点v相关联的边的数目,记为TD(v)。
有n个顶点,e条边的图,满足关系 e=
具有n个顶点的无向图最多有n(n-1)/2条边.
4.连通图
1)在无向图G中,若从顶点vi到顶点vj存在路径,则称vi和vj是连通的。
连通图(ConnectedGraph):
图中任意两顶点都是连通的。
连通分量(ConnectedComponent):
无向图中的极大连通子图。
图见本
2)在有向图G中,若从顶点vi到顶点vj有路径,则称vi和vj