C语言程序设计-第十一章综合实训-学生成绩管理系统资料课件_第1页
C语言程序设计-第十一章综合实训-学生成绩管理系统资料课件_第2页
C语言程序设计-第十一章综合实训-学生成绩管理系统资料课件_第3页
C语言程序设计-第十一章综合实训-学生成绩管理系统资料课件_第4页
C语言程序设计-第十一章综合实训-学生成绩管理系统资料课件_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

项目十一综合实训—学生成绩管理系统1项目十一综合实训—学生成绩管理系统1【项目要求】

将从键盘输入的十进制数转换为N(如二进制、八进制、十六进制)进制数据,利用顺序栈实现数制转换问题

十进制转化成N进制的算法是//整数部分为除N取余法,小数部分为乘N取整法。例如:对1348这个数,转化为N进制,也就是解方程1348=aN^5+bN^4+cN^3+dN^2+eN^1+f,目标就是要求出系数a,b,c,d,e,f的值(也许a的前面还有w*N^6甚至7次方等等,但是次数太高的话就必然会是0),比如我们假定N=10的话,那么求出来的结果必然是a=b=0,c=1,d=3,e=4,f=8

。对于N进制来说,a,b,c,d,e,f的值都必然要小于N(否则就会向高位进一),显然求解的过程是:将1348除以10(令N=10),则余数就是f

,即8,则商则是aN^4+bN^3+cN^2+dN^1+e,这样进一步除以10得e,依次得到d,c,b,a,可用堆栈来实现。【项目分析】2【项目要求】将从键盘输入的十进制数转换为N(如二进制、八问题情境及实现

/*

堆栈的应用---进制转换

将十进制转换成其他进制

*/

#include

<stdio.h>

#define

maNlen

100

typedef

struct

//堆栈的结构大家应该都很熟悉了

{

int

data[maNlen];

int

top;

}SeqStack;

void

InitStack(SeqStack

*

S)

//置栈空

{

S->top

=

-1;

}

3问题情境及实现

/*

3问题情境及实现

void

Pop(SeqStack

*

S,

int

*

N)

//出栈,N用来接受被弹出的数的

{

*N

=

S->data[S->top];

S->top--;

}

void

Push(SeqStack

*

S,

int

N)

//入栈

{

S->top++;

S->data[S->top]

=

N;

}

void

Conversion(SeqStack

*

S,

int

n,

int

d)

//n为一个十进制数,d为进制

{

if(d

<

0)

printf("ERROR!\n");

if(n

<

0)

n

=

-n;

if(n

==

0)

Push(S,

0);

while(n)

{

Push(S,

n%d);

n

/=

d;

}

}

4问题情境及实现

4问题情境及实现

int

main()

{

int

n,d,N;

//n为一个十进制数,d为进制

SeqStack

stack,

*S;

S

=

&stack;

while(scanf("%d

%d",&n,&d)

!=

EOF)

{

InitStack(S);

//初始化

Conversion(S,

n,

d);

if(n

<

0)

printf("%c",'-');

//若是负数

while(S->top

!=

-1)

{

Pop(S,

&N);

if(N

<

10)

printf("%d",N);

else

printf("%c",N

+

55);

//使输出的时候大于9的输出为字母ABC

}

printf("\n");

}

return

0;

}

5问题情境及实现

int

main()

5相关知识1.栈2.队列本讲小结6相关知识1.栈2.队列本讲小结61栈1.1栈的定义及顺序存储1.2栈的运算1.3双栈的操作1.4栈的应用71栈1.1栈的定义及顺序存储7栈满1.1栈的定义及顺序存储1.栈的定义栈又叫堆栈,允许在表的一端进行插入和删除。后进先出的线性表(简称LIFO表)。MAN-1┇i┇210top空栈a11个元素a3a2a13个元素a3a2a12个元素an┇┇a3a2a1toptoptoptop8栈满1.1栈的定义及顺序存储1.栈的定义栈又叫堆2.栈的顺序存储

#defineMAN栈中允许存放元素的最大个数typedefstruct{datatypedata[MAN];inttop;}stack;92.栈的顺序存储#defineMAN栈中允许存放元素1.2栈的运算1.栈的基本操作⑴栈初始化:init(s)构造了一个空栈;⑵判栈空:empty(s)若栈s为空栈返回为1,否则返回为0;⑶入栈:push(s,N)在栈s的顶部插入一个新元素N,使N成为新的栈顶元素;⑷出栈:pop(s)栈s的顶部元素从栈中删除;⑸读栈顶元素:get(s)取栈顶元素作为结果返回;⑹置栈空:clear(s)清除栈s中的所有元素,使之成为空栈。101.2栈的运算1.栈的基本操作⑴栈初始化:init2.栈的基本算法的实现⑴栈的初始化voidinit(stack*s){s->top=0;}⑵判空栈intempty(stack*s){if(s->top==0)return1;elsereturn0;}112.栈的基本算法的实现⑴栈的初始化voidinit(⑶入栈voidpush(stack*s,datatypeN){if(s->top==MAN-1)printf("栈满");else{s->top++;s->data[s->top]=N;}}12⑶入栈voidpush(stack*s,data⑷出栈voidpop(stack*s,datatype*N){if(empty(s))printf("栈空");else{*N=s->data[s->top]; s->top--; }}13⑷出栈voidpop(stack*s,datatyp⑸取栈顶元素datatypeget(stack*s){if(empty(s))printf("栈空"); elsereturn(s->data[s->top]);}14⑸取栈顶元素datatypeget(stack*s1.3双栈的操作让两个栈共享一个数组的存储空间,让一个栈的栈底为该空间的始端,另一个栈的栈底为该空间的末端,当元素进栈时,都从两端向中间靠拢,这样就可以达到在使用过程中有的栈占有的空间多一些,有的栈占有的空间少一些,公共的剩余空间可以调节使用,从而提高了存储空间的利用率。123…n

mm+1…MAN-1

dataa1

a2

a3

…an

bm

…b2

b1top1top2栈2底栈1底双栈共享存储空间151.3双栈的操作让两个栈共享一个数组的存储空间,让一个栈的存储结构可定义为#defineMAN双栈中允许存放元素的最大个数typedefstruct{datatypedata[MAN];inttop1,top2;}bothstack;用bothstack可以定义一个双栈ds:bothstackds;或bothstack*ds;16存储结构可定义为#defineMAN双栈中允许存放元素的1.进栈voidpush(bothstack*ds,datatypeN){if(ds->top2==ds->top1+1)printf("栈满");else{ds->top2--;ds->data[ds->top2]=N;}}171.进栈voidpush(bothstack*ds2.出栈voidpop(bothstack*ds,datatype*N){if(ds->top2==MAN) printf("栈空"); else{*N=ds->data[ds->top2];ds->top2++; }}182.出栈voidpop(bothstack*ds,d1.4栈的应用算法思路:把十进制数转换为二进制数采用的方法是“除2取余”,直到商为0。依次得到的余数是k1,k2,k3,……,km,而转换后的二进制数是kmkm-1…k3k2k1,从结果看恰好与计算过程相反,因此转换过程中每得到一位二进制数则进栈保存,转换完毕后依次出栈则正好是转换结果。此种方法同样适用于将十进制数转换为r进制的数。把十进制整数11转换为二进制的过程如下:211余数二进制位

低高

25

1k1

22

1k2

21

0k30

1k4例2-3编写一个算法将给定的十进制数转换为二进制数输出。191.4栈的应用算法思路:把十进制数转换为二进制数采用的方法数值转换的算法typedefintdatatype;#defineMAN10voidtransfer(intn,intr)voidtransfer(intn,intr){stacks;{ints[MAN],top;/*定义一个顺序栈*/datatypeN;intN;init(s); top=0;/*初始化栈*/while(n) while(n){push(s,n%r); {s[++top]=n%r;/*余数入栈*/n=n/r; n=n/r;/*商作为被除数继续*/} }while(!empty(s))while(top!=0){pop(s,N); {N=s[top--];printf("%d",N); printf("%d",N);} }} }

算法一算法二20数值转换的算法typedefintdatatype;例2-4栈与递归

下面以n!为例,介绍如何将递归的算法改写为堆栈的非递归算法。n!=1

n==0或n==1/*递归终止条件*/n*(n-1)! n>0/*递归步骤*/intfact(intn){if(n==0||n==1)return1;elsereturn(n*fact(n-1));}21例2-4栈与递归下面以n!为例,介绍如何将递归的算法程序的执行过程图示fact(3)n=3f=3*fact(2)returnff=3*2*1*1n=2f=2*fact(1)returnff=2*1*1n=1f=1*fact(0)returnff=1*1n=0f=1returnff=1intfact(intn){if(n==0||n==1)return1;elsereturn(n*fact(n-1));}22程序的执行过程图示fact(3)n=3f=3*fact(2)阶乘的堆栈算法(非递归)typedefintdatatype;#defineMAN20intfact(intn) intfact(intn){stacks;datatypeN;intm=1;{ints[MAN],top=0,N,m=1;init(s); if(n==0||n==1)m=1;if(n==0||n==1)m=1;else{while(n>1)else{while(n>1) {s[++top]=n; {push(s,n);n--; n--; } }while(!empty(s))while(top!=0) {pop(s,N); {N=s[top--];m=m*N; m=m*N; } }} }returnm; returnm;} }算法一 算法二23阶乘的堆栈算法(非递归)typedefintdataty例2-5算术表达式的求值1.算术表达式的两种表示方法⑴中缀表达式所谓中缀表达式就是把运算符放在两个运算对象之间的表达式。如3+5*3。实际中缀表达式就是经常习惯使用的算术表达式。①有括号出现时先算括号内的,后算括号外的,多层括号,由内向外进行;②在无括号或同层括号内的情况下,先做乘除运算,S后做加减运算;③同一优先级运算,从左向右依次进行。24例2-5算术表达式的求值1.算术表达式的两种表示方法⑵后缀表达式所谓后缀表达式就是把运算符放在两个运算对象之后的表达式。如3+5*3的后缀表达式是353*+其中运算对象和运算符之间用空格隔开。在后缀表达式中,不再引入括号,所有的计算按运算符出现的顺序,严格从左向右进行,即遇到运算符就将运算符前的两个运算对象进行计算,而不用再考虑运算规则和级别。所以计算机扫描一次就能完成运算。把中缀表达式转换成对应的后缀表达式的规则是:把每个运算符都移到他的两个运算对象的后面,然后删掉所有的括号即可。25⑵后缀表达式所谓后缀表达式就是把运算符放在两个运算对象之例如:对下列各中缀表达式①5/2-7②15+6*(2+4)③3*(N+y)/(2-y)④(25+N)*(a*(a+b)+b)对应的后缀表达式分别为①52/7-②15624+*+③3Ny+*2y-/④25N+aab+*b+*26例如:对下列各中缀表达式262.中缀表达式转换成后缀表达式在将中缀表达式转化为后缀表达示的算法中,为了讨论方便我们设表达式中的运算对象只有一位数字,并将中缀表达式保存在字符数组a中,转换后的后缀表达式存储在字符数组b中,用一个字符数组s作为栈,设字符'='为表达式的结束符。算法思路如下:272.中缀表达式转换成后缀表达式在将中缀表达式转化为后缀表达先将输入的中缀表达式,存入字符数组a中,取出a数组中的每一个字符存于c变量中,对于每一个c变量的值做如下处理:①若c为数字,则存于数组b中;②若c为左括号'(',则将其压入栈s;③若c为右括号‘)’,则将栈s中左括号‘(’以后的运算符依次出栈,存于数组b中,然后将左括号'('出栈;④若c为‘+’或‘-’,则将栈s中左括号‘(’以后的所有运算符依次出栈,存于数组b中,然后将c压入栈s中;⑤若c为'*'或'/',则将栈s中的栈顶端连续的'*'或'/'出栈,存于数组b中,然后将c压入栈s中⑥若c为'=',则将栈S中的所有运算符依次出栈,存于数组b中,然后将c存于数组b中,最后得到的后缀表达式存储在字符数组b中。28先将输入的中缀表达式,存入字符数组a中,取出a数组中的每一个中缀转后缀的算法如下所示:#defineMAN50Voidtrans(){chara[MAN],b[MAN],s[MAN],c;inti=0,j,t=1,top=0;do{i++;scanf("%c",&a[i]);}while(a[i]!='='&&i<MAN);i=1;c=a[i];i++;while(c!='='){if(c>='0'&&c<='9'){b[t]=c;t++;}elseif(c=='('){top++;s[top]=c;}elseif(c==')'){while(s[top]!='('){b[t]=s[top];top--;t++}top--;}

elseif(c=='+'||c=='-'){while(top!=0&&s[top]!='('){b[t]=s[top];top--;t++;}top++;s[top]=c;}elseif(c=='*'||c=='/'){while(s[top]!='*'||s[top]!='/'){b[t]=s[top];top--;t++;}top++;s[top]=c;}c=a[i];i++;}while(top!=0){b[t]=s[top];t++;top--;}b[t]='=';

for(j=1;j<t;j++)printf("%c",b[j]);printf("\n");}29中缀转后缀的算法如下所示:elseif(c=='+以中缀表达式2*(1+2)/2为例,其转换过程如图所示。其中a数组存放的是中缀表达式2*(1+2)/2=,b数组存放的是转换后的后缀表达式212+*2/=,s数组作为栈,暂存运算符。12345678910…a数组2*(1+2)/2=12345678910…b数组212+*2/=**(*(+/s栈30以中缀表达式2*(1+2)/2为例,其转换过程如图所示。其中3.后缀表达式求值后缀表达式值的计算是比较简单的,这是因为表达式中即无括号又无优先级的约束。具体做法:需要一个存放数值的栈s1,当从左向右扫描表达式时,每遇到一个操作数就送入栈中保存,每遇到一个运算符就从栈中取出两个操作数进行当前的计算,然后把结果再入栈,直到整个表达式结束,这时栈顶存放的值就是后缀表达式的结果。下面是后缀表达式求值的算法,在下面的算法中假设后缀表达式已被存入一个字符数组b中,且以'='为结束字符,为了简化问题,限定运算数的位数仅为一位。313.后缀表达式求值后缀表达式值的计算是比较简单的,这是因为后缀表达式求值算法:#defineMAN50floatcalcul(char*b){floats1[MAN],d;charc;inti=0,t=0,top=0;c=*b++;while(c!='='){d=c-'0';if(c>='0'&&c<='9'){top++;s1[top]=d;}else{switch(c){case'+':s1[top-1]=s1[top-1]+s1[top]:break;

case'-':s1[top-1]=s1[top-1]-s1[top];break;case'*':s1[top-1]=s1[top-1]*s1[top];break;case'/':s1[top-1]=s1[top-1]/s1[top];break;}top--;}c=*b++;}returns1[top];}32后缀表达式求值算法:#defineMAN5032

仍以中缀表达式2*(1+2)/2为例,他的后缀表达式存放在b数组中。后缀表达式212+*2/=的求值过程如下所示。222进栈1211入栈22122入栈+231和2出栈,计算1+2,并将结果3入栈*62和3出栈,计算2*3,并将结果6入栈2622入栈/32和6出栈,计算6/2,并将结果3入栈=空结果3出栈33仍以中缀表达式2*(1+2)/2为例,他的后缀表达式存放2队列2.1队列的定义及顺序存储2.2队列的运算2.3循环队列342队列2.1队列的定义及顺序存储342.1队列的定义及顺序存储1.队列的定义队列(queue)简称队。仅允许在表的一端进行插入,而在表的另一端进行删除。把允许插入的一端叫队尾(rear),把允许删除的一端叫队首(front)。出队a1a2a3a4a5入队向队列中插入新元素称作进队或入队,新元素进队后就成为新的队尾元素;从队列中删除元素称作出队,出队后,其后继元素成为队首元素。由于队列的插入和删除分别在两端进行,所以要删除的元素是队列中最先进入的元素,因此又把队列称作先进先出(FirstInFirstOut,简称FIFO)表。352.1队列的定义及顺序存储1.队列的定义队列(que2.队列的顺序存储类型定义如下:#defineMAN队列的最大容量typedefstruct{datatypedata[MAN];intf,r;}queue;362.队列的顺序存储类型定义如下:36队列的队首、队尾指针与队中数据元素的关系

012345678…MAN-1fr012345678…MAN-1a1

a2

a3

fr空队列f==r==0

3个元素

f==1,r==30123456789MAN-1a1

a2

a3

a4a5a6a7a8a9fr7个元素f==3,r==90123456789MAN-1a1

a2

a3

a4a5a6a7a8a9anfr

n-2个元素(队满)f==3,r==n37队列的队首、队尾指针与队中数据元素的关系0123456782.2队列的运算1.队列的基本操作⑴队列初始化:init(q)构造了一个空队;⑵入队操作:insert(q,N)在队列q中插入一个元素N到队尾;⑶出队操作:delete(q,N)删除队首元素,可以返回其值;⑷读队头元素:get(q,N)取队头元素作为结果返回;⑸判队空操作:empty(q)若q为空队则返回为1,否则返回为0;⑹置队空:clear(q)清除队列q中的所有元素,使之成为空队列。382.2队列的运算1.队列的基本操作⑴2.队列的基本算法的实现⑴队列的初始化voidinit(queue*q){q->f=q->r=0;}⑵判空队列intempty(queue*q){if(q->f==0&&q->r=0)return1;elsereturn0;}392.队列的基本算法的实现⑴队列的初始化voidini⑶入队入队时,首先判队是否满了,队满的条件为:q->r==MAN-1,队满时,不能入队,可以进行溢出错误处理,若可以入队则先将队尾指针后移(q->r++),再将元素赋给队尾单元。voidinsert(queue*q,datatypeN){if(q->r==MAN-1)printf("队满");else{if(q->f==0&&q->r==0)q->f=++q->r;elseq->r++;q->data[q->r]=N;}}40⑶入队入队时,首先判队是否满了,队满的条件为:q->r⑷出队列先判队列是否为空,为空时不能出队,若可以出队,则可先将队首元素赋给指定变量(若不需要保留,可以省去这一步),队首指针后移(q->f--)。voiddelete(queue*q,datatype*N){if(empty(q))printf("队空");else{*N=q->data[q->f];if(q->f==q->r)q->f=q->r=0;elseq->f++; }}41⑷出队列先判队列是否为空,为空时不能出队,若可以出队,则⑸取队首元素先判队列是否为空,为空时不能取元素,否则取出队首元素,但队首指针保持不变。datatypeget(queue*q){if(empty(q))printf("队空"); elsereturn(q->data[q->f]);}42⑸取队首元素先判队列是否为空,为空时不能取元素,否则取出rf01a9a8a7a6a5…2.3循环队列将队列的数据区data[1]至data[MAN]看成头尾相接的循环结构,头尾指针的关系不变,将其称为循环队列.43rf01a9a8a7a6a5…2.3循环队列将队列的数据⑴入队voidinsert(queue*q,datatypeN){if((q->r%(MAN-1)+1==q->f)printf("队满");else{q->r=q->r%(MAN-1)+1;q->data[q->r]=N;}}44⑴入队voidinsert(queue*q,d⑵出队voiddelete(queue*q,datatype*N){if(q->r==0&&q->f==0))printf("队空"); else{*N=q->data[q->f];if(q->f==q->r) q->f=q->r=0; elseq->f=q->f%(MAN-1)+1; }}45⑵出队voiddelete(queue*q,da项目十一综合实训—学生成绩管理系统46项目十一综合实训—学生成绩管理系统1【项目要求】

将从键盘输入的十进制数转换为N(如二进制、八进制、十六进制)进制数据,利用顺序栈实现数制转换问题

十进制转化成N进制的算法是//整数部分为除N取余法,小数部分为乘N取整法。例如:对1348这个数,转化为N进制,也就是解方程1348=aN^5+bN^4+cN^3+dN^2+eN^1+f,目标就是要求出系数a,b,c,d,e,f的值(也许a的前面还有w*N^6甚至7次方等等,但是次数太高的话就必然会是0),比如我们假定N=10的话,那么求出来的结果必然是a=b=0,c=1,d=3,e=4,f=8

。对于N进制来说,a,b,c,d,e,f的值都必然要小于N(否则就会向高位进一),显然求解的过程是:将1348除以10(令N=10),则余数就是f

,即8,则商则是aN^4+bN^3+cN^2+dN^1+e,这样进一步除以10得e,依次得到d,c,b,a,可用堆栈来实现。【项目分析】47【项目要求】将从键盘输入的十进制数转换为N(如二进制、八问题情境及实现

/*

堆栈的应用---进制转换

将十进制转换成其他进制

*/

#include

<stdio.h>

#define

maNlen

100

typedef

struct

//堆栈的结构大家应该都很熟悉了

{

int

data[maNlen];

int

top;

}SeqStack;

void

InitStack(SeqStack

*

S)

//置栈空

{

S->top

=

-1;

}

48问题情境及实现

/*

3问题情境及实现

void

Pop(SeqStack

*

S,

int

*

N)

//出栈,N用来接受被弹出的数的

{

*N

=

S->data[S->top];

S->top--;

}

void

Push(SeqStack

*

S,

int

N)

//入栈

{

S->top++;

S->data[S->top]

=

N;

}

void

Conversion(SeqStack

*

S,

int

n,

int

d)

//n为一个十进制数,d为进制

{

if(d

<

0)

printf("ERROR!\n");

if(n

<

0)

n

=

-n;

if(n

==

0)

Push(S,

0);

while(n)

{

Push(S,

n%d);

n

/=

d;

}

}

49问题情境及实现

4问题情境及实现

int

main()

{

int

n,d,N;

//n为一个十进制数,d为进制

SeqStack

stack,

*S;

S

=

&stack;

while(scanf("%d

%d",&n,&d)

!=

EOF)

{

InitStack(S);

//初始化

Conversion(S,

n,

d);

if(n

<

0)

printf("%c",'-');

//若是负数

while(S->top

!=

-1)

{

Pop(S,

&N);

if(N

<

10)

printf("%d",N);

else

printf("%c",N

+

55);

//使输出的时候大于9的输出为字母ABC

}

printf("\n");

}

return

0;

}

50问题情境及实现

int

main()

5相关知识1.栈2.队列本讲小结51相关知识1.栈2.队列本讲小结61栈1.1栈的定义及顺序存储1.2栈的运算1.3双栈的操作1.4栈的应用521栈1.1栈的定义及顺序存储7栈满1.1栈的定义及顺序存储1.栈的定义栈又叫堆栈,允许在表的一端进行插入和删除。后进先出的线性表(简称LIFO表)。MAN-1┇i┇210top空栈a11个元素a3a2a13个元素a3a2a12个元素an┇┇a3a2a1toptoptoptop53栈满1.1栈的定义及顺序存储1.栈的定义栈又叫堆2.栈的顺序存储

#defineMAN栈中允许存放元素的最大个数typedefstruct{datatypedata[MAN];inttop;}stack;542.栈的顺序存储#defineMAN栈中允许存放元素1.2栈的运算1.栈的基本操作⑴栈初始化:init(s)构造了一个空栈;⑵判栈空:empty(s)若栈s为空栈返回为1,否则返回为0;⑶入栈:push(s,N)在栈s的顶部插入一个新元素N,使N成为新的栈顶元素;⑷出栈:pop(s)栈s的顶部元素从栈中删除;⑸读栈顶元素:get(s)取栈顶元素作为结果返回;⑹置栈空:clear(s)清除栈s中的所有元素,使之成为空栈。551.2栈的运算1.栈的基本操作⑴栈初始化:init2.栈的基本算法的实现⑴栈的初始化voidinit(stack*s){s->top=0;}⑵判空栈intempty(stack*s){if(s->top==0)return1;elsereturn0;}562.栈的基本算法的实现⑴栈的初始化voidinit(⑶入栈voidpush(stack*s,datatypeN){if(s->top==MAN-1)printf("栈满");else{s->top++;s->data[s->top]=N;}}57⑶入栈voidpush(stack*s,data⑷出栈voidpop(stack*s,datatype*N){if(empty(s))printf("栈空");else{*N=s->data[s->top]; s->top--; }}58⑷出栈voidpop(stack*s,datatyp⑸取栈顶元素datatypeget(stack*s){if(empty(s))printf("栈空"); elsereturn(s->data[s->top]);}59⑸取栈顶元素datatypeget(stack*s1.3双栈的操作让两个栈共享一个数组的存储空间,让一个栈的栈底为该空间的始端,另一个栈的栈底为该空间的末端,当元素进栈时,都从两端向中间靠拢,这样就可以达到在使用过程中有的栈占有的空间多一些,有的栈占有的空间少一些,公共的剩余空间可以调节使用,从而提高了存储空间的利用率。123…n

mm+1…MAN-1

dataa1

a2

a3

…an

bm

…b2

b1top1top2栈2底栈1底双栈共享存储空间601.3双栈的操作让两个栈共享一个数组的存储空间,让一个栈的存储结构可定义为#defineMAN双栈中允许存放元素的最大个数typedefstruct{datatypedata[MAN];inttop1,top2;}bothstack;用bothstack可以定义一个双栈ds:bothstackds;或bothstack*ds;61存储结构可定义为#defineMAN双栈中允许存放元素的1.进栈voidpush(bothstack*ds,datatypeN){if(ds->top2==ds->top1+1)printf("栈满");else{ds->top2--;ds->data[ds->top2]=N;}}621.进栈voidpush(bothstack*ds2.出栈voidpop(bothstack*ds,datatype*N){if(ds->top2==MAN) printf("栈空"); else{*N=ds->data[ds->top2];ds->top2++; }}632.出栈voidpop(bothstack*ds,d1.4栈的应用算法思路:把十进制数转换为二进制数采用的方法是“除2取余”,直到商为0。依次得到的余数是k1,k2,k3,……,km,而转换后的二进制数是kmkm-1…k3k2k1,从结果看恰好与计算过程相反,因此转换过程中每得到一位二进制数则进栈保存,转换完毕后依次出栈则正好是转换结果。此种方法同样适用于将十进制数转换为r进制的数。把十进制整数11转换为二进制的过程如下:211余数二进制位

低高

25

1k1

22

1k2

21

0k30

1k4例2-3编写一个算法将给定的十进制数转换为二进制数输出。641.4栈的应用算法思路:把十进制数转换为二进制数采用的方法数值转换的算法typedefintdatatype;#defineMAN10voidtransfer(intn,intr)voidtransfer(intn,intr){stacks;{ints[MAN],top;/*定义一个顺序栈*/datatypeN;intN;init(s); top=0;/*初始化栈*/while(n) while(n){push(s,n%r); {s[++top]=n%r;/*余数入栈*/n=n/r; n=n/r;/*商作为被除数继续*/} }while(!empty(s))while(top!=0){pop(s,N); {N=s[top--];printf("%d",N); printf("%d",N);} }} }

算法一算法二65数值转换的算法typedefintdatatype;例2-4栈与递归

下面以n!为例,介绍如何将递归的算法改写为堆栈的非递归算法。n!=1

n==0或n==1/*递归终止条件*/n*(n-1)! n>0/*递归步骤*/intfact(intn){if(n==0||n==1)return1;elsereturn(n*fact(n-1));}66例2-4栈与递归下面以n!为例,介绍如何将递归的算法程序的执行过程图示fact(3)n=3f=3*fact(2)returnff=3*2*1*1n=2f=2*fact(1)returnff=2*1*1n=1f=1*fact(0)returnff=1*1n=0f=1returnff=1intfact(intn){if(n==0||n==1)return1;elsereturn(n*fact(n-1));}67程序的执行过程图示fact(3)n=3f=3*fact(2)阶乘的堆栈算法(非递归)typedefintdatatype;#defineMAN20intfact(intn) intfact(intn){stacks;datatypeN;intm=1;{ints[MAN],top=0,N,m=1;init(s); if(n==0||n==1)m=1;if(n==0||n==1)m=1;else{while(n>1)else{while(n>1) {s[++top]=n; {push(s,n);n--; n--; } }while(!empty(s))while(top!=0) {pop(s,N); {N=s[top--];m=m*N; m=m*N; } }} }returnm; returnm;} }算法一 算法二68阶乘的堆栈算法(非递归)typedefintdataty例2-5算术表达式的求值1.算术表达式的两种表示方法⑴中缀表达式所谓中缀表达式就是把运算符放在两个运算对象之间的表达式。如3+5*3。实际中缀表达式就是经常习惯使用的算术表达式。①有括号出现时先算括号内的,后算括号外的,多层括号,由内向外进行;②在无括号或同层括号内的情况下,先做乘除运算,S后做加减运算;③同一优先级运算,从左向右依次进行。69例2-5算术表达式的求值1.算术表达式的两种表示方法⑵后缀表达式所谓后缀表达式就是把运算符放在两个运算对象之后的表达式。如3+5*3的后缀表达式是353*+其中运算对象和运算符之间用空格隔开。在后缀表达式中,不再引入括号,所有的计算按运算符出现的顺序,严格从左向右进行,即遇到运算符就将运算符前的两个运算对象进行计算,而不用再考虑运算规则和级别。所以计算机扫描一次就能完成运算。把中缀表达式转换成对应的后缀表达式的规则是:把每个运算符都移到他的两个运算对象的后面,然后删掉所有的括号即可。70⑵后缀表达式所谓后缀表达式就是把运算符放在两个运算对象之例如:对下列各中缀表达式①5/2-7②15+6*(2+4)③3*(N+y)/(2-y)④(25+N)*(a*(a+b)+b)对应的后缀表达式分别为①52/7-②15624+*+③3Ny+*2y-/④25N+aab+*b+*71例如:对下列各中缀表达式262.中缀表达式转换成后缀表达式在将中缀表达式转化为后缀表达示的算法中,为了讨论方便我们设表达式中的运算对象只有一位数字,并将中缀表达式保存在字符数组a中,转换后的后缀表达式存储在字符数组b中,用一个字符数组s作为栈,设字符'='为表达式的结束符。算法思路如下:722.中缀表达式转换成后缀表达式在将中缀表达式转化为后缀表达先将输入的中缀表达式,存入字符数组a中,取出a数组中的每一个字符存于c变量中,对于每一个c变量的值做如下处理:①若c为数字,则存于数组b中;②若c为左括号'(',则将其压入栈s;③若c为右括号‘)’,则将栈s中左括号‘(’以后的运算符依次出栈,存于数组b中,然后将左括号'('出栈;④若c为‘+’或‘-’,则将栈s中左括号‘(’以后的所有运算符依次出栈,存于数组b中,然后将c压入栈s中;⑤若c为'*'或'/',则将栈s中的栈顶端连续的'*'或'/'出栈,存于数组b中,然后将c压入栈s中⑥若c为'=',则将栈S中的所有运算符依次出栈,存于数组b中,然后将c存于数组b中,最后得到的后缀表达式存储在字符数组b中。73先将输入的中缀表达式,存入字符数组a中,取出a数组中的每一个中缀转后缀的算法如下所示:#defineMAN50Voidtrans(){chara[MAN],b[MAN],s[MAN],c;inti=0,j,t=1,top=0;do{i++;scanf("%c",&a[i]);}while(a[i]!='='&&i<MAN);i=1;c=a[i];i++;while(c!='='){if(c>='0'&&c<='9'){b[t]=c;t++;}elseif(c=='('){top++;s[top]=c;}elseif(c==')'){while(s[top]!='('){b[t]=s[top];top--;t++}top--;}

elseif(c=='+'||c=='-'){while(top!=0&&s[top]!='('){b[t]=s[top];top--;t++;}top++;s[top]=c;}elseif(c=='*'||c=='/'){while(s[top]!='*'||s[top]!='/'){b[t]=s[top];top--;t++;}top++;s[top]=c;}c=a[i];i++;}while(top!=0){b[t]=s[top];t++;top--;}b[t]='=';

for(j=1;j<t;j++)printf("%c",b[j]);printf("\n");}74中缀转后缀的算法如下所示:elseif(c=='+以中缀表达式2*(1+2)/2为例,其转换过程如图所示。其中a数组存放的是中缀表达式2*(1+2)/2=,b数组存放的是转换后的后缀表达式212+*2/=,s数组作为栈,暂存运算符。12345678910…a数组2*(1+2)/2=12345678910…b数组212+*2/=**(*(+/s栈75以中缀表达式2*(1+2)/2为例,其转换过程如图所示。其中3.后缀表达式求值后缀表达式值的计算是比较简单的,这是因为表达式中即无括号又无优先级的约束。具体做法:需要一个存放数值的栈s1,当从左向右扫描表达式时,每遇到一个操作数就送入栈中保存,每遇到一个运算符就从栈中取出两个操作数进行当前的计算,然后把结果再入栈,直到整个表达式结束,这时栈顶存放的值就是后缀表达式的结果。下面是后缀表达式求值的算法,在下面的算法中假设后缀表达式已被存入一个字符数组b中,且以'='为结束字符,为了简化问题,限定运算数的位数仅为一位。763.后缀表达式求值后缀表达式值的计算是比较简单的,这是因为后缀表达式求值算法:#defineMAN50floatcalcul(char*b){floats1[MAN],d;charc;inti=0,t=0,top=0;c=*b++;while(c!='='){d=c-'0';if(c>='0'&&c<='9'){top++;s1[top]=d;}else{switch(c){case'+':s1[top-1]=s1[top-1]+s1[top]:break;

case'-':s1[top-1]=s1[top-1]-s1[top];break;case'*':s1[top-1]=s1[top-1]*s1[top];break;case'/':s1[top-1]=s1[top-1]/s1[top];break;}top--;}c=*b++;}returns1[top];}77后缀表达式求值算法:#defineMAN5032

仍以中缀表达式2*(1+2)/2为例,他的后缀表达式存放在b数组中。后缀表达式212+*2/=的求值过程如下所示。222进栈1211入栈22122入栈+231和2出栈,计算1+2,并将结果3入栈*62和3出栈,计算2*3,并将结果6入栈2622入栈/32和6出栈,计算6/2,并将结果3入栈=空结果3出栈78仍以中缀表达式2*(1+2)/2为例,他的后缀表达式存放2队列2.1队列的定义及顺序存储2.2队列的运算2.3循环队列792队列2.1队列的定义及顺序存储342.1队列的定义及顺序存储1.队列

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论