数据结构第三章习题
- 格式:doc
- 大小:22.50 KB
- 文档页数:6
第三章习题1.按图3.1(b)所示铁道(两侧铁道均为单向行驶道)进行车厢调度,回答:⑴如进站的车厢序列为123,则可能得到的出站车厢序列是什么?⑵如进站的车厢序列为123456,能否得到435612和135426的出站序列,并说明原因。
(即写出以“S”表示进栈、以“X”表示出栈的栈操作序列)。
2.设队列中有A、B、C、D、E这5个元素,其中队首元素为A。
如果对这个队列重复执行下列4步操作:(1)输出队首元素;(2)把队首元素值插入到队尾;(3)删除队首元素;(4)再次删除队首元素。
直到队列成为空队列为止,得到输出序列:(1)A、C、E、C、C (2) A、C、E(3) A、C、E、C、C、C (4) A、C、E、C3.给出栈的两种存储结构形式名称,在这两种栈的存储结构中如何判别栈空与栈满?4.按照四则运算加、减、乘、除和幂运算(↑)优先关系的惯例,画出对下列算术表达式求值时操作数栈和运算符栈的变化过程:A-B*C/D+E↑F5.试写一个算法,判断依次读入的一个以@为结束符的字母序列,是否为形如‘序列1& 序列2’模式的字符序列。
其中序列1和序列2中都不含字符’&’,且序列2是序列1的逆序列。
例如,‘a+b&b+a’是属该模式的字符序列,而‘1+3&3-1’则不是。
6.假设表达式由单字母变量和双目四则运算算符构成。
试写一个算法,将一个通常书写形式且书写正确的表达式转换为逆波兰式。
7.假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意不设头指针),试编写相应的队列初始化、入队列和出队列的算法。
8.要求循环队列不损失一个空间全部都能得到利用, 设置一个标志域tag , 以tag为0或1来区分头尾指针相同时的队列状态的空与满,请编写与此结构相应的入队与出队算法。
9.简述以下算法的功能(其中栈和队列的元素类型均为int):(1)void proc_1(Stack S){ int i, n, A[255];n=0;while(!EmptyStack(S)){n++; Pop(&S, &A[n]);}for(i=1; i<=n; i++)Push(&S, A[i]);}(2)void proc_2(Stack S, int e) { Stack T; int d;InitStack(&T);while(!EmptyStack(S)){ Pop(&S, &d);if (d!=e) Push( &T, d);}while(!EmptyStack(T)){ Pop(&T, &d);Push( &S, d);}}(3)void proc_3(Queue *Q){ Stack S; int d;InitStack(&S);while(!EmptyQueue(*Q)){DeleteQueue(Q, &d);Push( &S, d);}while(!EmptyStack(S)){ Pop(&S, &d);EnterQueue(Q,d)}}实习题1.回文判断。
第三章栈和队列试题一、单项选择题1.栈的插入和删除操作在()进行。
A. 栈顶B. 栈底C. 任意位置D. 指定位置2.当利用大小为n的数组顺序存储一个栈时,假定用top==n表示栈空,则向这个栈插入一个元素时,首先应执行()语句修改top指针。
A. top++;B. top--;C. top = 0;D. top;3.若让元素1,2,3依次进栈,则出栈次序不可能出现()种情况。
A. 3, 2, 1B. 2, 1, 3C. 3, 1, 2D. 1, 3, 24.在一个顺序存储的循环队列中,队头指针指向队头元素的()位置。
A. 前一个B. 后一个C. 当前D. 后面5.当利用大小为n的数组顺序存储一个队列时,该队列的最大长度为()。
A. n-2B. n-1C. nD. n+16.从一个顺序存储的循环队列中删除一个元素时,需要()。
A. 队头指针加一B. 队头指针减一C. 取出队头指针所指的元素D. 取出队尾指针所指的元素7.假定一个顺序存储的循环队列的队头和队尾指针分别为front和rear,则判断队空的条件为()。
A. front+1 == rearB. rear+1 == frontC. front == 0D. front == rear8.假定一个链式队列的队头和队尾指针分别为front和rear,则判断队空的条件为()。
A. front == rearB. front != NULLC. rear != NULLD. front == NULL9.设链式栈中结点的结构为(data, link),且top是指向栈顶的指针。
若想在链式栈的栈顶插入一个由指针s所指的结点,则应执行操作()。
A. top->link = s;B.s->link = top->link; top->link = s;C. s->link = top; top = s;D. s->link = top; top = top->link;10.设链式栈中结点的结构为(data, link),且top是指向栈顶的指针。
第三章习题1.按图3.1(b)所示铁道(两侧铁道均为单向行驶道)进行车厢调度,回答:⑴如进站的车厢序列为123,则可能得到的出站车厢序列是什么?⑵如进站的车厢序列为123456,能否得到435612和135426的出站序列,并说明原因。
(即写出以“S”表示进栈、以“X”表示出栈的栈操作序列)。
2.设队列中有A、B、C、D、E这5个元素,其中队首元素为A。
如果对这个队列重复执行下列4步操作:(1)输出队首元素;(2)把队首元素值插入到队尾;(3)删除队首元素;(4)再次删除队首元素。
直到队列成为空队列为止,得到输出序列:(1)A、C、E、C、C (2) A、C、E(3) A、C、E、C、C、C (4) A、C、E、C3.给出栈的两种存储结构形式名称,在这两种栈的存储结构中如何判别栈空与栈满?4.按照四则运算加、减、乘、除和幂运算(↑)优先关系的惯例,画出对下列算术表达式求值时操作数栈和运算符栈的变化过程:A-B*C/D+E↑F5.试写一个算法,判断依次读入的一个以@为结束符的字母序列,是否为形如‘序列1&序列2’模式的字符序列。
其中序列1和序列2中都不含字符’&’,且序列2是序列1的逆序列。
例如,‘a+b&b+a’是属该模式的字符序列,而‘1+3&3-1’则不是。
6.假设表达式由单字母变量和双目四则运算算符构成。
试写一个算法,将一个通常书写形式且书写正确的表达式转换为逆波兰式。
7.假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意不设头指针),试编写相应的队列初始化、入队列和出队列的算法。
8.要求循环队列不损失一个空间全部都能得到利用, 设置一个标志域tag , 以tag为0或1来区分头尾指针相同时的队列状态的空与满,请编写与此结构相应的入队与出队算法。
9.简述以下算法的功能(其中栈和队列的元素类型均为int):(1)void proc_1(Stack S){ int i, n, A[255];n=0;while(!EmptyStack(S)){n++; Pop(&S, &A[n]);} for(i=1; i<=n; i++)Push(&S, A[i]);}(2)void proc_2(Stack S, int e) { Stack T; int d;InitStack(&T);while(!EmptyStack(S)){ Pop(&S, &d);if (d!=e) Push( &T, d);}while(!EmptyStack(T)){ Pop(&T, &d);Push( &S, d);}}(3)void proc_3(Queue *Q){ Stack S; int d;InitStack(&S);while(!EmptyQueue(*Q)){DeleteQueue(Q, &d);Push( &S, d);}while(!EmptyStack(S)){ Pop(&S, &d);EnterQueue(Q,d)}}实习题1.回文判断。
第三章栈、队列和数组一、名词解释:1.栈、栈顶、栈底、栈顶元素、空栈2.顺序栈3.链栈4.递归5.队列、队尾、队头6.顺序队7.循环队8.队满9.链队10.随机存储结构11.特殊矩阵12.稀疏矩阵13.对称方阵14.上(下)三角矩阵二、填空题:1.栈修改的原则是_________或称________,因此,栈又称为________线性表。
在栈顶进行插入运算,被称为________或________,在栈顶进行删除运算,被称为________或________。
2.栈的基本运算至少应包括________、________、________、________、________五种。
3.对于顺序栈,若栈顶下标值top=0,此时,如果作退栈运算,则产生“________”。
4.对于顺序栈而言,在栈满状态下,如果此时在作进栈运算,则会发生“________”。
5.一般地,栈和线性表类似有两种实现方法,即________实现和________实现。
6.top=0表示________,此时作退栈运算,则产生“________”;top=sqstack_maxsize-1表示________,此时作进栈运算,则产生“________”。
7.以下运算实现在顺序栈上的初始化,请在________处用适当的句子予以填充。
int InitStack(SqStackTp *sq){ ________;return(1);}8.以下运算实现在顺序栈上的进栈,请在________处用适当的语句予以填充。
Int Push(SqStackTp *sq,DataType x){ if(sp->top==sqstack_maxsize-1}{error(“栈满”);return(0);}else{________________:________________=x;return(1);}}9.以下运算实现在顺序栈上的退栈,请在________________用适当句子予以填充。
数据结构第三章习题本文共分为三部分,分别针对数据结构第三章中的不同习题进行解答。
第一部分,解答关于树和二叉树的习题。
1.对于给定的有“n(n>0)”个结点的树,边数应为“n-1”条。
解析:树是一种无环连通无向图,因此任意n个结点的树有n-1条边。
2.往2(2≤n≤64)叉树的每个结点上添加一个数据元素,设计一个数据结构,实现迅速求该2叉树中所有结点的数据元素之和。
解析:可以使用先序遍历算法来完成,先序遍历树的根节点,然后递归遍历左子树和右子树,将每个结点的数据元素加和。
3.设计一个算法,判定给定的二叉树是否是完全二叉树。
解析:可以使用层次遍历算法来判定。
如果一棵树是完全二叉树,那么层次遍历结果中,如果一些结点有右孩子,那么该结点之后的所有结点都必须有孩子;如果一些结点没有右孩子,则该结点之后的所有结点都不能有孩子。
4.设有一棵完全二叉树,编写算法,生成一棵采用二叉链表存储结构的二叉树。
解析:可以使用层次遍历算法来构建树。
从根节点开始,依次按层次遍历的顺序遍历所有结点,依次将结点和它的孩子结点用链表链接起来。
第二部分,解答关于图的习题。
1.利用邻接表存储图,写出一个算法,判断两个节点之间是否存在路径。
解析:可以使用深度优先算法或广度优先算法来判断两个节点之间是否存在路径。
首先从起始节点开始,遍历其邻接节点,递归或使用队列来保存需要遍历的节点,直到遍历到目标节点或遍历完所有的节点。
2.利用邻接表存储图,写出一个算法,求图的连通分量个数。
解析:可以使用深度优先算法或广度优先算法来求图的连通分量个数。
首先从起始节点开始,遍历其邻接节点,标记遍历过的节点,直到遍历完所有的节点。
每次从一个未标记的节点开始进行遍历,当所有的节点都被遍历过后,即可得到图的连通分量个数。
3.利用邻接表存储图,写出一个算法,判断给定的图是否为无向图。
解析:可以遍历所有的边,对于每一条边(u,v),如果(u,v)存在,则判断(v,u)是否存在,如果都存在,则图为无向图,否则为有向图。
第3章栈和队列一选择题1. 对于栈操作数据的原则是()。
【青岛大学2001 五、2(2分)】A. 先进先出B. 后进先出C. 后进后出D. 不分顺序2. 在作进栈运算时,应先判别栈是否( ①),在作退栈运算时应先判别栈是否( ②)。
当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为( ③)。
为了增加内存空间的利用率和减少溢出的可能性,由两个栈共享一片连续的内存空间时,应将两栈的( ④)分别设在这片内存空间的两端,这样,当( ⑤)时,才产生上溢。
①, ②: A. 空 B. 满 C. 上溢 D. 下溢③: A. n-1 B. n C. n+1 D. n/2④: A. 长度 B. 深度 C. 栈顶 D. 栈底⑤: A. 两个栈的栈顶同时到达栈空间的中心点.B. 其中一个栈的栈顶到达栈空间的中心点.C. 两个栈的栈顶在栈空间的某一位置相遇.D. 两个栈均不空,且一个栈的栈顶到达另一个栈的栈底.【上海海运学院1997 二、1(5分)】【上海海运学院1999 二、1(5分)】3. 一个栈的输入序列为123…n,若输出序列的第一个元素是n,输出第i(1<=i<=n)个元素是()。
A. 不确定B. n-i+1C. iD. n-i【中山大学1999 一、9(1分)】4. 若一个栈的输入序列为1,2,3,…,n,输出序列的第一个元素是i,则第j个输出元素是()。
A. i-j-1B. i-jC. j-i+1D. 不确定的【武汉大学2000 二、3】5. 若已知一个栈的入栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,…,p N,若p N是n,则p i是( )。
A. iB. n-iC. n-i+1D. 不确定【南京理工大学2001 一、1(1.5分)】6. 有六个元素6,5,4,3,2,1 的顺序进栈,问下列哪一个不是合法的出栈序列?()A. 5 4 3 6 1 2B. 4 5 3 1 2 6C. 3 4 6 5 2 1D. 2 34 15 6【北方交通大学2001 一、3(2分)】7. 设栈的输入序列是1,2,3,4,则()不可能是其出栈序列。
第3章栈和队列一、选择题1.栈结构通常采用的两种存储结构是(A )。
A、顺序存储结构和链表存储结构B、散列和索引方式C、链表存储结构和数组D、线性链表结构和非线性存储结构2.设栈ST 用顺序存储结构表示,则栈ST 为空的条件是( B )A、ST.top-ST.base<>0B、ST.top-ST.base==0C、ST.top-ST.base<>nD、ST.top-ST.base==n3.向一个栈顶指针为HS 的链栈中插入一个s 结点时,则执行( C )A、HS->next=s;B、s->next=HS->next;HS->next=s;C、s->next=HS;HS=s;D、s->next=HS;HS=HS->next;4.从一个栈顶指针为HS 的链栈中删除一个结点,用x 保存被删除结点的值,则执行( C)A 、x=HS;HS=HS->next;B 、HS=HS->next;x=HS->data;C 、x=HS->data;HS=HS->next;D 、s->next=Hs;Hs=HS->next;5.表达式a*(b+c)-d 的后缀表达式为( B )A、abcdd+-B、abc+*d-C、abc*+d-D、-+*abcd6.中缀表达式A-(B+C/D)*E 的后缀形式是( D )A、AB-C+D/E*B、ABC+D/E*C、ABCD/E*+-D、ABCD/+E*-7.一个队列的入列序列是1,2,3,4,则队列的输出序列是( B )A、4,3,2,1B、1,2,3,4C、1,4,3,2D、3,2,4,18.循环队列SQ 采用数组空间SQ.base[0,n-1]存放其元素值,已知其头尾指针分别是front 和rear,则判定此循环队列为空的条件是()A、Q.rear-Q.front==nB、Q.rear-Q.front-1==nC、Q.front==Q.rearD、Q.front==Q.rear+19.循环队列SQ 采用数组空间SQ.base[0,n-1]存放其元素值,已知其头尾指针分别是front 和rear,则判定此循环队列为满的条件是()A、Q.front==Q.rearB、Q.front!=Q.rearC、Q.front==(Q.rear+1)%nD、Q.front!=(Q.rear+1)%n10.若在一个大小为6 的数组上实现循环队列,且当前rear 和front 的值分别为0 和3,当从队列中删除一个元素,再加入两个元素后,rear 和front 的值分别为()A、1,5B、2, 4C、4,2D、5,111.用单链表表示的链式队列的队头在链表的()位置A、链头B、链尾C、链中12.判定一个链队列Q(最多元素为n 个)为空的条件是()A、Q.front==Q.rearB、Q.front!=Q.rearC、Q.front==(Q.rear+1)%nD、Q.front!=(Q.rear+1)%n13.在链队列Q 中,插入s 所指结点需顺序执行的指令是()A 、Q.front->next=s;f=s;B 、Q.rear->next=s;Q.rear=s;C 、s->next=Q.rear;Q.rear=s;D 、s->next=Q.front;Q.front=s;14.在一个链队列Q 中,删除一个结点需要执行的指令是()A、Q.rear=Q.front->next;B、Q.rear->next=Q.rear->next->next;C、Q.front->next=Q.front->next->next;D、Q.front=Q.rear->next;15.用不带头结点的单链表存储队列,其队头指针指向队头结点,队尾指针指向队尾结点,则在进行出队操作时()A、仅修改队头指针B、仅修改队尾指针C、队头尾指针都要修改D、队头尾指针都可能要修改。
第3章栈和队列一、选择题1. 栈中元素的进出原则是( )A.先进先出B.后进先出C.栈空则进D.栈满则出2. 已知一个栈的进栈序列为1, 2, …, n,其输出序列是p1, p2, … , p n ,若p1=n,则p i=()A. iB. n-iC. n-i+1D.不确定3. 一个栈的输入序列为:a b c d e,则下列不可能是栈的输出序列的是()。
A. b c d a eB. e d a c bC. b c a d eD. a e d c b4. 判定一个栈ST(最多元素为m0)为空的条件是( )A.ST->top<>0 B.ST->top=0 C.ST->top<>m0 D.ST->top=m0 5. 判定一个队列QU(最多元素为m0)为满队列的条件是( )A.QU->rear -QU->front = = m0 B.QU->rear -QU->front -1= = m0 C.QU->front = = QU->rear D.QU->front = = QU->rear+16.数组Q[n]用来表示一个循环队列,f为当前队列头元素的前一位置,r为队尾元素的位置,假定队列中元素的个数小于n,计算队列中元素的公式为( )A. r-fB.(n+f-r)% nC.n+r-fD.(n+r-f)% n7. 栈和队列的共同点是()。
A. 都是先进先出B. 都是先进后出C. 只允许在端点处插入和删除元素D. 没有共同点8. 用单链表表示的链式队列的队头在链表的()位置。
A.表头B.表尾C.中间9. 设计一个判别表达式中左,右括号是否配对出现的算法,采用()结构最佳。
A.线性表的顺序存储结构 B. 队列C. 线性表的链式存储结构D. 栈10. 用不带头结点的单链表存储队列时,其队头指针指向队头结点,其队尾指针指向队尾结点,则在进行删除操作时( )。
第三章栈和队列(参考答案)// 从数据结构角度看,栈和队列是操作受限的线性结构,其顺序存储结构// 和链式存储结构的定义与线性表相同,请参考教材,这里不再重复。
3.1 1 2 3 4 2 1 3 4 3 2 1 4 4 3 2 11 2 4 3 2 1 4 3 3 2 4 11 32 4 23 14 3 4 2 11 3 42 234 11 4 32 2 43 1设入栈序列元素数为n,则可能的出栈序列数为C2n n=(1/n+1)*(2n!/(n!)2)3.2 证明:由j<k和p j<p k说明p j在p k之前出栈,即在k未进栈之前p j已出栈,之后k进栈,然后p k出栈;由j<k和p j>p k说明p j在p k之后出栈,即p j被p k压在下面,后进先出。
由以上两条,不可能存在i<j<k使p j<p k<p i。
也就是说,若有1,2,3顺序入栈,不可能有3,1,2的出栈序列。
3.3 void sympthy(linklist *head, stack *s)//判断长为n的字符串是否中心对称{ int i=1; linklist *p=head->next;while (i<=n/2) // 前一半字符进栈{ push(s,p->data); p=p->next; }if (n % 2 !==0) p=p->next;// 奇数个结点时跳过中心结点while (p && p->data==pop(s)) p=p->next;if (p==null) printf(“链表中心对称”);else printf(“链表不是中心对称”);} // 算法结束3.4int match()//从键盘读入算术表达式,本算法判断圆括号是否正确配对(init s;//初始化栈sscanf(“%c”,&ch);while (ch!=’#’) //’#’是表达式输入结束符号switch (ch){ case ’(’: push(s,ch); break;case ’)’: if (empty(s)) {printf(“括号不配对”); exit(0);}pop(s);}if (!empty(s)) printf(“括号不配对”);else printf(“括号配对”);} // 算法结束3.5typedef struct // 两栈共享一向量空间{ ElemType v[m]; // 栈可用空间0—m-1int top[2] // 栈顶指针}twostack;int push(twostack *s,int i, ElemType x)// 两栈共享向量空间,i是0或1,表示两个栈,x是进栈元素,// 本算法是入栈操作{ if (abs(s->top[0] - s->top[1])==1) return(0);// 栈满else {switch (i){case 0: s->v[++(s->top)]=x; break;case 1: s->v[--(s->top)]=x; break;default: printf(“栈编号输入错误”); return(0);}return(1); // 入栈成功}} // 算法结束ElemType pop(twostack *s,int i)// 两栈共享向量空间,i是0或1,表示两个栈,本算法是退栈操作{ ElemType x;if (i!=0 && i!=1) return(0);// 栈编号错误else {switch (i){case 0: if(s->top[0]==-1) return(0);//栈空else x=s->v[s->top--];break;case 1: if(s->top[1]==m) return(0);//栈空else x=s->v[s->top++]; break;default: printf(“栈编号输入错误”);return(0);}return(x); // 退栈成功}} // 算法结束ElemType top (twostack *s,int i)// 两栈共享向量空间,i是0或1,表示两个栈,本算法是取栈顶元素操作{ ElemType x;switch (i){case 0: if(s->top[0]==-1) return(0);//栈空else x=s->v[s->top]; break;case 1: if(s->top[1]==m) return(0);//栈空else x=s->v[s->top]; break;default: printf(“栈编号输入错误”);return(0);}return(x); // 取栈顶元素成功} // 算法结束3.6void Ackerman(int m,int n)// Ackerman 函数的递归算法{ if (m==0) return(n+1);else if (m!=0 && n==0) return(Ackerman(m-1,1);else return(Ackerman(m-1,Ackerman(m,n-1))} // 算法结束3.7(1) linklist *init(linklist *q)// q是以带头结点的循环链表表示的队列的尾指针,本算法将队列置空{ q=(linklist *)malloc(sizeof(linklist));//申请空间,不判断空间溢出q->next=q;return (q);} // 算法结束(2) linklist *enqueue(linklist *q,ElemType x)// q是以带头结点的循环链表表示的队列的尾指针,本算法将元素x入队{ s=(linklist *)malloc(sizeof(linklist));//申请空间,不判断空间溢出s->next=q->next; // 将元素结点s入队列q->next=s;q=s; // 修改队尾指针return (q);} // 算法结束(3) linklist *delqueue(linklist *q)//q是以带头结点的循环链表表示的队列的尾指针,这是出队算法{ if (q==q->next) return (null); // 判断队列是否为空else {linklist *s=q->next->next; // s指向出队元素if (s==q) q=q->next; // 若队列中只一个元素,置空队列else q->next->next=s->next;// 修改队头元素指针free (s); // 释放出队结点}return (q);} // 算法结束。
数据结构第三章习题3.1 单项选择题2.一个栈的入栈序列a, b, c, d, e, 则栈的不可能的输出序列是。
A. edcbaB. DecbaC. DceabD. abcde3. 若已知一个栈的入栈序列是1,2,3,………..n, 其输出序列为p1, p2, p3,……,pn, 若p1=n, 则pi为。
A.i.B. n=IC. n- i+1D.不确定4.栈结构通常采用的两种存储结构是。
A. 顺序存储结构和链表存储结构B. 散链方式和索引方式C.链表存储结构和数组D. 线性存储结构和非线性存储结构5.判定一个栈ST(最多元素为m0)为空的条件是。
A. ST->top<>0B. ST->top=0C.ST->top<>m0D.ST->top=m06.判定一个栈ST(最多元素为m0)为栈满的条件是。
A. ST->top!=0B.ST->top==0C.ST->top!=m0D.ST->top==m07.栈的特点是,队列的特点是。
A先进先出 B. 先进后出8. 一个队列的入栈序列是1,2,3,4,则队列的输出序列是。
A. 4,3,2,1B. 1,2,3,4C. 1,4,3,2D. 3,2,4,19. 判定一个队列QU(最多元素为m0)为空的条件是。
A.QU->rear- QU->front==m0B.QU->rear- QU->front-1==m0C.QU->front== QU->rearD. QU->front== QU->rear+110.判定一个队列QU(最多元素为m0)为满队列的条件是。
A.QU->rear- QU->front==m0B.QU->rear- QU->front-1==m0C.QU->front== QU->rearD.QU->front== QU->rear+111. 判定一个循环队列QU(最多元素为m0)为空的条件是。
A. QU->front== (QU->rear+1)%m0B. QU->front!= (QU->rear+1)%m0C.QU->front== QU->rearD.QU->front!= QU->rear12. 判定一个循环队列QU(最多元素为m0)为满队列的条件是。
A. QU->front== (QU->rear+1)%m0B. QU->front!= (QU->rear+1)%m0C.QU->front== QU->rearD.QU->front!= QU->rear+112. 向一个栈顶指针为HS的链栈中插入一个s所指结点时,则执行。
HS->next=s;A. s->next=HS->next; HS->next=s;B. s->next=HS; HS=s;C. s->next=HS; HS=HS->next;13. 从一个栈顶指针为HS的链栈中删除一个结点时,用x保存被删结点的值,则执行。
A x=HS; HS=HS->next;B. x=HS->data;C. HS=HS->next; x=HS->data;D. x=HS->data; HS=HS->next;14. 在一个链队中,假设f和r分别为队首和队尾指针,则插入s所指结点的运算时。
A. f->next=s; f=s;B. r->next=s;r=s;C. s->next=r; r=s;D. s->next=f; f=s;15. 在一个链队中,假设f和r分别为队首和队尾指针,则删除一个结点的运算时。
A. r=f->next;B. r=r->next;C. f=f->next;D. f=r-next;3.2 填空题4.向栈中压入元素的操作是5.对栈进行退栈的操作是6.在一个循环队列中,队首指针指向队首元素的7.从循环队列中删除一个元素时,其操作是8.在具有个单元的循环队列中,队满时共有个元素9. 在栈顶指针为HS的链栈中,判定栈空的条件是。
10. 在栈顶指针为HS的链栈中,计算该链站中结点个数的函数时。
11. 在HQ的链队中,判定只有一个结点的条件是。
12. 在HQ的链队中,计算该链队中结点个数的函数是。
3.3 顺序栈习题解析1. 对于一个栈,给出输入项A,B,C. 如果输入项序列由A,B,C所组成,是给出全部可能的输出序列。
解:本题利用栈的“后进先出”的特点,有如下几种情况:A进A出B进B出C进C出产生输出序列ABCA进A出B进C进C出B出产生输出序列ACBA进B进B出A出C进C出产生输出序列BACA进B进B出C进C出A出产生输出序列BCAA进B进C进C出B出A出产生输出序列CBA不可能产生的输出序列CAB2.有两个栈s1和s2共享存储空间c[1,m], 其中一个栈底设在c[1]处,另一个栈底设在c[m0]处,分别编写s1和s2的进栈push( i,x)、退栈pop(i)和设置栈空setnull(i)的函数,其中i=1,2。
注意:仅当整个空间c[1,m0]占满时才产生上溢。
解:该共享栈的结构如图2.3所示,两栈的最多元素个数为m0, top1是栈1的栈指针,top2 是栈2的栈指针,当top2=top1+1时出现上溢出,当top1=0时栈1出现下溢出,当top2=m0+1时栈2出现下溢出。
根据上述原理得到如下函数:top1 top2c的元素序号1 2 ……..n ……..m0-1 m0a1 a2 …… a n ………. bm ………b2 b1栈1底栈1顶栈2顶栈2底图2.3 共享栈/*top1,top2 和m0均为已赋初值的int型全局变量*/void push(x,i)int x,I{if (top1==top2-1) printf(“上溢出!\n”);elseif(i==1)/*对第一个栈进行入栈操作*/{top1++; c[top1]=x;}else /*对第二个栈进行入栈操作*/{top2--; c[top2]=x;}}/*函数pop*/void pop(i)int i ;{if (i ==1 )/*对第一个栈进行出栈操作*/if(top1==0)printf(“栈1下溢出!\n”);else{pop=c[top1]; top1--;}else /*对第二个栈进行出栈操作*/if (top2==m0+1) printf(“栈2下溢出!\n”);else{pop=c[top2];top2++;}}/*函数setnull*/setnull(i)int i ;{if(i ==1 )top1=0;else top2=m0+1;}4.证明:有可能从初始输入序列1,2,…….n, 利用一个栈得到输出序列p1,p2,…..,pn(p1,p2……pn是1,2,…..n 的一种排列)的充分必要条件是:不存在这样的i , j, k, 满足i <j<k同时pj<pk<pi.证明:【充分条件】如果不存在这样的i ,j,k 满足i<j<k同时pj<pk<pi, 即对于输入序列:…,pj… pk,…pi,…,(pj<pk<pi)不存在这样的输出序列:…,pi… pj,…pk,…,(或简单地对于输入序列1,2,3不存在输出序列3,1,2)从中看到,pi?后进先出,是满足栈的特点,因为pi最大也就是在pj和pk之后进入,却在输出序列中排在pj和pk之前,同时也说明, 在pk之前先进入的pj不可能在pk之后出来,反过来说明满足先进后出的特点,所以构成一个栈。
【必要条件】如果初始输入序列是1,2,…,n,假设是进栈,又同时存在i ,j,k满足i<j<k同时pj<pk<pi,即对于输入序列:…,pj… pk,…pi,…,(pj<pk<pi)存在这样的输出序列:…,pi… pj,…pk,…,从中看到,pi?先进后出,是满足栈的特点,因为pi最大也就是在pj和pk之后进入,同时看到在pk之前先进入的pj却在pk之前出来,反过来说明不满足先进后出的特点,与前面的假设是栈不一致,本题即证。
6. 已知两个整数集合A和B,它们的元素分别依元素值递增有序存放在两个单链表HA 和HB中,编写一个函数求出这两个集合的并集C,并要求表示集合C的链表的结点仍依元素值递增有序存放。
解:假设HA和HB的头指针分别为ha和hb,先设置一个空的循环单链表HC,头指针为hc,之后依次比较HA和HB的当前结点的元素值,将较小元素值的结点复制一个并链接到HC的末尾,若相等,则将其中之一复制一个并链接到HC的末尾。
当HA或HB为空后,把另一个链表的余下结点都复制并链接到HC的末尾。
实现本题功能的函数如下:void union(ha,hb,hc)node *ha,*hb,*hc;{node *p,*q,*r,*s;hc={node *}malloc(sizeof(node));/*建立一个头结点,r总是指向HC链表的最后一个结点*/r=hc;p=ha;q=hb;while(p!=NULL&&q!=NULL){if (p->data<q->data){s=(node*)malloc(sizeof(node));s->data=p->data;r->next=s;r=s;p=p->next;}else if (p->data>q->data){s=(node*)malloc(sizeof(node));s->data=q->data;r->next=s;r=s;q=q->next;}else /*p->data==q->data的情况/{s={node*}malloc(sizeof(node));q=q->next;}}if(p==NULL)/* 把q及之后的结点复制到HC中*/while (q!=NULL){s=(node*)malloc(sizeof(node));s->data=p->data;r->next=s;r=s;p=p->next;}r->next=NULL;s=hc;hc=hc->next;free(s); /*删除头结点*/}15. 假设在长度大于1的循环单链表中,既无头结点也无头指针,p为指向该链表中某个结点的指针,编写一个函数删除该结点的前驱结点。