10.数据结构 栈的应用举例

1.进制转换

在这里插入图片描述

#define N 8//定义待转换的进制N(二进制-九进制)
typedef int SElemType;//定义栈元素类型为整数

void conversion1()
{
	//对于输入的任意一个非负十进制整数,打印输出与其等值的N进制数
	SqStack s;
	unsigned n;//非负整数
	SElemType e;
	InitStack(s);//初始化栈
	printf("将十进制整数n转换为%d进制数,请输入:n(>=0)=", N);
	scanf("%u", &n);//输入非负十进制整数n
	while (n)//当n不等于0
	{
		Push(s, n%N);//入栈n除以N的余数(N进制的低位)
		n = n / N;
	}
	while (!StackEmpty(s))//当栈不空
	{
		Pop(s, e);//弹出栈顶元素且赋值给e
		printf("%d", e);//输出e
	}
	printf("\n");
}

2.十进制转十六进制

在这里插入图片描述

void conversion2()//十进制->十六进制
{
	SqStack s;
	unsigned n;//非负整数
	SElemType e;
	InitStack(s);//初始化栈
	printf("将十进制整数n转换为十六进制数,请输入:n(>=0)=");
	scanf("%u", &n);//输入非负十进制整数n
	while (n)//当n不等于0
	{
		Push(s, n % 16);//入栈n除以16的余数(十六进制的低位)
		n = n / 16;
	}
	while (!StackEmpty(s))//当栈不空
	{
		Pop(s, e);//弹出栈顶元素且赋值给e
		if (e <= 9)
			printf("%d", e);
		else
			printf("%c", e + 55); //大于9的余数,输出相应的字符
	}
	printf("\n");
}

3.括号匹配的检验

typedef char SElemType;

void check()
{
	//对于输入的任一字符串,检验括号是否匹配
	SqStack s;
	SElemType ch[80], *p, e;
	InitStack(s);//初始化栈成功
	printf("请输入带括号(()、[]和{})的表达式\n");
	gets(ch);
	p = ch;//p指向字符串的首字符
	while (*p)//没到串尾
	{
		switch (*p)
		{
		case '(':
		case '[':
		case '{':
			Push(s, *p++);//左括号入栈,且p++
			break;
		case ')':
		case ']':
		case '}':
			if (!StackEmpty(s))//栈不空
			{
				Pop(s, e);//弹出栈顶元素
				if (!( e == '(' && *p == ')' || e == '[' && *p == ']' || e == '{' && *p == '}'))
				{
					//出现3中匹配情况之外的情况
					printf("左右括号不配对\n");
					exit(ERROR);
				}
			}
			else//栈空
			{
				printf("缺乏左括号\n");
				exit(ERROR);
			}
		default:
			p++;//其他字符不处理,指针向后移
		}
		if (StackEmpty(s))//字符串结束时栈空
			printf("括号匹配\n");
		else
			printf("缺乏左括号\n");
	}
}

4.行编辑程序

FILE *fp;
void copy(SElemType c)
{
	//将字符c送至fp所指的文件中
	fputc(c, fp);
}
void LineEdit()
{
	//利用字符栈s,从终端接受一行并送至调用过程的数据区
	SqStack s;
	char ch;
	InitStack(s);
	printf("请输入一个文本文件,^Z结束输入:\n");
	ch = getchar();
	while (ch != EOF)
	{
		//当全文没结束(EOF为^Z键,全文结束)
		while (ch != EOF && ch != '\n')
		{
			//当全文没结束且没到行末(不说换行符)
			switch (ch)
			{
			case '#':
				if (!StackEmpty(s))
					Pop((s, ch));//仅当栈非空时退栈,c可由ch代替
				break;
			case '@':
				ClearStack(s);//重置s为空栈
				break;
			default:
				Push(s, ch);//其他字符进栈
			}
			ch = getchar();//从终端接受下一个字符
		}
		StackTraverse(s, copy);//将从栈底到栈顶的栈内字符传送至文件
		fputc('\n', fp);//向文件输入一个换行符
		ClearStack(s);//重置s为空栈
		if (ch != EOF)
			ch = getchar();
	}
	DestroyStack(s);
}

5.迷宫问题

在这里插入图片描述

struct PosType//迷宫坐标位置类型
{
	int x;//行值
	int y;//列值
};
#define MAXLENGTH 25 //设迷宫的最大行列为25
typedef int MazeType[MAXLENGTH][MAXLENGTH];//迷宫数组类型[行][列]
MazeType m;//迷宫数组
int x, y;//迷宫的行数,列数
PosType begin1, end1;//迷宫的入口坐标,出口坐标
void Print()
{
	//输出迷宫的解(m数组)
	int i, j;
	for (i = 0; i < x; i++)
	{
		for (j = 0; j < y; j++)
		{
			printf("%3d", m[i][j]);
		}
		printf("\n");
	}
}
void Init(int k)
{
	//设定迷宫的布局(墙为值0,通道值为k)
	int i, j, x1, y1;
	printf("请输入迷宫的行数,列数(包括外墙):");
	scanf("%d,%d", &x, &y);
	for (i = 0; i < x; i++)//定义周边值为0(外墙)
	{
		m[0][i] = 0;//行周边
		m[x - 1][i] = 0;
	}
	for (i = 0; i < y; i++)
	{
		m[i][0] = 0;//列周边
		m[i][y - 1] = 0;
	}
	for (i = 1; i <= x - 1; i++)
	{
		for (j = 1; j <= y - 1; j++)
		{
			m[i][j] = k;//定义除外墙,其余都是通道,初值为k
		}
	}
	printf("请输入迷宫内墙单元数:");
	scanf("%d", &j);
	printf("请依次输入迷宫内墙每个单元的行数、列数:\n");
	for (i = 1; i <= j; i++)
	{
		scanf("%d,%d", &x1, y1);
		m[x1][y1] = 0;//修改墙的值为0
	}
	printf("迷宫结构如下:\n");
	Print();
	printf("输入入口的行数,列数:");
	scanf("%d,%d", &begin1.x, &begin1.y);
	printf("输入出口的行数,列数:");
	scanf("%d,%d", &end1.x, &end1.y);
}

6.利用栈求解迷宫问题

在这里插入图片描述

int curstep = 1;//当前足迹,初值(在入口处)为1
struct SElemType//栈的元素类型
{
	int ord;//通道块在路径上的“序号”
	PosType seat;//通道块在迷宫中的“坐标位置”
	int di;//从此通道块走向下一通道的“方向”(0-3表示东-北)
};
Status Pass(PosType b)
{
	//当迷宫m的b点的序号为1(可通过路径),返回OK;否则,返回ERROR
	if (m[b.x][b.y] == 1)
		return OK;
	else
		return ERROR;
}
void FootPrint(PosType a)
{
	//使迷宫m a点的值变为足迹(curstep)
	m[a.x][a.y] = curstep;
}
void NextPos(PosType &c, int di)
{
	//根据当前位置及移动方向,求得下一位置
	PosType direc[4] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };//{行增量,列增量},移动方向,依次是东南西北
	c.x += direc[di].x;
	c.y += direc[di].y;
}
void MarkPrint(PosType b)
{
	//使迷宫m的b点的序号变为-1(不能通过的路径)
	m[b.x][b.y] = -1;
}
Status MazePath(PosType start, PosType end)
{
	//若迷宫m中存在从入口start到出口end的通道,
	//则求得一条存放在栈中(从栈底到栈顶),并返回TRUE;否则返回FALSE
	SqStack S;//顺序栈
	PosType curpos;//当前位置
	SElemType e;//栈元素;
	InitStack(S);//初始化栈
	curpos = start;//当前位置在入口
	do
	{
		if (Pass(curpos))
		{
			//当前位置可以通过,即是未曾走到过的通道块
			FootPrint(curpos);//留下足迹
			e.ord = curstep;
			e.seat = curpos;
			e.di = 0;
			Push(S, e);//入栈当前位置及状态
			curstep++;//足迹加1
			if (curpos.x == end.x && curpos.y == end.y)//到达终点(出口)
				return TRUE;
			NextPos(curpos, e.di);//由当前位置及移动方向,确定下一个当前位置
		}
		else
		{
			//当前位置不能通过
			if (!StackEmpty(S))//栈不空
			{
				Pop(S, e);//退栈到前一位置
				curstep--;//足迹再减一
				while (e.di == 3 && !StackEmpty(S))//前一位置处于最后一个方向(北)
				{
					MarkPrint(e.seat);//在前一位置留下不能通过的标记(-1)
					Pop(S, e);//再退回一步
					curstep--;//足迹再减1
				}
				if (e.di < 3)//没到最后一个反向(北)
				{
					e.di++;//换下一个方向探索
					Push(S, e);//入栈该位置的下一个方向
					curstep++;//足迹加1
					curpos = e.seat;//确定当前位置
					NextPos(curpos, e.di);//确定下一个当前位置是该新方向上的相邻块
				}
			}
		}
	} while (!StackEmpty(S));
	return FALSE;
}
void main()
{
	Init(1);//初始化迷宫,通道值为1
	if (MazePath(begin1, end1))//有通路
	{
		printf("此迷宫从入口到出口的一条路径如下:\n");
		Print();//输出此通路
	}
	else
	{
		printf("此迷宫无通路\n");
	}
}

迷宫程序运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.表达式求值

char PreCede(SElemType t1, SElemType t2)
{
	//判断两符号的优先关系
	char f;
	switch (t2)
	{
	case '+':
	case '-':
		if (t1 == '(' || t1 == '\n')
			f = '<';//t1<t2
		else
			f = '>';//t1>t2
		break;
	case '*':
	case '/':
		if (t1 == '*' || t1 == '/' || t1 == ')')
			f = '>';//t1>t2
		else
			f = '<';//t1<t2
		break;
	case '(':
		if (t1 == ')')
		{
			printf("括号不匹配\n");
			exit(ERROR);
		}
		else
			f = '<';//t1<t2
		break;
	case ')':
		switch (t1)
		{
		case '(':
			f = '=';//t1=t2
			break;
		case '\n':
			printf("缺乏左括号\n");
			exit(ERROR);
		default:
			f = '>';//t1>t2
		}
		break;
	case '\n':
		switch (t1)
		{
		case '\n':
			f = '=';//t1=t2
			break;
		case '(':
			printf("缺乏左括号\n");
			exit(ERROR);
		default :
			f = '>';//t1>t2
		}
	}
	return f;
}

8

Status In(SElemType c)
{
	//判断c是否为7中运算符之一
	switch (c)
	{
	case '+':
	case '-':
	case '*':
	case '/':
	case '(':
	case ')':
	case '\n':
		return TRUE;
	default:
		return FALSE;
	}
}

9

SElemType Operate(SElemType a, SElemType theta, SElemType b)
{
	//做四则运算a、theta、b,返回运算结果
	switch (theta)
	{
	case '+':
		return a + b;
	case '-':
		return a - b;
	case '*':
		return a * b;
	}
	return a / b;
}

10.表达式求值

typedef char SElemType;//栈元素为字符型
SElemType EvaluateExpression()
{
	//算数表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
	SqStack OPTR, OPND;
	SElemType a, b, c, x;
	InitStack(OPTR);//初始化运算符栈OPTR和运算数栈OPND
	InitStack(OPND);
	Push(OPTR, '\n');//将换行符压入运算符栈OPTR栈底(改)
	c = getchar();//由键盘读入1个字符到c
	GetTop(OPTR, x);//将运算符栈OPTR的栈顶元素赋给x
	while (c != '\n' || x != '\n')//c和x不都是换行符
	{
		if (In(c))//c是7种运算符之一
		{
			switch (PreCede(x,c))//判断x和c的优先权
			{
			case '<':
				Push(OPTR, c);//栈顶元素x的优先权低,入栈c
				c = getchar();//由键盘读入下一个字符到c
				break;
			case '=':
				Pop(OPTR, x);//x='(' 且 c=')'情况,弹出'('给x(后又扔掉)
				c = getchar();//由键盘读入下一个字符到c(扔掉‘)’)
				break;
			case '>':
				Pop(OPTR, x);//栈顶元素x的优先权高,弹出运算符栈OPTR的栈顶元素给x(改)
				Pop(OPND, b);//依次弹出运算数栈OPND的栈顶元素给b,a
				Pop(OPND, a);
				Push(OPND, Operate(a, x, b));//做运算a x b,并将运算结果入运算数栈
			}
		}
		else if (c >= '0' && c <= '9')//c是操作数
		{
			Push(OPND, c - 48);//将该操作数的值(不是ASCII码)压入运算数栈OPND
			c = getchar();//由键盘读入下一个字符到c
		}
		else//c是非法字符
		{
			printf("出现非法字符\n");
			exit(ERROR);
		}
		GetTop(OPTR, x);//将运算符栈OPTR的栈顶元素赋给x
	}
	Pop(OPND, x);//弹出运算数栈OPND的栈顶元素(运算结果)给x(改此处)
	if (!StackEmpty(OPND));//运算数栈OPND不空(运算符栈OPTR仅剩‘\n’)
	{
		printf("表达式不正确|\n");
		exit(ERROR);
	}
	return x;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值