栈的举例应用
--------------------------------------------------------------------------------------------------------------------------------
栈的举例应用1:
----------------------------------------------------------------------------------------------------------------
举例应用2:
十进制数 N 和其他 d 的进制的转换:
原 理: N=( N div d) * d + N mod d (div 为整除运算,mod 为求余运算 )
例如 :(1348)10 = (2504)8
运算过程:
N N div 8 N mod 8
1348 168 4
168 21 0
21 2 5
2 0 2
代码如下: (注:以 .cpp 为后缀名)
//头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
//宏定义
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int SElemType;
typedef int Status;
//栈的顺序结构体
typedef struct{
SElemType *base; //在栈构造之前和销毁之后,base 的值为NULL;
SElemType *top; //栈顶指针
int stacksize; //当前已分配的存储空间,以元素为单位
}SqStack;
//1.构建栈
Status InitStack(SqStack &S){
//构造一个空栈S
S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(! S.base) exit(OVERFLOW); //存储分配失败
S.top=S.base; //当栈为空时,栈底等于栈顶
S.stacksize=STACK_INIT_SIZE; //栈可存储的个数
return OK;
}
//4.判断栈是否为空
Status StackEmpty( SqStack S)
{
if(S.top==S.base)
return TRUE;
else
return ERROR;
}
//7.栈顶插入元素
Status Push(SqStack &S,SElemType &e)
{ //插入元素 e 为新的栈顶元素
if(S.top-S.base >= STACK_INIT_SIZE) //栈满的时候就需要追加存储空间
{
S.base=(SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!S.base) exit(OVERFLOW); //存储空间分配失败
S.top=S.base+S.stacksize; //栈底的位置可能改变,需要重新定位栈顶元素
//S.top 还是之前的那个没有存储的位置
S.stacksize = S.stacksize+STACKINCREMENT;
}
*S.top=e;
S.top++;
return OK;
}
//8.栈顶出栈元素
Status Pop(SqStack &S,SElemType &e){
//若栈不为空,则删除 S 的栈顶元素,用 e 返回其值,并返回 OK ,否则返回ERROR
if(S.top == S.base) return ERROR;
e=*(--S.top); //可以不加括号,但需要记住的是,需要让 top 指针减 1 ,再取出元素
return OK;
}
//转换函数:
void conversion(){
int N,N1,e;
SqStack S;
//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
InitStack(S); //构建空栈
scanf("%d",&N);
while(N){ //以 N 不等于 0 为条件
N1=N%8;
Push(S,N1); //入栈,将 N 除于 8 的余数入栈
N=N/8;
}
while( !StackEmpty(S) ){
Pop(S,e);
printf("%d",e);
}
}
void main(){
conversion();
}
举例应用3:
括号匹配:
如有一下括号序列:
[ ( [ ] [ ] ) ]
1 2 3 4 5 6 7 8
当计算机接收了第一个括号后,它期待着与其匹配的第八个括号出现,然而等来的是第二个,这是第一个括号入栈,接着迫切等待与第二个匹配的括号,然而等来了第三个,所以第二个入栈,接着第三个入栈,等来了第四个,发现第四个与第三个可以匹配,所以第三个出栈,与其第四个进行匹配成功。接下来一次类推;只要下一个字符能够与出栈的字符进行匹配,就算匹配成功一对字符。如果不能匹配就入栈。
完整代码(注: 后缀名为 .cpp )
//头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
//宏定义
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef char SElemType;
typedef char Status;
//栈的顺序结构体
typedef struct{
SElemType *base; //在栈构造之前和销毁之后,base 的值为NULL;
SElemType *top; //栈顶指针
int stacksize; //当前已分配的存储空间,以元素为单位
}SqStack;
//1.构建栈
Status InitStack(SqStack &S){
//构造一个空栈S
S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(! S.base) exit(OVERFLOW); //存储分配失败
S.top=S.base; //当栈为空时,栈底等于栈顶
S.stacksize=STACK_INIT_SIZE; //栈可存储的个数
return OK;
}
//4.判断栈是否为空
Status StackEmpty( SqStack S)
{
if(S.top==S.base)
return TRUE;
else
return ERROR;
}
//7.栈顶插入元素
Status Push(SqStack &S,SElemType &e)
{ //插入元素 e 为新的栈顶元素
if(S.top-S.base >= STACK_INIT_SIZE) //栈满的时候就需要追加存储空间
{
S.base=(SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!S.base) exit(OVERFLOW); //存储空间分配失败
S.top=S.base+S.stacksize; //栈底的位置可能改变,需要重新定位栈顶元素
//S.top 还是之前的那个没有存储的位置
S.stacksize = S.stacksize+STACKINCREMENT;
}
*S.top=e;
S.top++;
return OK;
}
//8.栈顶出栈元素
Status Pop(SqStack &S,SElemType &e){
//若栈不为空,则删除 S 的栈顶元素,用 e 返回其值,并返回 OK ,否则返回ERROR
if(S.top == S.base) return ERROR;
e=*(--S.top); //可以不加括号,但需要记住的是,需要让 top 指针减 1 ,再取出元素
return OK;
}
void bracket(){
SElemType a[8]={ '[' , '(' , '[' , ']' , '[' , ']' , ')' , ']' };
SElemType e;
int n=1;
SqStack S;
InitStack(S);
SElemType *p=a;
while(*p){
switch(*p){
case '[':
case '(':
Push(S,*p); //左括号就入栈
break;
case ']':
case ')':
Pop(S,e); //有括号就寻找一个出栈来进行匹配
if( (*p==')' && e=='(') || (*p==']' && e=='[') )
{ printf("匹配成功 %d 个\n",n); n++; }
else
{ printf("匹配不成功"); exit(OVERFLOW); }
}
p++; //下一个字符
}
if( StackEmpty(S) ) //如果栈已经为空,就证明全都搞定了,所有匹配成功。
printf("所有括号匹配成功!");
else
printf("匹配失败。");
}
void main(){
bracket();
}
应用举例3:
行编辑程序:
完整代码:
.cpp 为文件名
//头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
//宏定义
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef char SElemType;
typedef char Status;
//栈的顺序结构体
typedef struct{
SElemType *base; //在栈构造之前和销毁之后,base 的值为NULL;
SElemType *top; //栈顶指针
int stacksize; //当前已分配的存储空间,以元素为单位
}SqStack;
//1.构建栈
Status InitStack(SqStack &S){
//构造一个空栈S
S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(! S.base) exit(OVERFLOW); //存储分配失败
S.top=S.base; //当栈为空时,栈底等于栈顶
S.stacksize=STACK_INIT_SIZE; //栈可存储的个数
return OK;
}
//3.清空栈
Status ClearStack(SqStack &S){
S.top=S.base; //栈顶和栈底指向同一个位置,即为空
return OK;
}
//4.判断栈是否为空
Status StackEmpty( SqStack S)
{
if(S.top==S.base)
return TRUE;
else
return ERROR;
}
//7.栈顶插入元素
Status Push(SqStack &S,SElemType &e)
{ //插入元素 e 为新的栈顶元素
if(S.top-S.base >= STACK_INIT_SIZE) //栈满的时候就需要追加存储空间
{
S.base=(SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!S.base) exit(OVERFLOW); //存储空间分配失败
S.top=S.base+S.stacksize; //栈底的位置可能改变,需要重新定位栈顶元素
//S.top 还是之前的那个没有存储的位置
S.stacksize = S.stacksize+STACKINCREMENT;
}
*S.top=e;
S.top++;
return OK;
}
//8.栈顶出栈元素
Status Pop(SqStack &S,SElemType &e){
//若栈不为空,则删除 S 的栈顶元素,用 e 返回其值,并返回 OK ,否则返回ERROR
if(S.top == S.base) return ERROR;
e=*(--S.top); //可以不加括号,但需要记住的是,需要让 top 指针减 1 ,再取出元素
return OK;
}
void LineEdit(){
SqStack S;
char ch;
//利用字符栈S,从终端接受一行并传送至调用过程的数据取
InitStack(S);
ch=getchar(); //从终端接收第一个字符
while(ch!=EOF){ //EOF为全文结束符
while(ch!=EOF && ch!='\n'){
switch(ch){
case '#':
Pop(S,ch); //仅当非空栈时退栈
break;
case '@':
ClearStack(S); //重置S为空栈
break;
default:
Push(S,ch); //其他有效字符,入栈,未考虑栈满的情况
}
ch=getchar(); //从终端接收下一个字符
}
while( !StackEmpty(S) ){
Pop(S,ch);
printf("%c",ch);
}
ClearStack(S); //重置栈S为空栈
if(ch!=EOF) ch=getchar();
}
}
void main(){
LineEdit();
}
应用举例:
迷宫求解的方法:
完整代码:(文件后缀名为 .cpp )
//头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
//宏定义
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
const int M=10;
const int N=10;
//typedef char SElemType;
typedef char Status;
//迷宫图
int maze[M][N]={
1,1,1,1,1,1,1,1,1,1,
1,0,0,1,0,0,0,1,0,1,
1,0,0,1,0,0,0,1,0,1,
1,0,0,0,0,1,1,0,0,1,
1,0,1,1,1,0,0,0,0,1,
1,0,0,0,1,0,0,0,0,1,
1,0,1,0,0,0,1,0,0,1,
1,0,1,1,1,0,1,1,0,1,
1,1,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,
};
int next_xy[4][2]={ {0,1} , {1,0} , {0,-1} , {-1,0} }; //用于计算下一次搜索位置的计算量
typedef struct{
int x;
int y;
}PostType; //用于记录在迷宫中的位置
typedef struct{
int ord; //道路块在路径上的“序号”
PostType seat; //道路块在迷宫中的“坐标位置”
int di; //从此通道块走向下一通道块的“方向”
}SElemType; //栈的元素类型
//栈的顺序结构体
typedef struct{
SElemType *base; //在栈构造之前和销毁之后,base 的值为NULL;
SElemType *top; //栈顶指针
int stacksize; //当前已分配的存储空间,以元素为单位
}SqStack;
//1.构建栈
Status InitStack(SqStack &S){
//构造一个空栈S
S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(! S.base) exit(OVERFLOW); //存储分配失败
S.top=S.base; //当栈为空时,栈底等于栈顶
S.stacksize=STACK_INIT_SIZE; //栈可存储的个数
return OK;
}
//3.清空栈
Status ClearStack(SqStack &S){
S.top=S.base; //栈顶和栈底指向同一个位置,即为空
return OK;
}
//4.判断栈是否为空
Status StackEmpty( SqStack S)
{
if(S.top==S.base)
return TRUE;
else
return ERROR;
}
//7.栈顶插入元素
Status Push(SqStack &S,SElemType &e)
{ //插入元素 e 为新的栈顶元素
if(S.top-S.base >= STACK_INIT_SIZE) //栈满的时候就需要追加存储空间
{
S.base=(SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!S.base) exit(OVERFLOW); //存储空间分配失败
S.top=S.base+S.stacksize; //栈底的位置可能改变,需要重新定位栈顶元素
//S.top 还是之前的那个没有存储的位置
S.stacksize = S.stacksize+STACKINCREMENT;
}
*S.top=e;
S.top++;
return OK;
}
//8.栈顶出栈元素
Status Pop(SqStack &S,SElemType &e){
//若栈不为空,则删除 S 的栈顶元素,用 e 返回其值,并返回 OK ,否则返回ERROR
if(S.top == S.base) return ERROR;
e=*(--S.top); //可以不加括号,但需要记住的是,需要让 top 指针减 1 ,再取出元素
return OK;
}
//判断当前点是否为可通
int Pass(PostType e){
int i,j;
i=e.x;
j=e.y;
if(maze[i][j]==0)
return 1; //maze[i][j]=0 为可通,返回1
else
return 0; //maze[i][j]=0 为不可通,返回0
}
//为可行的地方留下标记
int FootPrint(PostType e){
int i,j;
i=e.x;
j=e.y;
maze[i][j]=8; //进行已经访问的标记,用 8 来表示
return 1;
}
PostType NextPost(PostType &e,int di){
e.x=e.x+next_xy[di-1][0]; //已经定义好的 next_xy[4][2]={ {0,1} , {1,0} , {0,-1} , {-1,0} }
e.y=e.y+next_xy[di-1][1]; //
return e;
}
//留下不能通过的痕迹
int MarkPrint(PostType e){
int i,j;
i=e.x;
j=e.y;
maze[i][j]=1; //不能通过为 1
return 1;
}
//迷宫计算函数
Status MazePath(int maze[M][N],PostType start,PostType end){
//若迷宫 maze 中存在从入口 start 到出口 end 的通道,则求得一条存放在栈中(从栈底到栈顶),并返回TRUE ,否则返回 FALSE
SqStack S; //定义栈S
PostType currentPsot; //当前位置
int curstep=1; //记载步数的
SElemType e;
currentPsot=start; //开始位置
InitStack(S);
do{
if( Pass(currentPsot) ){ //当前位置是否可以通过,即是未曾走到过的通道块
FootPrint(currentPsot); //留下足迹
e.di=curstep;
e.seat.x=currentPsot.x; //记录当前可通节点的情况
e.seat.y=currentPsot.y;
e.di=1; //当前可通结点的访问方向为1,东南西北顺序访问
Push(S,e); //加入路径,将当前节点入栈,如果下一步结点不可通可返回上一节点继续
if( currentPsot.x==end.x && currentPsot.y==end.y ){ //如果到了出口终点的时候
printf("迷宫行走完成!\n");
return 1;
}
currentPsot=NextPost(currentPsot,1); //下一位置是当前位置的东邻
curstep++; //探索下一步
}
else{ //当前结点的位置不能通过
if(!StackEmpty(S)){
Pop(S,e); //回到上一个结点
while(e.di==4 && !StackEmpty(S)){ //当前结点的所有方向都访问过了,且栈不为空,没有路可以走了,只能返回上一步
MarkPrint(e.seat);
Pop(S,e); //出栈 出下一节点
}
if(e.di<4){ //还有其他结点没有访问
e.di++; //下一个方向
Push(S,e); //先做好存储保护
currentPsot=NextPost(e.seat,e.di);
}
}
}
}while( !StackEmpty(S) ); //栈不为空,继续寻找下一个可走的节点
printf("Unable to find the way through.\n");
return -1; //当所有的栈元素出栈以后,栈为空,且没有返回找到的路径,那么说明已经没有其他的路可走,找不到通路
}
void main(){
int i,j; //定义
SqStack S;
PostType start,end;
start.x=1;
start.y=1; //起点
end.x=8;
end.y=8; //终点
printf("The current maze is:\n");
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
printf(" %d",maze[i][j]);
printf("\n");
}printf("\n");
MazePath(maze,start,end); //调用迷宫函数
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
printf(" %d",maze[i][j]);
printf("\n");
}printf("\n");
}