第三章 栈与队列.docx
- 文档编号:8153100
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:10
- 大小:18.31KB
第三章 栈与队列.docx
《第三章 栈与队列.docx》由会员分享,可在线阅读,更多相关《第三章 栈与队列.docx(10页珍藏版)》请在冰豆网上搜索。
第三章栈与队列
第三章栈与队列
3.15
typedefstruct{
Elemtype*base[2];
Elemtype*top[2];
}BDStacktype;//双向栈类型
StatusInit_Stack(BDStacktype&tws,intm)//初始化一个大小为m的双向栈tws
{
tws.base[0]=(Elemtype*)malloc(sizeof(Elemtype));
tws.base[1]=tws.base[0]+m;
tws.top[0]=tws.base[0];
tws.top[1]=tws.base[1];
returnOK;
}//Init_Stack
Statuspush(BDStacktype&tws,inti,Elemtypex)//x入栈,i=0表示低端栈,i=1表示高端栈
{
if(tws.top[0]>tws.top[1])returnOVERFLOW;//注意此时的栈满条件
if(i==0)*tws.top[0]++=x;
elseif(i==1)*tws.top[1]--=x;
elsereturnERROR;
returnOK;
}//push
Statuspop(BDStacktype&tws,inti,Elemtype&x)//x出栈,i=0表示低端栈,i=1表示高端栈
{
if(i==0)
{
if(tws.top[0]==tws.base[0])returnOVERFLOW;
x=*--tws.top[0];
}
elseif(i==1)
{
if(tws.top[1]==tws.base[1])returnOVERFLOW;
x=*++tws.top[1];
}
elsereturnERROR;
returnOK;
}//pop
3.16
voidTrain_arrange(char*train)//这里用字符串train表示火车,'H'表示硬席,'S'表示软席
{
p=train;q=train;
InitStack(s);
while(*p)
{
if(*p=='H')push(s,*p);//把'H'存入栈中
else*(q++)=*p;//把'S'调到前部
p++;
}
while(!
StackEmpty(s))
{
pop(s,c);
*(q++)=c;//把'H'接在后部
}
}//Train_arrange
3.17
intIsReverse()//判断输入的字符串中'&'前和'&'后部分是否为逆串,是则返回1,否则返回0
{
InitStack(s);
while((e=getchar())!
='&')
push(s,e);
while((e=getchar())!
='@')
{
if(StackEmpty(s))return0;
pop(s,c);
if(e!
=c)return0;
}
if(!
StackEmpty(s))return0;
return1;
}//IsReverse
3.18
StatusBracket_Test(char*str)//判别表达式中小括号是否匹配
{
count=0;
for(p=str;*p;p++)
{
if(*p=='(')count++;
elseif(*p==')')count--;
if(count<0)returnERROR;
}
if(count)returnERROR;//注意括号不匹配的两种情况
returnOK;
}//Bracket_Test
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
3.20
typedefstruct{
.intx;
inty;
}coordinate;
voidRepaint_Color(intg[m][n],inti,intj,intcolor)//把点(i,j)相邻区域的颜色置换为color
{
old=g[i][j];
InitQueue(Q);
EnQueue(Q,{I,j});
while(!
QueueEmpty(Q))
{
DeQueue(Q,a);
x=a.x;y=a.y;
if(x>1)
if(g[x-1][y]==old)
{
g[x-1][y]=color;
EnQueue(Q,{x-1,y});//修改左邻点的颜色
}
if(y>1)
if(g[x][y-1]==old)
{
g[x][y-1]=color;
EnQueue(Q,{x,y-1});//修改上邻点的颜色
}
if(x if(g[x+1][y]==old) { g[x+1][y]=color; EnQueue(Q,{x+1,y});//修改右邻点的颜色 } if(y if(g[x][y+1]==old) { g[x][y+1]=color; EnQueue(Q,{x,y+1});//修改下邻点的颜色 } }//while }//Repaint_Color 分析: 本算法采用了类似于图的广度优先遍历的思想,用两个队列保存相邻同色点的横坐标和纵坐标.递归形式的算法该怎么写呢? 3.21 voidNiBoLan(char*str,char*new)//把中缀表达式str转换成逆波兰式new { p=str;q=new;//为方便起见,设str的两端都加上了优先级最低的特殊符号 InitStack(s);//s为运算符栈 while(*p) { if(*p是字母))*q++=*p;//直接输出 else { c=gettop(s); if(*p优先级比c高)push(s,*p); else { while(gettop(s)优先级不比*p低) { pop(s,c);*(q++)=c; }//while push(s,*p);//运算符在栈内遵循越往栈顶优先级越高的原则 }//else }//else p++; }//while }//NiBoLan//参见编译原理教材 3.22 intGetValue_NiBoLan(char*str)//对逆波兰式求值 { p=str;InitStack(s);//s为操作数栈 while(*p) { if(*p是数)push(s,*p); else { pop(s,a);pop(s,b); r=compute(b,*p,a);//假设compute为执行双目运算的过程 push(s,r); }//else p++; }//while pop(s,r);returnr; }//GetValue_NiBoLan 3.23 StatusNiBoLan_to_BoLan(char*str,stringtype&new)//把逆波兰表达式str转换为波兰式new { p=str;Initstack(s);//s的元素为stringtype类型 while(*p) { if(*p为字母)push(s,*p); else { if(StackEmpty(s))returnERROR; pop(s,a); if(StackEmpty(s))returnERROR; pop(s,b); c=link(link(*p,b),a); push(s,c); }//else p++; }//while pop(s,new); if(! StackEmpty(s))returnERROR; returnOK; }//NiBoLan_to_BoLan 分析: 基本思想见书后注释.本题中暂不考虑串的具体操作的实现,而将其看作一种抽象数据类型stringtype,对其可以进行连接操作: c=link(a,b). 3.24 Statusg(intm,intn,int&s)//求递归函数g的值s { if(m==0&&n>=0)s=0; elseif(m>0&&n>=0)s=n+g(m-1,2*n); elsereturnERROR; returnOK; }//g 3.25 StatusF_recursive(intn,int&s)//递归算法 { if(n<0)returnERROR; if(n==0)s=n+1; else { F_recurve(n/2,r); s=n*r; } returnOK; }//F_recursive StatusF_nonrecursive(intn,ints)//非递归算法 { if(n<0)returnERROR; if(n==0)s=n+1; else { InitStack(s);//s的元素类型为struct{inta;intb;} while(n! =0) { a=n;b=n/2; push(s,{a,b}); n=b; }//while s=1; while(! StackEmpty(s)) { pop(s,t); s*=t.a; }//while } returnOK; }//F_nonrecursive 3.26 floatSqrt_recursive(floatA,floatp,floate)//求平方根的递归算法 { if(abs(p^2-A)<=e)returnp; elsereturnsqrt_recurve(A,(p+A/p)/2,e); }//Sqrt_recurve floatSqrt_nonrecursive(floatA,floatp,floate)//求平方根的非递归算法 { while(abs(p^2-A)>=e) p=(p+A/p)/2; returnp; }//Sqrt_nonrecursive 3.27 这一题的所有算法以及栈的变化过程请参见《数据结构(pascal版)》,作者不再详细写出. 3.28 voidInitCiQueue(CiQueue&Q)//初始化循环链表表示的队列Q { Q=(CiLNode*)malloc(sizeof(CiLNode)); Q->next=Q; }//InitCiQueue voidEnCiQueue(CiQueue&Q,intx)//把元素x插入循环链表表示的队列Q,Q指向队尾元素,Q->next指向头结点,Q->next->next指向队头元素 { p=(CiLNode*)malloc(sizeof(CiLNode)); p->data=x; p->next=Q->next;//直接把p加在Q的后面 Q->next=p; Q=p; //修改尾指针 } StatusDeCiQueue(CiQueue&Q,intx)//从循环链表表示的队列Q头部删除元素x { if(Q==Q->next)returnINFEASIBLE;//队列已空 p=Q->next->next; x=p->data; Q->next->next=p->next; free(p); returnOK; }//DeCiQueue 3.29 StatusEnCyQueue(CyQueue&Q,intx)//带tag域的循环队列入队算法 { if(Q.front==Q.rear&&Q.tag==1)//tag域的值为0表示"空",1表示"满" returnOVERFLOW; Q.base[Q.rear]=x; Q.rear=(Q.rear+1)%MAXSIZE; if(Q.front==Q.rear)Q.tag=1;//队列满 }//EnCyQueue StatusDeCyQueue(CyQueue&Q,int&x)//带tag域的循环队列出队算法 { if(Q.front==Q.rear&&Q.tag==0)returnINFEASIBLE; Q.front=(Q.front+1)%MAXSIZE; x=Q.base[Q.front]; if(Q.front==Q.rear)Q.tag=1;//队列空 returnOK; }//DeCyQueue 分析: 当循环队列容量较小而队列中每个元素占的空间较多时,此种表示方法可以节约较多的存储空间,较有价值. 3.30 StatusEnCyQueue(CyQueue&Q,intx)//带length域的循环队列入队算法 { if(Q.length==MAXSIZE)returnOVERFLOW; Q.rear=(Q.rear+1)%MAXSIZE; Q.base[Q.rear]=x; Q.length++; returnOK; }//EnCyQueue StatusDeCyQueue(CyQueue&Q,int&x)//带length域的循环队列出队算法 { if(Q.length==0)returnINFEASIBLE; head=(Q.rear-Q.length+1)%MAXSIZE;//详见书后注释 x=Q.base[head]; Q.length--; }//DeCyQueue 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 3.32 voidGetFib_CyQueue(intk,intn)//求k阶斐波那契序列的前n+1项 { InitCyQueue(Q);//其MAXSIZE设置为k for(i=0;i Q.base[k-1]=1;//给前k项赋初值 for(i=0;i for(i=k;i<=n;i++) { m=i%k;sum=0; for(j=0;j Q.base[m]=sum;//求第i项的值存入队列中并取代已无用的第一项 printf("%d",sum); } }//GetFib_CyQueue 3.33 StatusEnDQueue(DQueue&Q,intx)//输出受限的双端队列的入队操作 { if((Q.rear+1)%MAXSIZE==Q.front)returnOVERFLOW;//队列满 avr=(Q.base[Q.rear-1]+Q.base[Q.front])/2; if(x>=avr)//根据x的值决定插入在队头还是队尾 { Q.base[Q.rear]=x; Q.rear=(Q.rear+1)%MAXSIZE; }//插入在队尾 else { Q.front=(Q.front-1)%MAXSIZE; Q.base[Q.front]=x; }//插入在队头 returnOK; }//EnDQueue StatusDeDQueue(DQueue&Q,int&x)//输出受限的双端队列的出队操作 { if(Q.front==Q.rear)returnINFEASIBLE;//队列空 x=Q.base[Q.front]; Q.front=(Q.front+1)%MAXSIZE; returnOK; }//DeDQueue 3.34 voidTrain_Rearrange(char*train)//这里用字符串train表示火车,'P'表示硬座,'H'表示硬卧,'S'表示软卧,最终按PSH的顺序排列 { r=train; InitDQueue(Q); while(*r) { if(*r=='P') { printf("E"); printf("D");//实际上等于不入队列,直接输出P车厢 } elseif(*r=='S') { printf("E"); EnDQueue(Q,*r,0);//0表示把S车厢从头端入队列 } else { printf("A"); EnDQueue(Q,*r,1);//1表示把H车厢从尾端入队列 } }//while while(! DQueueEmpty(Q)) { printf("D"); DeDQueue(Q); }//while//从头端出队列的车厢必然是先S后H的顺序 }//Train_Rearrange
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第三章 栈与队列 第三 队列