数据结构:栈的应用 C语言版 -(1)

一 进制转换:

十进制 N 和 其他进制 d 之间的转换 公式:
N = ( N ÷ d ) ∗ d + N % d N=(N\div d)*d+N\%d N=(N÷d)d+N%d
例: ( 1348 ) 10 = ( 2504 ) 8 (1348)_{10}=(2504)_8 (1348)10=(2504)8 运算过程如下:
在这里插入图片描述
示例:

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "LinkStack.h"



//进制转换
int main()
{

	LinkStack * stack = NULL;
	stack = LinkStack_Create();
	int arr[30] = { 0 };
	int i = 0;
	int sys = 0;
	int num = 0;

	printf("请输入进制:\n");
	scanf("%d", &sys);
	printf("请输入待转换的数字:\n");
	scanf("%d", &num);

	printf("\n\n");

	while (num)
	{
		arr[i] = num%sys;
		LinkStack_Push(stack, &arr[i]);
		num = num / sys;
		i++;
	}

	printf("转换 %d 进制结果= ",sys);
	while (LinkStack_Size(stack) > 0)
	{
		int *n = (int*)LinkStack_Pop(stack);
		if (sys==16)
		{
			printf("%X", *n);
		}
		else
		{
			printf("%d", *n);
		}
		
	}

	printf("\n\n");

	LinkStack_Destroy(stack);

	system("pause");


	return 0;
}

在这里插入图片描述
在这里插入图片描述
使用的栈结构见博客:数据结构:栈(Stack 链式存储结构) C语言版

2:基于中缀和后缀表达式的括号匹配和算式计算

基于栈的特性和就近匹配原则

中缀表达式:

符合我们习惯的数学表达式叫做中缀表达式 ,例如: 9 + ( 3 − 1 ) ∗ 5 + 8 / 2 9 + (3 - 1) * 5 + 8 / 2 9+(31)5+8/2 ,等这种日常表达式。
明显特正就是运算符号在数字中间

后缀表达式:

后缀表达式是一种不需要括号的后缀表达法,也称逆波兰表示。
例如:

  • ( 中 缀 ) 8 + ( 3 – 1 ) ∗ 5 = > ( 后 缀 ) 831 – 5 ∗ + (中缀)8 + ( 3 – 1 ) * 5 => (后缀)8 3 1 – 5 * + ()8+(31)5=>()8315+
  • ( 中 缀 ) 1 + 2 ∗ 3 = > ( 后 缀 ) 123 ∗ + (中缀)1 + 2 * 3 => (后缀)1 2 3 * + ()1+23=>()123+
  • ( 中 缀 ) 5 + 4 = > ( 后 缀 ) 54 + (中缀)5 + 4=>(后缀) 5 4 + ()5+4=>()54+

明显特征就是运算符号在数字后面,后缀表达式更符合计算机运算习惯。

中缀转后缀

栈数据结构对于中缀转后缀规则:
遍历中缀表达式中的数字和符号
对于数字:直接输出
对于符号:

  • 左括号:进栈
  • 运算符号:与栈顶符号进行优先级比较,若栈顶符号优先级低:此符合进栈 (默认栈顶若是左括号,左括号优先级最低)若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈。
  • 右括号:将栈顶符号弹出并输出,直到匹配左括号(弹出左括号,不输出)

遍历结束:将栈中的所有符号弹出并输出。

运算符的优先关系:
任意两个相继出现的算符 θ 1 \theta_1 θ1 θ 2 \theta_2 θ2 之间的优先关系之多是下面3中关系之一。

  1. θ 1 < θ 2 \theta_1 < \theta_2 θ1<θ2 θ 1 \theta_1 θ1 的优先权低于 θ 2 \theta_2 θ2
  2. θ 1 = θ 2 \theta_1 = \theta_2 θ1=θ2 θ 1 \theta_1 θ1 的优先权等于 θ 2 \theta_2 θ2
  3. θ 1 > θ 2 \theta_1 > \theta_2 θ1>θ2 θ 1 \theta_1 θ1 的优先权高于 θ 2 \theta_2 θ2

在这里插入图片描述

示例:
在这里插入图片描述
基于栈的后缀表达式计算方法:
例: 8 + ( 3 − 1 ) ∗ 5 = = > 831 − 5 ∗ + 8+(3-1)*5==>831-5*+ 8+(31)5==>8315+

在这里插入图片描述

算法实现

1:括号匹配

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "LinkStack.h"

int isLeft(char c)
{
	int ret = 0;

	switch (c)
	{
	case '<':
	case '(':
	case '[':
	case '{':
	case '\'':
	case '\"':
		ret = 1;
		break;
	default:
		ret = 0;
		break;
	}

	return ret;
}

int isRight(char c)
{
	int ret = 0;

	switch (c)
	{
	case '>':
	case ')':
	case ']':
	case '}':
	case '\'':
	case '\"':
		ret = 1;
		break;
	default:
		ret = 0;
		break;
	}

	return ret;
}

int match(char left, char right)
{
	int ret = 0;

	switch (left)
	{
	case '<':
		ret = (right == '>');
		break;
	case '(':
		ret = (right == ')');
		break;
	case '[':
		ret = (right == ']');
		break;
	case '{':
		ret = (right == '}');
		break;
	case '\'':
		ret = (right == '\'');
		break;
	case '\"':
		ret = (right == '\"');
		break;
	default:
		ret = 0;
		break;
	}

	return ret;
}

int scanner(const char* code)
{
	LinkStack* stack = LinkStack_Create();
	int ret = 0;
	int i = 0;

	while (code[i] != '\0')
	{
		if (isLeft(code[i]))
		{
			LinkStack_Push(stack, (void*)(code + i)); //&code[i]
		}

		if (isRight(code[i]))
		{
			char* c = (char*)LinkStack_Pop(stack);

			if ((c == NULL) || !match(*c, code[i]))
			{
				printf(" 【%c】 错误匹配  【%c】 , \n", code[i],*c);
				ret = 0;
				break;
			}
		}

		i++;
	}

	if ((LinkStack_Size(stack) == 0) && (code[i] == '\0'))
	{
		printf("合格代码!\n");
		ret = 1;
	}
	else
	{
		printf("错误代码!\n");
		ret = 0;
	}

	LinkStack_Destroy(stack);

	return ret;
}

void main()
{
	const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0; return 0;} ";

	scanner(code);
	system("pause");
	return;
}

下面这段代码 a[0 少了一个 ] 号,进行测试括号匹配

#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0; return 0;} "

在这里插入图片描述
补全 a[0] 进行测试
在这里插入图片描述
2:中缀转后缀

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "linkstack.h"

int isNumber(char c)
{
	return ('0' <= c) && (c <= '9');
}

int isOperator(char c)
{
	return (c == '+') || (c == '-') || (c == '*') || (c == '/');
}

int isLeft(char c)
{
	return (c == '(');
}

int isRight(char c)
{
	return (c == ')');
}

int priority(char c)
{
	int ret = 0;

	if ((c == '+') || (c == '-'))
	{
		ret = 1;
	}

	if ((c == '*') || (c == '/'))
	{
		ret = 2;
	}

	return ret;
}

void output(char c)
{
	if (c != '\0')
	{
		printf("%c", c);
	}
}

void transform(const char* exp)
{
	int i = 0;
	LinkStack* stack = LinkStack_Create();

	while (exp[i] != '\0')
	{
		if (isNumber(exp[i]))
		{
			output(exp[i]);
		}
		else if (isOperator(exp[i]))
		{
			while (priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)))
			{
				output((char)(int)LinkStack_Pop(stack));
			}

			LinkStack_Push(stack, (void*)(int)exp[i]);
		}
		else if (isLeft(exp[i]))
		{
			LinkStack_Push(stack, (void*)(int)exp[i]);
		}
		else if (isRight(exp[i]))
		{
			//char c = '\0';
			while (!isLeft((char)(int)LinkStack_Top(stack)))
			{
				output((char)(int)LinkStack_Pop(stack));
			}

			LinkStack_Pop(stack);
		}
		else
		{
			printf("Invalid expression!");
			break;
		}

		i++;
	}

	while ((LinkStack_Size(stack) > 0) && (exp[i] == '\0'))
	{
		output((char)(int)LinkStack_Pop(stack));
	}

	LinkStack_Destroy(stack);
}

int main()
{
	transform("8+(3-1)*5");

	printf("\n");
	system("pause");
	return 0;
}

在这里插入图片描述
3:后缀表达式计算

#include "stdio.h"
#include "stdlib.h"
#include "linkstack.h"

int isNumber3(char c)
{
	return ('0' <= c) && (c <= '9');
}

int isOperator3(char c)
{
	return (c == '+') || (c == '-') || (c == '*') || (c == '/');
}

int value(char c)
{
	return (c - '0');
}

int express(int left, int right, char op)
{
	int ret = 0;

	switch (op)
	{
	case '+':
		ret = left + right;
		break;
	case '-':
		ret = left - right;
		break;
	case '*':
		ret = left * right;
		break;
	case '/':
		ret = left / right;
		break;
	default:
		break;
	}

	return ret;
}

int compute(const char* exp)
{
	LinkStack* stack = LinkStack_Create();
	int ret = 0;
	int i = 0;

	while (exp[i] != '\0')
	{
		if (isNumber3(exp[i]))
		{
			LinkStack_Push(stack, (void*)value(exp[i]));
		}
		else if (isOperator3(exp[i]))
		{
			int right = (int)LinkStack_Pop(stack);
			int left = (int)LinkStack_Pop(stack);
			int result = express(left, right, exp[i]);

			LinkStack_Push(stack, (void*)result);
		}
		else
		{
			printf("Invalid expression!");
			break;
		}

		i++;
	}

	if ((LinkStack_Size(stack) == 1) && (exp[i] == '\0'))
	{
		ret = (int)LinkStack_Pop(stack);
	}
	else
	{
		printf("Invalid expression!");
	}

	LinkStack_Destroy(stack);

	return ret;
}

int main()
{
	printf("8 + (3 - 1) * 5  = %d\n", compute("831-5*+"));
	system("pause");
	return 0;
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值