栈的应用
文章目录
- 括号匹配
- 表达式
- 递归
- 进制转化
1.括号匹配
假设一个算术表达式中包含()、[] 和 {}3种类型的括号,编写一个算法判别表达式中括号是否匹配,以字符‘\0’作为算术表达式的结束符。
算法思想:
扫描每个字符,遇到圆、方、花的左括号是进栈,遇到圆、方、花的右括号时检查栈顶元素是否为相应的左括号,若是,退栈,否则匹配错误。最后栈不为空也为错误。
完整代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Maxsize 50
typedef char Datatype;
typedef struct{
Datatype data[Maxsize];
int top;
}SqStack;
void InitStack(SqStack *S)
{
S->top=-1;
}
int StackEmpty(SqStack *S)
{
if(S->top==-1)
return 0;
else
return 1;
}
int Push (SqStack *S,Datatype x)
{
if(S->top==Maxsize-1)
return 0;
else
S->data[++(S->top)]=x;
return 1;
}
int Pop(SqStack *S, Datatype *x)
{
if(S->top==-1)
return 0;
else
*x=S->data[(S->top)--];
return 1;
}
int GetTop(SqStack S,Datatype *x)
{
if(S.top==-1)
return 0;
else
*x=S.data[S.top];
return 1;
}
int Bracketscheck(SqStack *S,char *str)
{
InitStack(S);
char e;
int i=0;
while(str[i]!='\0')
{
switch(str[i]){
case '(':
Push(S,'(');
break;
case '{':
Push(S,'{');
break;
case '[':
Push(S,'[');
break;
case ')':
Pop(S,&e);
if(e!='(')
return 0;
break;
case '}':
Pop(S,&e);
if(e!='{')
return 0;
break;
case ']':
Pop(S,&e);
if(e!='[')
return 0;
break;
default:
break;
}
i++;
}
int h=StackEmpty(S);
if(h==1)
return 0;
else
return 1;
}
int main()
{ SqStack S;
char str[Maxsize];
printf("请输入你要收入的字符串:");
scanf("%s",str);
int h=Bracketscheck(&S,str);
if(h==0)
printf("括号不匹配");
else
printf("括号匹配");
return 0;
}
2.表达式
- 中缀表达式转后缀表达式
- 后缀表达式的计算
- 中缀表达式的计算
附上代码
//后缀表达式的计算
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#define STACK_SIZE 20
#define STACK 10
#define MAXBUFFER 10
typedef double ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stack_size;
} sqstack;
void initstack(sqstack *s)
{
s->base=(ElemType *)malloc(STACK_SIZE * sizeof(ElemType));
if(!s->base)
{
exit(0);
}
s->top=s->base;
s->stack_size=STACK_SIZE;
}
void push(sqstack *s,ElemType e)
{
if(s->top - s->base>=s->stack_size)
{
s->base=(ElemType *)realloc(s->base,(s->stack_size+STACK) *sizeof(ElemType));
}
if(!s->base)
{
exit(0);
}
*(s->top)=e;
s->top++;
}
void pop(sqstack *s,ElemType *e)
{
if(s->top==s->base)
{
return ;
}
*e=*--(s->top);
}
int stacklen(sqstack s)
{
return(s.top - s.base);
}
int main()
{
sqstack s;
char c;
double d,e;
char str[MAXBUFFER];//定义缓冲区
int i;
initstack(&s);
printf("请按照逆波兰表达式输入待计算数据,数据域运算符之前用空格隔开,以'#'作为结束标志\n");
scanf("%c",&c);
while (c!='#')
{
while(isdigit(c) || c=='.')//48-57,0-9
{
str[i++]=c;
str[i]='\0';
if(i>=10)
{
printf("出错,输入的单个数据过大!\n");
return -1;
}
scanf("%c",&c);
if(c==' ')
{
d=atof(str);//将字符串转化为浮点数
push(&s,d);
i=0;
break;
}
}
switch(c)
{
case'+':
pop(&s,&e);
pop(&s,&d);
push(&s,d+e);
break;
case'-':
pop(&s,&e);
pop(&s,&d);
push(&s,d-e);
break;
case'*':
pop(&s,&e);
pop(&s,&d);
push(&s,d*e);
break;
case'/':
pop(&s,&e);
pop(&s,&d);
if(e != 0)
{
push(&s,d/e);
}
else
{
printf("除数为0\n");
return -1;
}
break;
}
scanf("%c",&c);
}
pop(&s,&d);
printf("\n最终的计算结果为:%f\n",d);
return 0;
}
//中缀转后缀
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#define STACK_SIZE 20
#define STACK 10
//#define MAXBUFFER 10
typedef char ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stack_size;
} sqstack;
void initstack(sqstack *s)
{
s->base=(ElemType *)malloc(STACK_SIZE * sizeof(ElemType));
if(!s->base)
{
exit(0);
}
s->top=s->base;
s->stack_size=STACK_SIZE;
}
void push(sqstack *s,ElemType e)
{
if(s->top - s->base>=s->stack_size)
{
s->base=(ElemType *)realloc(s->base,(s->stack_size+STACK) *sizeof(ElemType));
}
if(!s->base)
{
exit(0);
}
*(s->top)=e;
s->top++;
}
void pop(sqstack *s,ElemType *e)
{
if(s->top==s->base)
{
return ;
}
*e=*--(s->top);
}
int stacklen(sqstack s)
{
return(s.top - s.base);
}
int main()
{
sqstack s;
char c,e;
initstack(&s);
printf("请输入中缀表达式,以#作为结束标志:\n");
scanf("%c",&c);
while( c!= '#')
{
if(c>='0'&& c<= '9')
{
printf("%c",c);
}
else if( ')' ==c)
{
pop(&s,&e);
while( '('!= e)
{
printf("%c",e);
pop(&s,&e);
}
}
else if( '+'==c || '-'==c)
{
if( !stacklen(s))
{
push(&s,c);
}
else
{
do
{
pop(&s,&e);
if('('==e)
{
push(&s,e);
}
else
{
printf("%c",e);
}
}while(stacklen(s) &&'('!=e);
push(&s,c);
}
}
else if('*'==c || '/'==c ||'('==c)
{
push(&s,c);
}
else
{
printf("\n出错:输入格式错误!\n");
return -1;
}
scanf("%c",&c);
}
while( stacklen(s))
{
pop(&s,&e);
printf("%c",e);
}
return 0;
}
之后用中缀转后缀的算法加上后缀表达式计算的算法就可以实现中缀表达式的计算啦
3.栈在递归中的应用
- 阶乘
- 斐波那契数列
- 回文数
//n的阶乘的递归与非递归算法
#include<stdio.h>
int fac1(int n)
{
if(n==0||n==1)
{
return 1;
}
else
{
return n*fac1(n-1);
}
}
int fac2(int n)
{
if(n==0||n==1)
{
return 1;
}
else
{
int value =1;
while(n>1)
{
value*=n;
n--;
}
return value;
}
}
int main()
{
printf("%d\n",fac1(5));
printf("%d\n",fac2(5));
}
//斐波那契数列
#include<stdio.h>
int Fb(int i)
{
if(i<2)
return i == 0? 0 :1;
return Fb(i-1) + Fb(i-2);
}
int main()
{
int n;
printf("请输入月数n\n");
scanf("%d",&n);
printf("%d",Fb(n));
}
//利用栈实现回文数
#include<stdio.h>
#include<string.h>
int main()
{
char a[101],s[101];
int i,len,mid,next,top;
gets(a);
len=strlen(a);
mid=len/2-1;
top=0;//栈的初始化
for(i=0;i<=mid;i++)
{
s[++top]=a[i];
}
if(len%2==0)
{
next=mid+1;
}
else
{
next=mid+2;
}
for(i=next;i<=len-1;i++)
{
if(a[i]!=s[top])
break;
top--;
}
if(top==0)
printf("YES");
else
printf("NO");
getchar();getchar();
return 0;
}
4.进制转化
- 二进制转十进制
- 二进制转八进制
- 二进制转16进制
- 十进制转n进制
1.二进制转十进制
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define STACK_SIZE 20
#define STACK 10
typedef char ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stack_size;
} sqstack;
void initstack(sqstack *s)
{
s->base=(ElemType *)malloc(STACK_SIZE * sizeof(ElemType));
if(!s->base)
{
exit(0);
}
s->top=s->base;
s->stack_size=STACK_SIZE;
}
void push(sqstack *s,ElemType e)
{
if(s->top - s->base>=s->stack_size)
{
s->base=(ElemType *)realloc(s->base,(s->stack_size+STACK) *sizeof(ElemType));
}
if(!s->base)
{
exit(0);
}
*(s->top)=e;
s->top++;
}
void pop(sqstack *s,ElemType *e)
{
if(s->top==s->base)
{
return ;
}
*e=*--(s->top);
}
int stacklen(sqstack s)
{
return(s.top - s.base);
}
int main()
{
ElemType a;
sqstack s;
int len,i,sum=0;
initstack(&s);
printf("请输入二进制数,输入#符号表示结束!\n");
scanf("%c",&a);
while( a != '#')
{
push(&s,a);
scanf("%c",&a);
}
getchar();//清理键盘缓冲区 ,把'\n'从缓冲区去掉
len = stacklen(s);
printf("栈的当前容量是:%d\n",len);
for(i=0;i<len;i++)
{
pop(&s,&a);
sum = sum +(a-48) *pow(2,i);
}
printf("转化为十进制数是:%d\n",sum);
return 0;
}
2.二进制转八进制
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
typedef char ElemType;
typedef struct
{
ElemType *top;
ElemType *base;
int stacksize;//指示栈当前最大可使用容量
}sqstack;
void Initstack(sqstack *s)
{
s->base=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType));
if(!s->base)
exit(0);
s->top=s->base;
s->stacksize=STACK_INIT_SIZE;
}
void push(sqstack *s,ElemType e)
{
if(s->top-s->base>=s->stacksize)
{
s->base=(ElemType *)realloc(s->base,(STACKINCREMENT+s->stacksize)*sizeof(ElemType));
if(!s->base)
exit(0);
s->top=s->base+s->stacksize;
s->stacksize=s->stacksize+STACKINCREMENT;
}
*(s->top)=e;
s->top++;
}
void pop(sqstack *s,ElemType *e)
{
if(s->top==s->base)
return;
*e=*--(s->top);
}
//会对栈进行修改则传地址,不修改只是做测试等操作则只传数据即可
int stackLen(sqstack s)//这里传进来的是结构不是指针
{
return (s.top-s.base);//相减的不是地址,是地址指向元素相减
}
int main()
{
ElemType c;
sqstack s1;
sqstack s2;
int len,i,j,sum=0;
Initstack(&s1);
printf("请输入二进制数,输入#表示结束\n");
scanf("%c",&c);
while(c!='#')
{
if(c=='0'||c=='1')
push(&s1,c);
scanf("%c",&c);
}
getchar();
len=stackLen(s1);
Initstack(&s2);
for(i=0;i<len;i+=3)
{
for(j=0;j<3;j++)
{
pop(&s1,&c);
sum=sum+(c-48)*pow(2,j);
if(s1.base==s1.top)//若没有限制条件语句,在不足三位时,会因j<3继续进行循环,在空缺位补1造成错误
{
break;
}
}
push(&s2,sum+48);//再次以字符形式传入
sum=0;
}
printf("转化为八进制数为:");
while(s2.top!=s2.base){ //如果没有循环则只pop出一位
pop(&s2,&c);
printf("%c",c);
}
printf("(O)");
return 0;
}
3.二进制转16进制
/*二进制转十六进制*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAXSIZE 20
#define ERROR 0
#define OK 1
typedef int Status;
typedef char Elemtype;
typedef struct{ //栈的静态分配存储结构
Elemtype elem[MAXSIZE];
int top;
}SqStack;
void InitStack(SqStack *S)
{
S->top=-1; //top为整数且指向栈顶元素
}
/*压栈操作*/
Status PushStack(SqStack *S,Elemtype e)
{
if(S->top >= MAXSIZE-1)
{
return ERROR;
}
S->elem[++S->top]=e;
return OK;
}
/*弹栈操作*/
Status PopStack(SqStack *S,Elemtype *e)
{
if(S->top == -1)
{
return ERROR;
}
*e = S->elem[S->top--];
return OK;
}
/*求栈长度*/
Status StackLength(SqStack *S)
{
return S->top+1;
}
int main()
{
int sum=0,value,i,j;
Elemtype c;
SqStack S,S1;
InitStack(&S);
printf("请输入二进制数,以#结束输入:\n");
scanf("%c",&c);
while( c != '#')
{
if( c == '1'|| c == '0')
{
value=PushStack(&S,c);
if(!value)
{
printf("输入二进制数超过存储范围!\n");
return ERROR;
}
scanf("%c",&c);
}
else
{
printf("非法输入!\n");
return ERROR;
}
}
getchar(); //把'\n'从缓冲区去掉
InitStack(&S1);
int len=StackLength(&S);
for(i=0 ; i<len ; i+=4)
{
for(j=0;j<4;j++) //四位二进制数对应一位十六进制数
{
PopStack(&S,&c);
sum += ( c - 48 ) * pow( 2 , j );
if(S.top == -1)
{
break;
}
}
switch(sum)
{
case 10:
case 11:
case 12:
case 13:
case 14:
case 15: sum+=55;break;//大于十转换成字母字符
default :sum+=48; //小于十转换成数字字符
}
PushStack(&S1,sum); //把转换的字符进行压栈
sum=0; //从新进行下一个字符转换
}
printf("转化成十六进制是:");
while( S1.top != -1) //把转换好的十六进制数以字符形式进行弹栈
{
PopStack(&S1,&c);
printf("%c",c);
}
printf("(H)\n");
return 0;
}
4.十进制转n进制
#include<stdio.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
#define INITSIZE 10
#define INCREMENT 2
typedef int Status;
typedef int Elemtype;
typedef struct{
Elemtype *base;
Elemtype *top;
int StackSize;
}SqStack;
Status InitStack(SqStack *S)
{
S->base=(Elemtype*)malloc(sizeof(Elemtype)*INITSIZE);
if(!S->base)
{
return ERROR;
}
S->top=S->base;
S->StackSize=INITSIZE;
return OK;
}
Status PushStack(SqStack *S,Elemtype e)
{
if( S->top - S->base >= S->StackSize)
{
S->base=(Elemtype*)realloc(S->base,(S->StackSize+INCREMENT)*sizeof(Elemtype));
if(!S->base)
{
return ERROR;
}
S->top = S->base+S->StackSize;
S->StackSize+=INCREMENT;
}
*S->top=e;
S->top++;
return OK;
}
Status StackEmpty(SqStack *S)
{
if(S->top == S->base)
{
return OK;
}
return ERROR;
}
Status PopStack(SqStack *S,Elemtype *e)
{
if(S->top == S->base)
{
return ERROR;
}
*e=*--S->top;
return OK;
}
void Fun_10_2_8_16(int number,int cet)
{
SqStack S;
Elemtype e;
InitStack(&S);
if(number==0)
{
printf("转换后的%d进制数为:0",cet);
return ;
}
while(number)
{
PushStack(&S,number%cet);
number=number/cet;
}
printf("转换后的%d进制数为:",cet);
while(!StackEmpty(&S))
{
PopStack(&S,&e);
switch(e) //整型数转成字符输出
{
case 10:
case 11:
case 12:
case 13:
case 14:
case 15: e+=55;break;
default :e+=48;
}
printf("%c",e);
}
}
int main()
{
int number,cet;
printf("请输入要转换的十进制数:");
scanf("%d",&number);
printf("请输入要转换的数制:");
scanf("%d",&cet);
Fun_10_2_8_16(number,cet);
return 0;
}
到这里,栈的应用部分整理完成,若有没有整理到的后续进行补充,之后会更新线性表链表的相关知识.