数据结构:栈的应用举例(严蔚敏版)

本文将数据结构学习中栈的应用举例的几个例子规整到本文当中,经测试均准确!

1.数制转换

/*******************************************************************************
                 		       数据结构练习
--------------------------------------------------------------------------------
实 验 名: 栈的应用举例
实验说明: 数制转换
时    间: 2017-7-2   
作    者: Elvan
*******************************************************************************/
#include <stdio.h>  
#include <malloc.h>   //malloc,realloc  
#include <math.h>     //含有overflow  
#include <iostream>

using namespace std;

#define STACK_INIT_SIZE 100   //栈的初始空间大小  
#define STACKINCREAMENT 10    //增加空间

/*数据类型定义*/
typedef int SElemType;
typedef struct{
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;

//----------------函数声明--------------
void InitStack(SqStack &S);//初始化空栈  
bool StackEmpty(SqStack S);//判空  
void GetTop(SqStack S, SElemType &e);//获得栈顶元素  
void Push(SqStack &S, SElemType e);//进栈  
void Pop(SqStack &S, SElemType &e);//出栈  
void convert(SqStack &S, int N, int n);//十进制转N进制  

/*构造一个空栈*/
void InitStack(SqStack &S)
{
	S.base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
	if (!S.base) exit(OVERFLOW);   //存储分配失败
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
}

/*栈的判空函数*/
bool StackEmpty(SqStack S)
{
	if (S.base == S.top)
		return true;
	else 
		return false;
}

/*获得栈顶元素*/
void GetTop(SqStack S, SElemType &e)
{
	if (S.top == S.base) return;
	else
		e = *(S.top - 1);
}

/*进栈*/
void Push(SqStack &S, SElemType e)
{
	if (S.top - S.base >= S.stacksize)
	{
		S.base = (SElemType*)realloc(S.base,(S.stacksize+STACKINCREAMENT)*sizeof(SElemType));
		if (!S.base) exit(OVERFLOW);
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREAMENT;
	}
	*S.top++ = e;   //注意:相当于*S.top =e;S.top++;
}

/*出栈*/
void Pop(SqStack &S, SElemType &e)
{
	if (S.top == S.base) return;
	e = *--S.top;   //注意:相当于--S.top;S.top =e;
}

/*数制的转换函数*/
void convert(SqStack &S, int N, int n)
{
	InitStack(S);
	while (N)
	{
		Push(S, N % n);
		N = N / n;
	}
	cout << "转换为" << n << "进制之后的数为:";
	while (!StackEmpty(S))
	{
		SElemType e;
		Pop(S, e);
		cout << e;
	}
	cout << endl;
}

int main()
{
	/*数制的转换过程*/
	int n, N;//要转换成的进制数和要转换的数  
	SqStack s;
	InitStack(s);//初始化空栈  
	cout << "请输入需要十进制数:";
	cin >> N;
	cout << endl;
	cout << "请输入需要转换的进制数:";
	cin >> n;
	cout << endl;
	convert(s, N, n);
}
测试结果如下图。

2.括号匹配的检验

/*******************************************************************************
                 		       数据结构练习
--------------------------------------------------------------------------------
实 验 名: 栈的应用举例
实验说明: 括号检验
时    间: 2017-7-2   
作    者: Elvan
*******************************************************************************/
#include <stdio.h>  
#include <malloc.h>   //malloc,realloc  
#include <math.h>     //含有overflow  
#include <iostream>

using namespace std;

#define STACK_INIT_SIZE 100   //栈的初始空间大小  
#define STACKINCREAMENT 10    //增加空间

/*数据类型定义*/
typedef char SElemType;
typedef struct{
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;

//----------------函数声明--------------
void InitStack(SqStack &S);//初始化空栈  
bool StackEmpty(SqStack S);//判空  
void GetTop(SqStack S, SElemType &e);//获得栈顶元素  
void Push(SqStack &S, SElemType e);//进栈  
void Pop(SqStack &S, SElemType &e);//出栈  
bool MatchBracket(SqStack S, char a[]); //括号检测函数

/*构造一个空栈*/
void InitStack(SqStack &S)
{
	S.base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
	if (!S.base) exit(OVERFLOW);   //存储分配失败
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
}

/*栈的判空函数*/
bool StackEmpty(SqStack S)
{
	if (S.base == S.top)
		return true;
	else 
		return false;
}

/*获得栈顶元素*/
void GetTop(SqStack S, SElemType &e)
{
	if (S.top == S.base) return;
	else
		e = *(S.top - 1);
}

/*进栈*/
void Push(SqStack &S, SElemType e)
{
	if (S.top - S.base >= S.stacksize)
	{
		S.base = (SElemType*)realloc(S.base,(S.stacksize+STACKINCREAMENT)*sizeof(SElemType));
		if (!S.base) exit(OVERFLOW);
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREAMENT;
	}
	*S.top++ = e;   //注意:相当于*S.top =e;S.top++;
}

/*出栈*/
void Pop(SqStack &S, SElemType &e)
{
	if (S.top == S.base) return;
	e = *--S.top;   //注意:相当于--S.top;S.top =e;
}

/*括号匹配的转换函数*/
bool MatchBracket(SqStack S, char *a)
{
	int length = strlen(a);
	int i;
	SElemType e,x;
	for (i = 0; i < length; i++)
	{
		switch (a[i])
		{
		case '(': 
		case '[': 
		case '{': 
		case '<': Push(S, a[i]); break;
		case ')':{GetTop(S, e);
			if (e == '(')
				Pop(S, x);
			else return false;
		}break;
		case ']':{GetTop(S, e);
			if (e == '[')
				Pop(S, x);
			else return false; }break;
		case '}':{GetTop(S, e);
			if (e == '{')
				Pop(S, x);
			else return false; }break;
		case '>':{GetTop(S, e);
			if (e == '<')
				Pop(S, x);
			else return false; }break;
		default: break;
		}
	}
	if (StackEmpty(S))
		return true;
	else return false;
}

int main()
{
	cout << "请输入一组括号:";
	char a[50];
	cin >> a;
	SqStack s;
	InitStack(s);
	if (MatchBracket(s, a))
		cout << "括号匹配!" << endl;
	else
		cout << "括号不匹配!" << endl;
	return 0;
}

测试结果如下图。

3.行编辑程序

/*******************************************************************************
                 		       数据结构练习
--------------------------------------------------------------------------------
实 验 名: 栈的应用举例
实验说明: 行编辑程序
时    间: 2017-7-2   
作    者: Elvan
*******************************************************************************/
#include <stdio.h>  
#include <malloc.h>   //malloc,realloc  
#include <math.h>     //含有overflow  
#include <iostream>

using namespace std;

#define STACK_INIT_SIZE 100   //栈的初始空间大小  
#define STACKINCREAMENT 10    //增加空间

/*数据类型定义*/
typedef char SElemType;
typedef struct{
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;

//----------------函数声明--------------
void InitStack(SqStack &S);//初始化空栈  
bool StackEmpty(SqStack S);//判空  
void GetTop(SqStack S, SElemType &e);//获得栈顶元素  
void Push(SqStack &S, SElemType e);//进栈  
void Pop(SqStack &S, SElemType &e);//出栈  
void ClearStack(SqStack &S);  //清空栈
void DestroyStack(SqStack &S);  //销毁栈
void LineEdit(); //行编辑程序

/*构造一个空栈*/
void InitStack(SqStack &S)
{
	S.base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
	if (!S.base) exit(OVERFLOW);   //存储分配失败
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
}

/*栈的判空函数*/
bool StackEmpty(SqStack S)
{
	if (S.base == S.top)
		return true;
	else 
		return false;
}

/*获得栈顶元素*/
void GetTop(SqStack S, SElemType &e)
{
	if (S.top == S.base) return;
	else
		e = *(S.top - 1);
}

/*进栈*/
void Push(SqStack &S, SElemType e)
{
	if (S.top - S.base >= S.stacksize)
	{
		S.base = (SElemType*)realloc(S.base,(S.stacksize+STACKINCREAMENT)*sizeof(SElemType));
		if (!S.base) exit(OVERFLOW);
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREAMENT;
	}
	*S.top++ = e;   //注意:相当于*S.top =e;S.top++;
}

/*出栈*/
void Pop(SqStack &S, SElemType &e)
{
	if (S.top == S.base) return;
	e = *--S.top;   //注意:相当于--S.top;S.top =e;
}

/*清空栈*/
void ClearStack(SqStack &S)
{
	S.top = S.base;
}

/*销毁栈 */
void DestroyStack(SqStack &S)
{
	free(S.base);
	S.base = S.top = NULL;
	S.stacksize = 0;
}

/*利用字符栈S,从终端接收一行并传送至调用过程的数据区*/
void LineEdit()
{
	SqStack s;
	InitStack(s);
	SElemType ch = getchar();
	SElemType c;
	while (ch != ' ')  //按空格结束
	{
		//EOF为全文结束符
		if(ch != ' ' &&ch != '\n')
		{
			switch (ch)
			{
			case '#':Pop(s, c);   break;
			case '@':ClearStack(s);   break;
			default: Push(s, ch);  break;
			}
		}
		else
		{
			int num = s.top - s.base;
			char *pt = new char[num];//建立一个临时字符数组,用来存放从S中弹出的值 
			while (s.top != s.base)
			{
				SElemType e;
				Pop(s, e); 
				*(pt++) = e;//将弹出的数据存放到临时字符数组中  
			}
			for (int i = 1; i <= num; i++)
				cout << *(--pt);//pt先减1的原因是在(*pt++)操作中当数据输入完成后,pt仍加1,此时因此要先减1  
			delete[]pt;//销毁临时数组  
		}
		ch = getchar();   //从终端接收下一个字符
	}
	ClearStack(s);
}

int main()
{
	LineEdit();
} 

测试结果如下图。


4.迷宫行走

/*******************************************************************************
                 		       数据结构练习
--------------------------------------------------------------------------------
实 验 名: 栈的应用举例
实验说明: 迷宫行走
时    间: 2017-7-3   
作    者: Elvan
*******************************************************************************/
#include <stdio.h>  
#include <malloc.h>   //malloc,realloc  
#include <math.h>     //含有overflow  
#include <iostream>
#include <time.h>

using namespace std;

#define STACK_INIT_SIZE 100   //栈的初始空间大小  
#define STACKINCREAMENT 10    //增加空间
#define MAXLEN 10  
/*数据类型定义*/
typedef struct
{
	int r;  //位置的横坐标  
	int c;  //位置的纵坐标  
}PosType;

typedef struct
{
	int ord;//路径中的“序号”
	PosType seat;  //“行走位置”
	int di;   //行走的"方向"
}SElemType;
	
typedef struct{
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;

typedef struct
{
	int r;  //迷宫的行数,除去外墙  
	int c;  //迷宫的列数,除去外墙  
	char adr[MAXLEN][MAXLEN];
}MazeType;  //迷宫类型  

//----------------函数声明--------------
void InitStack(SqStack &S);//初始化空栈  
bool StackEmpty(SqStack S);//判空  
void GetTop(SqStack S, SElemType &e);//获得栈顶元素  
void Push(SqStack &S, SElemType e);//进栈  
void Pop(SqStack &S, SElemType &e);//出栈  
void ClearStack(SqStack &S);  //清空栈
void DestroyStack(SqStack &S);  //销毁栈
void InitMaze(MazeType &maze);  //初始化一个迷宫
bool Pass(const MazeType &M, PosType curpos);// 判断当前位置是否可以通过
bool Pass(const MazeType &M, PosType curpos);
PosType NextPos(PosType curpos, int i);

//----------------函数定义--------------
/*构造一个空栈*/
void InitStack(SqStack &S)
{
	S.base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
	if (!S.base) exit(OVERFLOW);   //存储分配失败
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
}

/*栈的判空函数*/
bool StackEmpty(SqStack S)
{
	if (S.base == S.top)
		return true;
	else 
		return false;
}

/*获得栈顶元素*/
void GetTop(SqStack S, SElemType &e)
{
	if (S.top == S.base) return;
	else
		e = *(S.top - 1);
}

/*进栈*/
void Push(SqStack &S, SElemType e)
{
	if (S.top - S.base >= S.stacksize)
	{
		S.base = (SElemType*)realloc(S.base,(S.stacksize+STACKINCREAMENT)*sizeof(SElemType));
		if (!S.base) exit(OVERFLOW);
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREAMENT;
	}
	*S.top++ = e;   //注意:相当于*S.top =e;S.top++;
}

/*出栈*/
void Pop(SqStack &S, SElemType &e)
{
	if (S.top == S.base) return;
	e = *--S.top;   //注意:相当于--S.top;S.top =e;
}

/*清空栈*/
void ClearStack(SqStack &S)
{
	S.top = S.base;
}

/*销毁栈 */
void DestroyStack(SqStack &S)
{
	free(S.base);
	S.base = S.top = NULL;
	S.stacksize = 0;
}

/*初始化一个迷宫*/
void InitMaze(MazeType &maze)
{
	maze.c = 8;  //迷宫的行数  
	maze.r = 8;  //迷宫的列数  
	int i, j;
	for (i = 0; i < 10; ++i)
	{
		//初始化外墙  
		maze.adr[0][i] = '#';
		maze.adr[9][i] = '#';
		maze.adr[i][0] = '#';
		maze.adr[i][9] = '#';
	}
	srand(time(NULL));
	for (i = 1; i < 9; ++i)  //生成迷宫  
	{
		for (j = 1; j < 9; ++j)
		{
			int i_rand = rand() % 2;
			if (i_rand == 1)
				maze.adr[i][j] = '1';
			else
				maze.adr[i][j] = '0';
		}
	}
}

/*判断当前位置是否可通*/
bool Pass(const MazeType &M, PosType curpos)
{
	  
	if (M.adr[curpos.r][curpos.c] == '1')
		return true;
	else
		return false;
}

/*探索下一位置并返回下一位置的坐标  */
PosType NextPos(PosType curpos, int i)
{
	
	PosType nextPos = curpos;
	switch (i)
	{
	case 1:nextPos.c += 1; break;//向东一步  
	case 2:nextPos.r += 1; break;//向南一步  
	case 3:nextPos.c -= 1; break;//向西一步  
	case 4:nextPos.r -= 1; break;//向北一步  
	default:
		exit(0);
	}
	return nextPos;
}

/*曾走过但不通留下标记*/
void MarkPrint(MazeType &M, PosType curpos)
{
	M.adr[curpos.r][curpos.c] = 'x'; //@表示走过但不通  
}

/*走过的地方留下足迹*/
void FootPrint(MazeType &M, PosType curpos)
{
	 
	M.adr[curpos.r][curpos.c] = '*';//表示可通,用*表示  
}

/*寻找迷宫路径*/
bool MazePath(MazeType &M, PosType start, PosType end)
{
	//若迷宫M中存在从入口start到出口end的通道,则求得一条存放在栈中,  
	//并返回TRUE,否则返回FALSE;  
	SqStack S;
	InitStack(S);
	SElemType e;
	PosType curpos = start;  //设定当前位置为入口位置  
	int curstep = 1; //探索第一步  
	do
	{
		if (Pass(M, curpos))
		{
			//当前位置可以通过,是未曾走过的通道块  
			FootPrint(M, curpos);   //留下足迹  
			e.ord = curstep;
			e.seat = curpos;
			e.di = 1;
			Push(S, e);//加入路径  
			if (curpos.r == end.r && curpos.c == end.c) return true;//到达出口  
			curpos = NextPos(curpos, 1);  //下一位置是当前位置的东邻  
			curstep++;  //探索下一步  
		}
		else
		{
			//当前位置不能通过  
			if (!StackEmpty(S))
			{
				Pop(S, e);
				while (e.di == 4 && !StackEmpty(S))//栈不空,四周均不通  
				{
					//留下不能通过的标记,并退回一步  
					MarkPrint(M, e.seat);
					Pop(S, e);
				}
				if (e.di < 4)
				{
					++e.di;//换下一个方向探索  
					Push(S, e);
					curpos = NextPos(e.seat, e.di);//设定当前位置是该新方向上的相邻块  
				}
			}
		}
	} while (!StackEmpty(S));
	return false;
}

void PrintMaze(const MazeType &M)
{
	//输出迷宫  
	int i, j;
	for (i = 0; i < 11; ++i)
	{
		if (0 == i)
			printf("  ");
		else
			printf("%2d", i - 1);//打印列名  
	}
	printf("\n");
	for (i = 0; i < 10; ++i)
	{
		printf("%2d", i);
		for (j = 0; j < 10; ++j)
		{
			printf("%2c", M.adr[i][j]);
		}
		printf("\n");
	}
}

/*主函数*/
int main()
{
	MazeType M;
	while (1)
	{
		InitMaze(M);
		cout << "迷宫为:" << endl;
		cout << "其中'#'代表外墙,'1'表示通道,'0'表示不可走" << endl;
		PrintMaze(M);
		PosType In, Out;
		cout << "请输入入口坐标:";
		cin >> In.r >> In.c;
		cout << "请输入出口坐标:";
		cin >> Out.r >> Out.c;
		if (MazePath(M, In, Out))
		{
			cout << "其中*表示路径,x表示此路不通:" << endl;
			PrintMaze(M);
		}
		else
			cout << "没有通道" << endl;
		system("pause");
	}
	return 0;
}

测试结果如下。



猜你喜欢

转载自blog.csdn.net/weixin_38169413/article/details/74389695