栈的应用
来源:互联网 发布:武汉天融信网络 编辑:程序博客网 时间:2024/06/05 16:24
1、数制转换
十进制数N和其他d进制数的转换。
原理:N=(N div d)*d+N mod d (其中:div为整除运算,mod为求余运算)
具体例题:
对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数。
思想:
在计算过程中,是从低位到高位的顺序产生八进制数的各个位数,而打印输出则是从高位到低位进行,恰好与计算过程相反。在这个例子里,利用栈的后进先出特性,且操作的顺序直线式的,即先一味地进栈,再一味地出栈。
算法:
void conversion( ) { initstack(s); scanf (“%”,n); while(n){ push(s,n%8); n=n/8; } while(! Stackempty(s)){ pop(s,e); printf(“%d”,e); } }
具体代码实现(C)
#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<process.h> /* exit() */#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */#define STACKINCREMENT 2 /* 存储空间分配增量 */typedef struct SqStack{ int *base; /* 在栈构造之前和销毁之后,base的值为NULL */ int *top; /* 栈顶指针 */ int stacksize; /* 当前已分配的存储空间,以元素为单位 */}SqStack; /* 顺序栈 */int InitStack(SqStack *S){ /* 构造一个空栈S */ (*S).base=(int *)malloc(STACK_INIT_SIZE*sizeof(int)); if(!(*S).base) exit(-2); /* 存储分配失败 */ (*S).top=(*S).base; (*S).stacksize=STACK_INIT_SIZE; return 1;}int StackEmpty(SqStack S){ /* 若栈S为空栈,则返回TRUE,否则返回FALSE */ if(S.top==S.base) return 1; else return 0;}int Push(SqStack *S,int e){ /* 插入元素e为新的栈顶元素 */ if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */ { (*S).base=(int *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(int)); if(!(*S).base) exit(-2); /* 存储分配失败 */ (*S).top=(*S).base+(*S).stacksize; (*S).stacksize+=STACKINCREMENT; } *((*S).top)++=e; return 1;}int Pop(SqStack *S,int *e){ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */ if((*S).top==(*S).base) return 0; *e=*--(*S).top; return 1;}void conversion(){ /* 对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数 */ SqStack s; unsigned n; /* 非负整数 */ int e; InitStack(&s); /* 初始化栈 */ printf("n(>=0)="); scanf("%u",&n); /* 输入非负十进制整数n */ while(n) /* 当n不等于0 */ { Push(&s,n%8); /* 入栈n除以8的余数(8进制的低位) */ n=n/8; } while(!StackEmpty(s)) /* 当栈不空 */ { Pop(&s,&e); /* 弹出栈顶元素且赋值给e */ printf("%d",e); /* 输出e */ } printf("\n");}void main(){ conversion();}
2、括号匹配的检验
假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,即([]())或[([][])]等为正确的格式,[(])或([())均为不正确的格式。
原理:设置一个栈,每读入一个括号,若是右括号,则或者使置于栈顶的最急迫的期待得以消解,或者是不合法的情况;若是左括号,则作为一个新的更急迫的期待压入栈中,自然使原有的在栈中的所有未消解的期待的急迫性都降一级。算法开始和结束时,栈都应该是空的。
算法:
void check(){ if(InitStack(S)) { gets(ch); p=ch; while(*p) switch(*p) { case '(': case '[':Push(S,*p++);break; case ')': case ']':if(!StackEmpty(S)) { Pop(S,e); if(*p==')'&&e!='('||*p==']'&&e!='[') exit(ERROR); else {p++;break;} } else exit(ERROR); default : p++; } }
具体代码的实现(C):
#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<process.h> /* exit() */#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */#define STACKINCREMENT 2 /* 存储空间分配增量 */typedef struct SqStack{ char *base; /* 在栈构造之前和销毁之后,base的值为NULL */ char *top; /* 栈顶指针 */ int stacksize; /* 当前已分配的存储空间,以元素为单位 */}SqStack; /* 顺序栈 */int InitStack(SqStack *S){ /* 构造一个空栈S */ (*S).base=(char *)malloc(STACK_INIT_SIZE*sizeof(char)); if(!(*S).base) exit(-2); /* 存储分配失败 */ (*S).top=(*S).base; (*S).stacksize=STACK_INIT_SIZE; return 1;}int StackEmpty(SqStack S){ /* 若栈S为空栈,则返回1,否则返回0 */ if(S.top==S.base) return 1; else return 0;}int Push(SqStack *S,char e){ /* 插入元素e为新的栈顶元素 */ if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */ { (*S).base=(char *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(char)); if(!(*S).base) exit(-2); /* 存储分配失败 */ (*S).top=(*S).base+(*S).stacksize; (*S).stacksize+=STACKINCREMENT; } *((*S).top)++=e; return 1;}int Pop(SqStack *S,char *e){ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */ if((*S).top==(*S).base) return 0; *e=*--(*S).top; return 1;}void check(){ /* 对于输入的任意一个字符串,检验括号是否配对 */ SqStack s; char ch[80],*p,e; if(InitStack(&s)) /* 初始化栈成功 */ { printf("请输入表达式\n"); gets(ch); p=ch; while(*p) /* 没到串尾 */ switch(*p) { case '(': case '[':Push(&s,*p++); break; /* 左括号入栈,且p++ */ case ')': case ']':if(!StackEmpty(s)) /* 栈不空 */ { Pop(&s,&e); /* 弹出栈顶元素 */ if(*p==')'&&e!='('||*p==']'&&e!='[') /* 弹出的栈顶元素与*p不配对 */ { printf("左右括号不配对\n"); exit(0); } else { p++; break; /* 跳出switch语句 */ } } else /* 栈空 */ { printf("缺乏左括号\n"); exit(0); } default: p++; /* 其它字符不处理,指针向后移 */ } if(StackEmpty(s)) /* 字符串结束时栈空 */ printf("括号匹配\n"); else printf("缺乏右括号\n"); }}void main(){ check();}
3、行编辑
简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,为了能发现错误并及时改正,再设立一个数据缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。
具体例题:当用户发现刚刚键入的一个字符是错误的时,可以补进一个退格符“#”,以表示前面的一个字符无效,若发现当前键入的行内差错较多或难以补救时,则可以键入一个退行符“@”,以表示当前行中的字符均无效。
eg:whli##ilr#e(s#*s)
outcha@putchar(*s=#++)
则实际有效的是下列两行
while(* s)
putchar(*s++);
算法:
void lineedit( ) { initstack(s); ch=getchar( ); while(ch!=eof) { while(ch!=eof && ch!=‘\n’) { switch(ch) { case ‘#’ : pop(s,c); case ‘@’ : clearstack(s); default : push(s,ch); } ch=getchar( ); } clearstack(s); if(ch!=eof) ch=getchar( ); } destroystack(s); }
具体代码的实现(C):
#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() */FILE *fp;#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */#define STACKINCREMENT 2 /* 存储空间分配增量 */typedef struct SqStack{ char *base; /* 在栈构造之前和销毁之后,base的值为NULL */ char *top; /* 栈顶指针 */ int stacksize; /* 当前已分配的存储空间,以元素为单位 */}SqStack; /* 顺序栈 */int InitStack(SqStack *S){ /* 构造一个空栈S */ (*S).base=(char *)malloc(STACK_INIT_SIZE*sizeof(char)); if(!(*S).base) exit(-2); /* 存储分配失败 */ (*S).top=(*S).base; (*S).stacksize=STACK_INIT_SIZE; return 1;}int DestroyStack(SqStack *S){ /* 销毁栈S,S不再存在 */ free((*S).base); (*S).base=NULL; (*S).top=NULL; (*S).stacksize=0; return 1;}int ClearStack(SqStack *S){ /* 把S置为空栈 */ (*S).top=(*S).base; return 1;}int StackEmpty(SqStack S){ /* 若栈S为空栈,则返回TRUE,否则返回FALSE */ if(S.top==S.base) return 1; else return 0;}int GetTop(SqStack S,char *e){ /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */ if(S.top>S.base) { *e=*(S.top-1); return 1; } else return 0;}int Push(SqStack *S,char e){ /* 插入元素e为新的栈顶元素 */ if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */ { (*S).base=(char *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(char)); if(!(*S).base) exit(-2); /* 存储分配失败 */ (*S).top=(*S).base+(*S).stacksize; (*S).stacksize+=STACKINCREMENT; } *((*S).top)++=e; return 1;}int Pop(SqStack *S,char *e){ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */ if((*S).top==(*S).base) return 0; *e=*--(*S).top; return 1;}int StackTraverse(SqStack S,int(*visit)(char)){ /* 从栈底到栈顶依次对栈中每个元素调用函数visit()。 */ /* 一旦visit()失败,则操作失败 */ while(S.top>S.base) visit(*S.base++); printf("\n"); return 1;}int copy(char c){ /* 将字符c送至fp所指的文件中 */ fputc(c,fp); return 1;}void LineEdit(){ /* 利用字符栈s,从终端接收一行并送至调用过程的数据区。算法3.2 */ SqStack s; char ch,c; InitStack(&s); printf("请输入一个文本文件,^Z结束输入:\n"); ch=getchar(); while(ch!=EOF) { /* EOF为^Z键,全文结束符 */ while(ch!=EOF&&ch!='\n') { switch(ch) { case '#':Pop(&s,&c); break; /* 仅当栈非空时退栈 */ case '@':ClearStack(&s); break; /* 重置s为空栈 */ default :Push(&s,ch); /* 有效字符进栈 */ } ch=getchar(); /* 从终端接收下一个字符 */ } StackTraverse(s,copy); /* 将从栈底到栈顶的栈内字符传送至文件 */ ClearStack(&s); /* 重置s为空栈 */ fputc('\n',fp); if(ch!=EOF) ch=getchar(); } DestroyStack(&s);}void main(){ fp=fopen("ED.DAT","w"); /* 在当前目录下建立ED.DAT文件,用于写数据, */ if(fp) /* 如已有同名文件则先删除原文件 */ { LineEdit(); fclose(fp); /* 关闭fp所指的文件 */ } else printf("建立文件失败!\n");}
4、表达式求值
表达式求值是程序设计语言中的一个最基本问题。在此应用栈的“后进先出”的特点,介绍一种“算法优先级”算法。
算术四则运算的规则:
(1) 先乘除,后加减。
(2)从左算到右。
(3)先括号内,后括号外。
为实现算符优先算法,可使用两个工作栈:
OPND栈:存数据或运算结果
OPTR栈:存运算符
算法原理:
1.初态: 置OPND栈为空;将“#”作为OPTR栈的栈底元素
2.依次读入表达式中的每个字符
1)若是操作数,则进入OPND栈;
2)若是运算符,则与OPTR栈的栈顶运算符进行优先权(级)的比较:
§ 若读入运算符的优先权高,则进入OPTR栈;
§若读入运算符的优先权低,则OPTR退栈(退出
原有的栈顶元素),OPND栈退出两个元素
(先退出b,再退出a),中间结果再进入OPND栈;
§若读入“)”,OPTR栈的原有栈的栈顶元素若为
“(”,则OPTR退出“(”;
§若读入“#”,OPTR栈栈顶元素也为“#”,则OPTR栈退出“#”,结束
算法:
OperandType EvaluateExpression( ){ / /OPTR为运算符栈,OPND为运算数,OP为运算符集 InitStack(OPTR); Push(OPTR,'#'); InitStack(OPND); c=getchar(); while(c!='#'||GetTop(OPTR)!='#'){ if(! In(c,OP)) { Push(OPND,c);c=getchar();} else switch (Precede(GetTop(OPTR),c)) { case '<': Push(OPTR,c); c=getchar();break; case '=': Pop(OPTR,x);c=getchar();break; case '>': Pop(OPTR,theta); Pop(OPND,b);Pop(OPND,a); Push(OPND,OPerate(a,theta,b));break; } } return GetTop(OPND);}
具体代码的实现(C):
#include<string.h> #include<ctype.h> #include<malloc.h> /* malloc()等 */ #include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<process.h> /* exit() */ #define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */ #define STACKINCREMENT 2 /* 存储空间分配增量 */ typedef struct SqStack { char *base; /* 在栈构造之前和销毁之后,base的值为NULL */ char *top; /* 栈顶指针 */ int stacksize; /* 当前已分配的存储空间,以元素为单位 */ }SqStack; /* 顺序栈 */ int InitStack(SqStack *S) { /* 构造一个空栈S */ (*S).base=(char *)malloc(STACK_INIT_SIZE*sizeof(char)); if(!(*S).base) exit(-2); /* 存储分配失败 */ (*S).top=(*S).base; (*S).stacksize=STACK_INIT_SIZE; return 1; } int GetTop(SqStack S,char *e) { /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */ if(S.top>S.base) { *e=*(S.top-1); return 1; } else return 0; } int Push(SqStack *S,char e) { /* 插入元素e为新的栈顶元素 */ if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */ { (*S).base=(char *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(char)); if(!(*S).base) exit(-2); /* 存储分配失败 */ (*S).top=(*S).base+(*S).stacksize; (*S).stacksize+=STACKINCREMENT; } *((*S).top)++=e; return 1; } int Pop(SqStack *S,char *e) { /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */ if((*S).top==(*S).base) return 0; *e=*--(*S).top; return 1; } int StackTraverse(SqStack S,int(*visit)(char)) { /* 从栈底到栈顶依次对栈中每个元素调用函数visit()。 */ /* 一旦visit()失败,则操作失败 */ while(S.top>S.base) visit(*S.base++); printf("\n"); return 1; } char Precede(char t1,char t2) { /* 判断两符号的优先关系 */ char f; switch(t2) { case '+': case '-':if(t1=='('||t1=='#') f='<'; else f='>'; break; case '*': case '/':if(t1=='*'||t1=='/'||t1==')') f='>'; else f='<'; break; case '(':if(t1==')') { printf("ERROR1\n"); exit(0); } else f='<'; break; case ')':switch(t1) { case '(':f='='; break; case '#':printf("ERROR2\n"); exit(0); default: f='>'; } break; case '#':switch(t1) { case '#':f='='; break; case '(':printf("ERROR3\n"); exit(0); default: f='>'; } } return f; } int In(char c) { /* 判断c是否为运算符 */ switch(c) { case'+': case'-': case'*': case'/': case'(': case')': case'#':return 1; default:return 0; } } char Operate(char a,char theta,char b) { char c; a=a-48; b=b-48; switch(theta) { case'+':c=a+b+48; break; case'-':c=a-b+48; break; case'*':c=a*b+48; break; case'/':c=a/b+48; } return c; } char EvaluateExpression() { /* 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈 */ SqStack OPTR,OPND; char a,b,c,x,theta; InitStack(&OPTR); Push(&OPTR,'#'); InitStack(&OPND); c=getchar(); GetTop(OPTR,&x); while(c!='#'||x!='#') { if(In(c)) /* 是7种运算符之一 */ switch(Precede(x,c)) { case'<':Push(&OPTR,c); /* 栈顶元素优先权低 */ c=getchar(); break; case'=':Pop(&OPTR,&x); /* 脱括号并接收下一字符 */ c=getchar(); break; case'>':Pop(&OPTR,&theta); /* 退栈并将运算结果入栈 */ Pop(&OPND,&b); Pop(&OPND,&a); Push(&OPND,Operate(a,theta,b)); break; } else if(c>='0'&&c<='9') /* c是操作数 */ { Push(&OPND,c); c=getchar(); } else /* c是非法字符 */ { printf("ERROR4\n"); exit(-2); } GetTop(OPTR,&x); } GetTop(OPND,&x); return x; } void main() { printf("请输入算术表达式(中间值及最终结果要在0~9之间),并以#结束\n"); printf("%c\n",EvaluateExpression()); }
0 0
- 栈&栈的应用
- 栈的应用
- 栈的应用
- 简单的栈应用
- 栈的应用
- 栈的简单应用
- 栈的应用
- 栈的应用
- hdu1022栈的应用
- 栈的应用举例
- 栈的应用
- 栈的简单应用
- 数据结构栈的应用
- 栈的简单应用
- 栈的简单应用
- 栈的应用
- 栈的应用
- 栈的经典应用
- ajax案例---以GET和POST方式异步提交数据给后台
- Fruit Ninja II (微积分)
- php输出中文乱码问题
- php中创建用户和数据库的连接
- Android UI 设计 选项卡组件和ListView组件结合模拟新浪微博
- 栈的应用
- 买房流程
- 操作系统实验二-ubuntu下安装配置pintos
- Ubuntu Sun JDK 安装
- C++ 友元
- Csharp: speech to text, text to speech in win
- Csharp: speech to text, text to speech in win
- iOS崩溃堆栈还原
- 多功能心脏流血漏洞扫描工具(Heartbleed bug scanner suggested )