第三章-栈(2)举例应用

栈的举例应用

--------------------------------------------------------------------------------------------------------------------------------

栈的举例应用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");

}











  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值