1、34大数据结构作业第三章3.5 假设以S和X分别表示入栈和出栈的操作,则初态和终态均为空栈的入栈和出栈的操作序列可以表示为仅由S和X组成的序列。称可以操作的序列为合法序列(例如,SXSX为合法序列,SXXS为非法序列)。试给出区分给定序列为合法序列或非法序列的一般准则,并证明:两个不同的合法(栈操作)序列(对同一输入序列)不可能得到相同的输出元素(注意:在此指的是元素实体,而不是值)序列。解:一般准则:任何前n个序列中S的个数一定大于或等于X的个数且整个序列中S的个数一定等于X的个数。证明:设两个合法序列为:T1=SXS T2=SXX 假定前n个操作都相同,从第n+1个操作开始,为序列不同的起
2、始操作点。由于前n个操作相同,故此时两个栈(不妨为栈A、B)的存储情况完全相同,假设此时栈顶元素均为a。第n+1个操作不同,不妨T1的第n+1个操作为S,T2的第n+1个操作为X。T1为入栈操作,假设将b压栈,则T1的输出顺序一定是先b后a;而T2将a退栈,则其输出顺序一定是先a后b。由于T1的输出为ba,而T2的输出顺序为ab,说明两个不同的合法栈操作序列的输出元素的序列一定不同。3.9 试将下列递推过程改写为递归过程。void ditui(int n) int i; i = n; while(i1) coutx; if(x=0) sum=0; else test(sum); sum+=x;
3、 coutsum; 解:void test(int & sum) sqstack s; int x; scanf(%d,&x); initstack(s); while(x!=0) *s.front+=x; scanf(%d,&x); sum=0; int e; printf(%d,sum); while(s.front!=s.base) e=*(-s.front); sum+=e; printf(%d,sum); 3.15 假设以顺序存储结构实现一个双向栈,即在一维数组的存储空间中存在着两个栈,它们的栈底分别设在数组的两个端点。试编写实现这个双向栈tws的三个操作:初始化inistack(t
4、ws)、入栈push(tws,i,x)和出栈pop(tws,i)的算法,其中i为0或1,用以分别指示设在数组两端的两个栈,并讨论按过程(正/误状态变量可设为变参)或函数设计这些操作算法各有什么有缺点。解:程序源代码:#include#include#define STACK_INIT_SIZE 100#define TURE 1#define FALSE 0#define ok 1#define error 0#define INFEASIBLE -1typedef int selemtype ;typedef int status;typedef struct int * base2; se
5、lemtype * top2; int stacksize;sqstack;status INITstack(sqstack * s) int * p; p=(selemtype *) malloc (STACK_INIT_SIZE * sizeof(selemtype); (*s).base0=(*s).top0=p; (*s).base1=(*s).top1=p+STACK_INIT_SIZE-1; if(!(*s).base0) exit(-2); if(!(*s).base1) exit(-2); return ok;status Push(sqstack * s,int i,sele
6、mtype e) if(i=0) if (*s).top0=(*s).base0+(STACK_INIT_SIZE/2)-1) return error; else *(*s).top0+=e; return ok; if(i=1) if(*s).top1=(*s).base1-(STACK_INIT_SIZE/2)+1) return error; else *(*s).top1-=e; return ok; return error;status Pop(sqstack * s,int i,selemtype * e) if(i=0&(*s).top0=(*s).base0) return
7、 error; if(i=1&(*s).top1=(*s).base1) return error; if(i=0) *e=*(-(*s).top0); return ok; if(i=1) *e=*(-(*s).top1); return ok; void main() sqstack sta; selemtype e; selemtype * p; int i; if(INITstack(& sta) printf(双栈已被创建n); printf(请输入进栈端(0/1)及进栈元素:n); scanf(%d %d,&i,&e); if(Push(&sta,i,e) printf(元素已入栈
8、n); printf(请输入进栈端(0/1)及进栈元素:n); scanf(%d %d,&i,&e); if(Push(&sta,i,e) printf(元素已入栈n); printf(请输入进栈端(0/1)及进栈元素:n); scanf(%d %d,&i,&e); if(Push(&sta,i,e) printf(元素已入栈n); printf(左端栈元素:); p=sta.base0; while(sta.top0!=p) printf(%d ,*p); p+; printf(右端栈元素:); p=sta.base1; while(sta.top1!=p) printf(%d ,*p);
9、p-; printf(n请输入出栈端(0/1):n); scanf(%d,&i); if(Pop(&sta,i,&e) printf(n栈顶元素 %d 出栈n,e); printf(左端栈元素:); p=sta.base0; while(sta.top0!=p) printf(%d ,*p); p+; printf(右端栈元素:); p=sta.base1; while(sta.top1!=p) printf(%d ,*p); p-; 运行结果:3.21 假设表达式有单字母变量和双目四则运算符构成。试写一个算法,将一个通常书写形式且书写正确的表达式转换为逆波兰表达式。解:程序源代码:#incl
10、ude#include#define SIZE 100typedef char selemtype ;typedef struct selemtype * base; selemtype * top; int size; stack;int Prior(char c1,char c2) char ch5=#+-*/; int i=0,j=0; if(c1=() return 0; while(chi & chi!=c1) i+; if(i=2) i-; / 加和减可认为是同级别的运算符 if(i=4) i-; / 乘和除可认为是同级别的运算符 while(chj & chj!=c2) j+;
11、if(j=2) j-; if(j=4) j-; if(ij) return 1; else return 0;void main() stack sta; char ch=0,ct; sta.base=(selemtype *)malloc(SIZE*sizeof(selemtype); if(!sta.base ) exit(0); sta.top=sta.base; sta.size=0; *sta.top+=#; printf(please enter the expression:n); while(ch!=#&*sta.base=#) ch=getchar(); if(a=ch&ch
12、=z) printf( %c ,ch); else if(ch=#) ct=*(-sta.top); while(ct!=#) printf( %c ,ct); ct=*(-sta.top); -sta.top; else if(ch=() *sta.top+=ch; else if(ch=) ct=*(-sta.top); while(ct!=() printf( %c ,ct); ct=*(-sta.top); else ct=*(sta.top-1); if(Prior(ct,ch)=0) *sta.top+=ch; else ct=*(-sta.top); while(Prior(ct
13、,ch) printf( %c ,ct); ct=*(-sta.top); *(+sta.top)=ch; +sta.top; 运行结果:3.22 如题3.21的假设条件,试写一个算法,对以逆波兰式表示的表达式求值。解:程序源代码:#include#include#define max_size_stack 100#define incre 10#define ok 1#define error -100typedef int elemtype2;typedef int status;typedef struct elemtype2 * top; elemtype2 * base; int s
14、ize;stack2;status initstack2(stack2 & da) da.base=(elemtype2*)malloc(max_size_stack*sizeof(elemtype2); if(!da.base) cout操作失败,程序执行无效!=da.size) da.base=(elemtype2 *)realloc(da.base,(da.size+incre)*sizeof(elemtype2); if(!da.base) cout操作失败,程序执行无效!endl; da.top=da.base+da.size; da.size+=incre; *da.top+=e;
15、 return ok;int coun(elemtype2 e1,elemtype2 e2,char cch) switch(cch) case +: return e1+e2; case -: return e1-e2; case *: return e1*e2; case /: if(e2=0) return error;else return e1/e2; case #: return ok;break; default: return error; void main() char cch; int i,count=0,e1,e2; stack2 da; initstack2(da);
16、 cout请输入表达式的逆波兰式:(#表结束)endl; for(cch=1,i=0;cch!=#&icch; if(cch!=+&cch!=-&cch!=*&cch!=/&cch!=#) push2(da,cch-48); else if(cch!=#) pop2(da,e2);pop2(da,e1); if(coun(e1,e2,cch)=-100) cout表达是不合法:endl; cout操作失败,程序执行无效!endl; else push2(da,coun(e1,e2,cch); else pop2(da,e1); cout表达式的值为:e1endl; 运行结果:3.14 若以12
17、34作为双端队列的输入序列,试分别求出满足以下条件的输出序列: (1) 能由输入受限的双端队列得到,但不能由输出受限的双端队列得到的输出序列。 (2) 能由输出受限的双端队列得到,但不能由输入受限的双端队列得到的输出序列。(3) 既不能由输入受限的双端队列得到,也不能由输出受限的双端队列得到的输出序列。解:1,2,3,4输入受限12344和2不可相连1,2,3,4输出受限121和2不可分开4在1,3或2,3之间由上分析可知:输出受限不可得到:1243,3412,1342,1432,3142,4132,1324,1423,2143,3421,2341,2431,3241,4231,2314,24
18、13输入受限不可得到:1243,3241,1423,34213.29 如果希望循环队列中的元素都能得到利用,则需设置一个标志域tag,并以tag的值为0和1来区分,尾指针和头指针值相同时的队列状态是“空”还是“满”。试编写与此结构相应的入队列和出队列的算法,并从时间和空间角度讨论设标志和不设标志这两种方法的使用范围(如当循环队列容量较小而队列中每个元素占的空间较多时,哪一种方法较好)。解:程序源代码:#include#include #define maxqsize 5#define ok 1#define error 0typedef int qelemtype;typedef int st
19、atus;typedef struct qelemtype * base; int front; int rear; int tag;squeue;status initqueue(squeue & sq) sq.base=(qelemtype*)malloc(maxqsize*sizeof(qelemtype); if(!sq.base) exit(-2); sq.front=sq.rear=0; sq.tag=0; return ok;status enqueue(squeue & sq,qelemtype e) if(sq.rear=sq.front&sq.tag) return err
20、or; sq.basesq.rear=e; sq.rear=(sq.rear+1)%maxqsize; if(sq.rear=sq.front) sq.tag=1; return ok;status dequeue(squeue & sq,qelemtype & e) if(sq.rear=sq.front&!sq.tag) return error; e=sq.basesq.front; sq.front=(sq.front+1)%maxqsize; if(sq.tag=1) sq.tag=0; return ok;void main() squeue sq; qelemtype e; in
21、t i; initqueue(sq); cout请输入队列元素:e; if(enqueue(sq,e) cout元素已插入endl; cout请输入队列元素:e; if(enqueue(sq,e) cout元素已插入endl; cout请输入队列元素:e; if(enqueue(sq,e) cout元素已插入endl; if(dequeue(sq,e) cout队头元素:e已删除endl; cout队列中元素为:endl; for(;dequeue(sq,e);) coute ; coutendl;运行结果:3.30 假设将循环队列定义为:以域变量rear和length分别指示循环队列中队尾元
22、素的位置和内含元素的个数。试给出此循环队列的队满条件,并写出相应的入队列和出队列的算法(在出队列的算法中要返回队头元素)。解:程序源代码:#include#include#define max 3#define ok 1#define error 0typedef int status;typedef int selemtype;typedef struct selemtype * base; int rear; int length;squeue;status initqueue(squeue & sq) sq.base=(selemtype *)malloc(max*sizeof(sele
23、mtype); if(!sq.base) exit(-2); sq.rear=0; sq.length=0; return ok;status enqueue(squeue & sq,selemtype e) if(sq.length=max) return error; sq.basesq.rear=e; sq.rear=(sq.rear+1)%max; sq.length+; return ok;status dequeue(squeue & sq,selemtype & e) if(sq.length=0) return error; e=sq.base(sq.rear+max-sq.l
24、ength)%max; sq.length-; return ok;void main() squeue sq; selemtype e; initqueue(sq); cout请输入队列元素:e; if(enqueue(sq,e) cout元素已插入endl; else cout队列已满元素未被插入endl; cout请输入队列元素:e; if(enqueue(sq,e) cout元素已插入endl; else cout队列已满元素未被插入endl; cout请输入队列元素:e; if(enqueue(sq,e) cout元素已插入endl; else cout队列已满元素未被插入endl;
25、 cout请输入队列元素:e; if(enqueue(sq,e) cout元素已插入endl; else cout队列已满元素未被插入endl; if(dequeue(sq,e) cout队头元素:e已删除endl; cout队列中元素为:endl; for(;dequeue(sq,e);) coute ; coutendl;运行结果:3.31 假设称正读和反读都相同的字符序列为“回文”,例如,abba和abcba是回文,abcde和ababab则不是回文。试写一个算法判别读入的一个以为结束符的字符序列是否是“回文”。解:程序源代码:#include#include#define max 10typedef char elemtype;typedef struct elemtype * base; int front; int rear;squeue;void main() squeue sq;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1