}
【解答】程序段的功能是实现了栈中元素的逆置。
(2) voiddemo2(SeqStackS,intm)∥设栈中元素类型为int型
{intx;SeqStackT;
StackInit(T);
while(!
StackEmpty(S))
if((x=Pop(S)!
=m)Push(T,x);
while(!
(StackEmpty(T)){x=Pop(T);Push(S,x);}
}
【解答】程序段的功能是删除了栈中值为m的元素。
(3) voiddemo3(SeQueueQ,intm)∥设队列中元素类型为int型
{intx;SeqStackS;
StackInit(S);
while(!
QueueEmpty(Q)){x=QueueOut(Q);Push(S,x);}
while(!
StackEmpty(S)){x=Pop(s);QueueIn(Q,x);}
}
【解答】程序段的功能是实现了队列中元素的逆置。
3.8 试将下列递推过程改写为递归过程。
voidditui(intn)
{i=n;
while(i>1)printf(i--);
}
【解答】voiddigui(intn)
{if(n>1){printf(n);
digui(n-1);
}
}
3.9 写出下列中缀表达式的后缀表达式:
(1)A*B*C
(2)(A+B)*C-D(3)A*B+C/(D-E)(4)(A+B)*D+E/(F+A*D)+C
【解答】
(1)ABC**
(2)AB+C*D-
(3)AB*CDE-/+
(4)AB+D*EFAD*+/+C+
3.10 选择题:
循环队列存储在数组A[0..m]中,则入队时的操作为()。
A.rear=rear+1B.rear=(rear+1)%(m-1)
C.rear=(rear+1)%mD.rear=(rear+1)%(m+1)
【解答】D
3.11选择题:
4个园盘的Hahoi塔,总的移动次数为()。
A.7B.8C.15D.16
【解答】C
3.12选择题:
允许对队列进行的操作有()。
A.对队列中的元素排序B.取出最近进队的元素
C.在队头元素之前插入元素D.删除队头元素
【解答】D
二、算法设计题
3.13利用栈的基本操作,编写求栈中元素个数的算法。
【题目分析】将栈值元素出栈,出栈时计数,直至栈空。
【算法】intStackLength(StackS)
{//求栈中元素个数
intn=0;
while(!
StackEmpty(S)
{n++;Pop(S);
}
returnn;
}
算法讨论:
若要求统计完元素个数后,不能破坏原来栈,则在计数时,将原栈导入另一临时栈,计数完毕,再将临时栈倒入原栈中。
intStackLength(StackS)
{//求栈中元素个数
intn=0;
StackT;
StackInit(T);//初始化临时栈T
while(!
StackEmpty(S)
{n++;Push(T,Pop(S));
}
while(!
StackEmpty(T)
{Push(S,Pop(T));
}
returnn;
}
3.14双向栈S是在一个数组空间V[m]内实现的两个栈,栈底分别处于数组空间的两端。
试为此双向栈设计栈初始化Init(S)、入栈Push(S,i,x)、出栈Pop(S,i)算法,其中i为0或1,用以指示栈号。
[题目分析]两栈共享向量空间,将两栈栈底设在向量两端,初始时,s1栈顶指针为-1,s2栈顶为m。
两栈顶指针相邻时为栈满。
两栈顶相向、迎面增长,栈顶指针指向栈顶元素。
#defineElemTypeint∥假设元素类型为整型
typedefstruct
{ElemTypeV[m];∥栈空间
inttop[2];∥top为两个栈顶指针
}stk;
stkS;∥S是如上定义的结构类型变量,为全局变量
(1) 栈初始化
intInit()
{S.top[0]=-1;
S.top[1]=m;
return1;//初始化成功
}
(2) 入栈操作:
intpush(stkS,inti,intx)
∥i为栈号,i=0表示左栈,i=1为右栈,x是入栈元素。
入栈成功返回1,否则返回0
{if(i<0||i>1){printf(“栈号输入不对\n”);exit(0);}
if(S.top[1]-S.top[0]==1){printf(“栈已满\n”);return(0);}
switch(i)
{case0:
S.V[++S.top[0]]=x;return
(1);break;
case1:
S.V[--S.top[1]]=x;return
(1);
}
}∥push
(3) 退栈操作
ElemTypepop(stkS,inti)
∥退栈。
i代表栈号,i=0时为左栈,i=1时为右栈。
退栈成功返回退栈元素
∥否则返回-1
{if(i<0||i>1){printf(“栈号输入错误\n”);exit(0);}
switch(i)
{case0:
if(S.top[0]==-1){printf(“栈空\n”);return(-1);}
elsereturn(S.V[S.top[0]--]);
case1:
if(S.top[1]==m{printf(“栈空\n”);return(-1);}
elsereturn(S.V[S.top[1]++]);
}∥switch}∥算法结束
(4) 判断栈空
intEmpty();
{return(S.top[0]==-1&&S.top[1]==m);
}
[算法讨论]请注意算法中两栈入栈和退栈时的栈顶指针的计算。
s1(左栈)是通常意义下的栈,而s2(右栈)入栈操作时,其栈顶指针左移(减1),退栈时,栈顶指针右移(加1)。
3.15设以数组Q[m]存放循环队列中的元素,同时设置一个标志tag,以tag=0和tag=1来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“不空”。
试编写相应的入队(QueueIn)和出队(QueueOut)算法。
(1) 初始化
SeQueueQueueInit(SeQueueQ)
{//初始化队列
Q.front=Q.rear=0;Q.tag=0;
returnQ;
}
(2)入队
SeQueueQueueIn(SeQueueQ,inte)
{//入队列
if((Q.tag==1)&&(Q.rear==Q.front))printf("队列已满\n");
else{Q.rear=(Q.rear+1)%m;
Q.data[Q.rear]=e;
if(Q.tag==0)Q.tag=1;//队列已不空
}
returnQ;
}
(3)出队
ElemTypeQueueOut(SeQueueQ)
{//出队列
if(Q.tag==0)printf("队列为空\n");
else
{Q.front=(Q.front+1)%m;
e=Q.data[Q.front];
if(Q.front==Q.rear)Q.tag=0;//空队列
}
return(e);
}
3.16假设用变量rear和length分别指示循环队列中队尾元素的位置和内含元素的个数。
试给出此循环队列的定义,并写出相应的入队(QueueIn)和出队(QueueOut)算法。
【算法设计】
(1)循环队列的定义
typedefstruct
{ElemTypeQ[m];∥循环队列占m个存储单元
intrear,length;∥rear指向队尾元素,length为元素个数
}SeQueue;
(2)初始化
SeQueueQueueInit(SeQueuecq)
∥cq为循环队列,本算法进行队列初始化
{cq.rear=0;cq.length=0;returncq;
}
(3)入队
SeQueueQueueIn(SeQueuecq,ElemTypex)
∥c