栈->栈的应用

时间:2023-03-09 13:16:54
栈->栈的应用

e.g.1 数制转换

十进制数N和其它d进制数的转换是计算机实现计算的基本问题,其解决方法很多,其中一个简单算法基于下列原理。

假设编写一个程序:对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数。由于上述计算过程是从低位到高位顺序产生八进制数的各个数位,而打印输出,一般来说应从高位到低位进行,恰好和计算过程相反。因此,若将计算过程中得到的八进制数的各为顺序进栈,则按出栈序列打印输出的即为与输入对应的八进制数。

栈->栈的应用

e.g.2 括号匹配

假设表达式中运行包含两种括号:圆括号和方括号,其嵌套的顺序随意,即([]())或[([])[]]等为正确的格式,[(])或([()]或为不正确的格式。可利用栈来检验括号是否匹配。

e.g.3 行编辑程序

一个简单的行编辑程序的功能:接受用户从终端输入的程序或数据,并存入用户的数据区。由于用户在终端上进行输入时,不能保证不出差错,当用户发现刚刚键入的一个字符是错的时,可补进一个退格符#,表示前一个字符无效;如果发现当前键入的行内差错较多或难以补救,则可以键入一个退格符@,表示当前行中的字符均无效。

栈->栈的应用

e.g.4 表达式求值

可以使用两个工作栈。一个称为OPTR,用来存运算符(+=*/()#); 另一个称为OPND,用来存放操作数或运算结果。算法的基本思想是:

(1)   首先将操作数栈置为空栈,表达式起始符#为运算法栈的栈底元素;

(2)   依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为#)

栈->栈的应用

栈->栈的应用

e.g.5 迷宫求解

求迷宫中从入口到出口的路径:(如下图)

栈->栈的应用     栈->栈的应用

代码实现

 #include <stdio.h>
#include <stdlib.h>
#include <string.h> #define STACK_INIT_SIZE 100
#define STACKINVREMENT 10
typedef char SElemType;
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
}SqStack; static int InitStack(SqStack *S);
static int GetTop(SqStack *S, SElemType *e);
static int Push(SqStack *S, SElemType e);
static int Pop(SqStack *S, SElemType *e);
static int StackTraversie(SqStack S);
static int StackEmpty(SqStack S);
static int ClearStack(SqStack *S);
static int DestoryStack(SqStack *S); static void conversion()
{
int N = ;
SElemType E;
SqStack S;
InitStack(&S);
printf("请输入一个十进制数:");
scanf("%d", &N);
while(N){
Push(&S, ''+N%);
N=N/;
}
printf("该数的八进制数为:");
while(StackEmpty(S)<){
Pop(&S, &E);
printf("%c", E);
}
printf("\n");
} static int bracketMatch()
{
SElemType e;
SqStack S;
InitStack(&S); int err = ;
char string[] = {};
char *c = string;
printf("输入待检验的字符串:");
scanf("%s[^\\n]", string);
while(*c){
switch(*c){
case '[':
case '(':
Push(&S, *c);
break;
case ']':
if((!GetTop(&S, &e)) && (e == '[')){
Pop(&S, &e);
}else{
err = -;
goto end;
}
break;
case ')':
if((!GetTop(&S, &e)) && (e == '(')){
Pop(&S, &e);
}else{
err = -;
goto end;
}
break;
default:
err = -;
goto end;
}
c++;
}
end:
if(err<){
printf("%s 是不匹配的!\n", string);
}else{
printf("%s 是匹配的!\n", string);
}
return err;
} static void lineEdit()
{
SElemType e;
SqStack S;
InitStack(&S); char line[] = {};
char data[] = {};
char *c = line;
printf("输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):");
scanf("%s[^\\n]", line);
if(strncmp(line, "end", strlen("end")) == ){
return ;
}
while(*c){
if(*c == '!'){
DestoryStack(&S);
break;
}
switch(*c){
case '#':
Pop(&S, &e);
break;
case '@':
ClearStack(&S);
break;
default:
Push(&S, *c);
break;
}
c+=;
if(!(*c)){
printf("输出字符:%s\n", S.base);
ClearStack(&S);
memset(line, , sizeof(line));
printf("输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):");
scanf("%s[^\\n]", line);
if(strncmp(line, "end", strlen("end")) == ){
return;
}
c = line;
}
}
} static int IsOPTR(char c, char OP[], int len)
{
int i = ;
for(i=; i<len; i++){
if(c == OP[i]){
return ;
}
}
return -;
} static char Precede(char c1, char c2)
{
int I[] = {};
I['+'] = ;
I['-'] = ;
I['*'] = ;
I['/'] = ;
I['('] = ;
I[')'] = ;
I['#'] = ;
char table[][] = {};
table[I['+']][I['+']] = '>';table[I['+']][I['-']] = '>';table[I['+']][I['*']] = '<';table[I['+']][I['/']] = '<';table[I['+']][I['(']] = '<';table[I['+']][I[')']] = '>';table[I['+']][I['#']] = '>';
table[I['-']][I['+']] = '>';table[I['-']][I['-']] = '>';table[I['-']][I['*']] = '<';table[I['-']][I['/']] = '<';table[I['-']][I['(']] = '<';table[I['-']][I[')']] = '>';table[I['-']][I['#']] = '>';
table[I['*']][I['+']] = '>';table[I['*']][I['-']] = '>';table[I['*']][I['*']] = '>';table[I['*']][I['/']] = '>';table[I['*']][I['(']] = '<';table[I['*']][I[')']] = '>';table[I['*']][I['#']] = '>';
table[I['/']][I['+']] = '>';table[I['/']][I['-']] = '>';table[I['/']][I['*']] = '>';table[I['/']][I['/']] = '>';table[I['/']][I['(']] = '<';table[I['/']][I[')']] = '>';table[I['/']][I['#']] = '>';
table[I['(']][I['+']] = '<';table[I['(']][I['-']] = '<';table[I['(']][I['*']] = '<';table[I['(']][I['/']] = '<';table[I['(']][I['(']] = '<';table[I['(']][I[')']] = '=';table[I['(']][I['#']] = ' ';
table[I[')']][I['+']] = '>';table[I[')']][I['-']] = '>';table[I[')']][I['*']] = '>';table[I[')']][I['/']] = '>';table[I[')']][I['(']] = ' ';table[I[')']][I[')']] = '>';table[I[')']][I['#']] = '>';
table[I['#']][I['+']] = '<';table[I['#']][I['-']] = '<';table[I['#']][I['*']] = '<';table[I['#']][I['/']] = '<';table[I['#']][I['(']] = '<';table[I['#']][I[')']] = ' ';table[I['#']][I['#']] = '=';
return table[I[c1]][I[c2]];
} static char Operate(char a, char theta, char b)
{
int i = atoi(&a);
int j = atoi(&b);
int ret = ;
if(theta == '+'){
ret = i+j;
}
if(theta == '-'){
ret = i-j;
}
if(theta == '*'){
ret = i*j;
}
if((theta=='/') && (j!=)){
ret = i/j;
}
return (char)(ret+'');
} static int EvaluateExpression()
{
SElemType e;
SqStack OPTR;
SqStack OPND;
InitStack(&OPTR); //操作符
InitStack(&OPND); //操作数
Push(&OPTR, '#');
char line[] = {};
char *c = line;
char OP[] = "+-*/()#", theta, a, b;
printf("输入仅含有运算符+-*/()的表达式,若有#则表示结束输入, 只支持10以内的运算:");
scanf("%s[^\\n]", line);
while(*c){
if(IsOPTR(*c, OP, sizeof(OP))<){
Push(&OPND, *c);
c+=;
}else{
GetTop(&OPTR, &e);
switch(Precede(e, *c)){
case '<':
Push(&OPTR, *c);
c+=;
break;
case '=':
Pop(&OPTR, &e);
c+=;
break;
case '>':
Pop(&OPTR, &theta);
Pop(&OPND, &b);
Pop(&OPND, &a);
Push(&OPND, Operate(a, theta, b));
break;
default:
break;
}
}
}
GetTop(&OPND, &e);
printf("结果 %s = %c\n", line, e);
return ;
} int main(int argc, char *argv[])
{
printf("e.g.1: 任意一个十进制数转换成八进制树.\n");
conversion(); printf("e.g.2: 检验括号是否匹配.\n");
bracketMatch();
bracketMatch(); printf("e.g.3: 行编辑程序.\n");
lineEdit(); printf("e.g.4: 表达式求值.\n");
EvaluateExpression(); return ;
} static int InitStack(SqStack *S)
{
if((S->base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType))) == NULL){
printf("failed malloc when initSTack!\n");
return -;
}
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
return ;
} static int GetTop(SqStack *S, SElemType *e)
{
if(S->top == S->base){
return -;
}
(*e) = *(S->top-);
return ;
} static int Push(SqStack *S, SElemType e)
{
if((S->top - S->base) >= S->stacksize){
if((S->base=(SElemType*)realloc(S->base, (S->stacksize+STACKINVREMENT)*sizeof(SElemType))) == NULL){
printf("failed reamalloc when Push!\n");
return -;
}
S->top = S->base+S->stacksize;
S->stacksize += STACKINVREMENT;
}
*(S->top++) = e;
return ;
} static int Pop(SqStack *S, SElemType *e)
{
if(S->top == S->base){
return -;
}
(*e) = *(--S->top);
return ;
} static int StackTraversie(SqStack S)
{
SElemType *p = S.base;
printf("base is 0x%x, top is 0x%x\n", S.base, S.top);
while(p)
{
if(p == S.top){
break;
}
printf("0x%x, %c\n", p, *p);
p++;
}
return ;
} static int StackEmpty(SqStack S)
{
if(S.top == S.base){
return ;
}else{
return -;
}
} static int ClearStack(SqStack *S)
{
if(S==NULL){
return -;
}
memset(S->base, , S->stacksize);
S->top = S->base;
return ;
} static int DestoryStack(SqStack *S)
{
if(S == NULL){
return -;
}
if(S->base){
free(S->base);
S->base = NULL;
S->top = NULL;
S->stacksize = ;
}
return ;
}

栈的应用1-2-3-4

 //
// Created by lady on 19-3-27.
// #include <stdlib.h>
#include <stdio.h>
#include <string.h> #define YES 1
#define NO 0
#define MAX_SIZE 10
typedef struct position{
int Xaxis; //横坐标
int Yaxis; //纵坐标
}position;
typedef struct brick{
int type; //yes: 表示通过; no: 表示障碍物或墙
int visit; //no: 表示未曾到过; yes: 表示已经来过
}brick; typedef struct matrix{
int w; //宽度
int h; //高度
brick wall[MAX_SIZE][MAX_SIZE];
position in; // 入口
position out; // 出口
}matrix; /////////////////////////////
#define STACK_INIT_SIZE 100 //栈的初始大小
#define STACK_INVREMENT 10 //栈的增量大小
typedef struct SElemType{
int ord; //序号
position seat; //位置坐标
int di; //方向
}SElemType;
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
static int InitStack(SqStack *S); //栈的初始化
static int Push(SqStack *S, SElemType e); //入栈
static int Pop(SqStack *S, SElemType *e); //出栈
static int StackEmpty(SqStack S); //判断栈是否为空
///////////////////////////// //创建一个迷宫矩阵
int create_matrix(matrix *array)
{
int i = ;
int j = ;
memset(array->wall, , sizeof(array->wall)); array->w = ;
array->h = ; brick b;
b.type = YES;
b.visit = NO;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->in.Xaxis = ;
array->in.Yaxis = ;
array->out.Xaxis = ;
array->out.Yaxis = ;
return ;
} //打印迷宫矩阵,红色表示墙或者障碍物,绿色表示通道,蓝色表示迷宫中从入口到出口的一条路径
void print_matrix(matrix *array)
{
int i = ;
int j = ;
printf("%c\t", ' ');
for(i=; i<array->w; i++){
printf("%d\t", i);
}
printf("\n");
for(i=; i<array->h; i++){
printf("%d\t", i);
for(j=; j<array->w; j++){
if(array->wall[i][j].visit){//蓝色
printf("\033[1;30;44m%d\t\033[0m", array->wall[i][j].visit);
}else if(array->wall[i][j].type == YES){//绿色
printf("\033[1;30;42m%d\t\033[0m", array->wall[i][j].type);
}else{//红色
printf("\033[1;30;41m%d\t\033[0m", array->wall[i][j].type);
}
}
printf("\n");
}
} //判断迷宫array中的位置pos是否可以通过,即是通道还是障碍物
static int Pass(position pos, matrix *array)
{
int x = pos.Xaxis;
int y = pos.Yaxis;
int type = array->wall[x][y].type;
int visit = array->wall[x][y].visit;
if( type== YES ){
if(visit == NO){
return ;
}
}
return ;
} //在迷宫array的位置pos上留下来过的痕迹
static int FootPrint(position pos, matrix *array)
{
int x = pos.Xaxis;
int y = pos.Yaxis;
array->wall[x][y].visit = YES;
return ;
} //在迷宫array的位置pos上留下来过的痕迹
static int MarkPrint(position pos, matrix *array)
{
int x = pos.Xaxis;
int y = pos.Yaxis;
array->wall[x][y].visit = YES;
return ;
} //返回位置pos的下一个探测的"通道"
static position NextPos(position pos, int direct)
{
position p;
if(direct == ){
p.Xaxis = pos.Xaxis;
p.Yaxis = pos.Yaxis-;
}
if(direct == ){
p.Xaxis = pos.Xaxis + ;
p.Yaxis = pos.Yaxis;
}
if(direct == ){
p.Xaxis = pos.Xaxis;
p.Yaxis = pos.Yaxis + ;
}
if(direct == ){
p.Xaxis = pos.Xaxis - ;
p.Yaxis = pos.Yaxis;
}
return p;
} //寻找迷宫array中从入口到出口的一条路径
static int Find_Path(matrix *array)
{
SqStack S;
position curpos = array->in; //设定当前位置
position end = array->out;
SElemType e;
int curstep = ; //探索第一步
int flag = ;
int x, y;
int i, j;
InitStack(&S); //初始化栈 do{
if(Pass(curpos, array)){//当前位置可以通过,即使未来过的通道
FootPrint(curpos, array);//留下到过的足迹
e.ord = curstep;
e.seat = curpos;
e.di = ;
Push(&S, e); //加入路径
if((curpos.Xaxis == end.Xaxis) && (curpos.Yaxis == end.Yaxis)){//到达终点
flag = ;
break;
}
curstep += ;//探索下一步
}else{//当前位置不能通过
if(StackEmpty(S)<){
Pop(&S, &e);
while((e.di == ) && (StackEmpty(S) < )){
MarkPrint(e.seat, array);//留下不能通过的足迹
Pop(&S, &e);
}
if(e.di < ){
e.di += ;//换下一个方向探索
Push(&S, e);
curpos = NextPos(e.seat, e.di);//设定当前位置是该块新方向上的相邻块
}
}
}
}while(StackEmpty(S)<); //清空迷宫中的块的visit标记
for(i=; i<array->w; i++){
for(j=; j<array->h; j++){
array->wall[i][j].visit = NO;
}
} //foreach stack
if(flag){//有入口到出口的路径
SElemType *p = S.base;
while(p){
if(p==S.top){
break;
}
x = p->seat.Xaxis;
y = p->seat.Yaxis;
//将迷宫中的块的visit标记来表示路径上的序号
array->wall[x][y].visit = p->ord;
p += ;
}
return ;
}else{
return -;
}
} int main(int argc, char *argv[])
{
matrix array;
if(create_matrix(&array) < ){
return -;
}
Find_Path(&array);
print_matrix(&array);
return ;
} /////////////////////////////
static int InitStack(SqStack *S)
{
if((S->base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType))) == NULL){
return -;
}
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
return ;
} static int Push(SqStack *S, SElemType e)
{
if((S->top - S->base) >= S->stacksize){
if((S->base=(SElemType*)realloc(S->base, (S->stacksize+STACK_INVREMENT)*sizeof(SElemType))) == NULL){
printf("failed reamalloc when Push!\n");
return -;
}
S->top = S->base+S->stacksize;
S->stacksize += STACK_INVREMENT;
}
*(S->top++) = e;
return ;
} static int Pop(SqStack *S, SElemType *e)
{
if(S->top == S->base){
return -;
}
(*e) = *(--S->top);
return ;
}
static int StackEmpty(SqStack S)
{
if(S.top == S.base){
return ;
}else{
return -;
}
}
/////////////////////////////

e.g.5 迷宫求解

代码运行

 /home/lady/CLionProjects/untitled/cmake-build-debug/untitled
e.g.1: 任意一个十进制数转换成八进制树.
请输入一个十进制数:123
该数的八进制数为:173
e.g.2: 检验括号是否匹配.
输入待检验的字符串:[([][])]
[([][])] 是匹配的!
输入待检验的字符串:(()]
(()] 是不匹配的!
e.g.3: 行编辑程序.
输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):whli##ilr#e(s#*s)
输出字符:while(*s)
输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):outchar@putchar(*s=#++)
输出字符:putchar(*s++)
输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):end
e.g.4: 表达式求值.
输入仅含有运算符+-*/()的表达式,若有#则表示结束输入, 只支持10以内的运算:3*(7-5)#
结果 3*(7-5)# = 6 Process finished with exit code 0

栈->栈的应用