栈的应用--括号匹配,运算表达式

括号匹配检验

栈里存放的是左括号,右括号则与栈顶元素进行匹配。

  • 若读入的是左括号,入栈
  • 若读入的是右括号,则与栈顶元素进行匹配。若与栈顶的左括号是同类型的,则二者匹配,将栈顶的左括号出栈;若不是同类型的,则括号匹配检验出错误。
#include<iostream>
using namespace std;

#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define SElemType char
#define Status int
#define OK 1
#define ERROR 0
typedef struct {
	SElemType* base;
	SElemType* top;  //栈顶指针
	int stacksize;  //当前已分配的存储空间
}SqStack;

Status 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;
	return OK;
}
Status GetTop(SqStack S, SElemType& e)
{
	if (S.top == S.base) return ERROR;  //栈为空
	e = *(S.top - 1);
	return OK;
}
Status Push(SqStack& S, SElemType& e)
{
	if (S.top - S.base >= S.stacksize)  //栈满,追加存储空间
	{
		S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!S.base) exit(OVERFLOW);
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREMENT;
	}
	*S.top++ = e;
	return OK;
}
Status Pop(SqStack& S, SElemType& e)
{
	if (S.top == S.base) return ERROR;
	e = *--S.top;
	return OK;
}
Status StackTraverse(SqStack S)
{
	SElemType* p;
	p = S.base;
	while (p < S.top)
	{
		cout << *p << ' ';
		p++;
	}
	cout << endl;
	return OK;
}
Status StackEmpty(SqStack S)
{
	if (S.base == S.top) return 1;
	else return 0;
}
Status matching(char* exp)
{
	int state = 1, i = 0;
	SqStack s;
	SElemType e;
	InitStack(s);
	while (i < strlen(exp) && state)
	{
		switch (exp[i])
		{
		case '[':
		case '(':
		case '{':
		{
			Push(s, exp[i]);  //让该左括号入栈
			i++;
			break;
		}
		case ']':
		{
			GetTop(s, e);
			if (!StackEmpty(s) && e == '[')
			{
				Pop(s, e);
				i++;
			}
			else state = 0;  //state=0出错
			break;
		}
		case ')':
		{
			GetTop(s, e);
			if (!StackEmpty(s) && e == '(')
			{
				Pop(s, e);
				i++;
			}
			else state = 0;
			break;
		}
		case '}':
		{
			GetTop(s, e);
			if (!StackEmpty(s) && e == '{')
			{
				Pop(s, e);
				i++;
			}
			else state = 0;
			break;
		}
		default:
		{
			i++;
			break;
		}
		}
	}
	if (state && StackEmpty(s))
	{
		cout << "检查无误" << endl;
		return OK;
	}
	else
	{
		cout << "出现错误" << endl;
		return ERROR;
	}
}
int main()
{
	char a[100];
	cout << "输入待检验的括号字符串" << endl;
	cin >> a;
	matching(a);
	return 0;
}

后缀表达式计算

  • 如果是操作数,则直接入栈。
  • 如果是操作符,连续出栈两个操作数,用该操作符计算。

时间复杂度O(N)

#include<iostream>
using namespace std;

#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define SElemType int
#define Status int
#define OK 1
#define ERROR 0
typedef struct {
	SElemType* base;
	SElemType* top;  //栈顶指针
	int stacksize;  //当前已分配的存储空间
}SqStack;

Status 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;
	return OK;
}
Status GetTop(SqStack S, SElemType& e)
{
	if (S.top == S.base) return ERROR;  //栈为空
	e = *(S.top - 1);
	return OK;
}
Status Push(SqStack& S, SElemType& e)
{
	if (S.top - S.base >= S.stacksize)  //栈满,追加存储空间
	{
		S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!S.base) exit(OVERFLOW);
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREMENT;
	}
	*S.top++ = e;
	return OK;
}
Status Pop(SqStack& S, SElemType& e)
{
	if (S.top == S.base) return ERROR;
	e = *--S.top;
	return OK;
}
Status StackTraverse(SqStack S)
{
	SElemType* p;
	p = S.base;
	while (p < S.top)
	{
		cout << *p << ' ';
		p++;
	}
	cout << endl;
	return OK;
}
//后缀表达式的计算
int Compute(char* str)
{
    int i = 0;
    SqStack s;
    InitStack(s);
    SElemType number_to_push, num1, num2;
    while (str[i] != '\0') //防止字符串走到末尾
    {
        if (str[i] != ' ')//跳过空格
        {
            if (str[i] >= '0' && str[i] <= '9') //是数字
            {
                number_to_push = 0;
                while (str[i] != ' ' && str[i]) //将字符串转化为数字,每位取出计算
                {
                    number_to_push = number_to_push * 10 + (str[i] - '0');
                    i++;
                }
                Push(s, number_to_push);
            }
            else  //是操作符
            {
                Pop(s, num2);
                Pop(s, num1);
                switch (str[i])
                {
                case '+': {
                    num1 += num2;
                    break;
                }
                case '-': {
                    num1 -= num2;
                    break;
                }
                case '*': {
                    num1 *= num2;
                    break;
                }
                case '/': {
                    num1 /= num2;
                    break;
                }
                case '%': {
                    num1 %= num2;
                    break;
                }
                }
                Push(s, num1);  //num1为进行操作后的结果
            }
        }
        i++;
    }
    Pop(s, num1);  //最后的结果
    return num1;
}
//测试用例
void test01()
{
    char arr[] = "6  2 / 3 - 4  2 * +";
    int answer = Compute(arr);
    printf("%s = %d", arr, answer);
}

int main()
{
    test01();
	return 0;
}

中缀表达式转后缀表达式

后缀表达式方便计算,所以通常将运算表达式转化为后缀表达式。

栈用来放运算符。

1.从左到右扫描中缀表达式

若为数字,则直接输出

若为运算符,左括号直接入栈(入栈前优先级最高, 入栈后最低)

                     右括号,将运算符栈中的元素依次出栈并输出,直到遇到运算符栈中的左括号

                     其他,将运算符栈的元素依次输出,直到遇到比当前运算符优先级更低的符号或者左                       括号(也就是说,若栈顶元素的优先级高于等于当前运算符的优先级,则栈顶元素需                         出栈)。然后将当前运算符入栈。

2.扫描结束,将运算符栈中的剩余元素依次出栈

例子: a + b * c + ( d * e + f ) * g

a为数字,直接输出

+为运算符,其他,入栈

b为数字,输出

*为运算符,其他,栈顶元素为+,优先级比*低,不需出栈,将*入栈

c为数字,输出

+为运算符,其他,栈顶元素为*,优先级比+高,出栈,栈顶元素为+,优先级等于+,出栈,此+入栈。

左括号,入栈

d为数字,输出

*为运算符,其他,栈顶元素为左括号,优先级低于*, 无出栈元素,*入栈

e为数字,入栈

+为运算符,其他,栈顶元素为*,优先级比+高,出栈,栈顶元素为左括号,优先级低于+,此+入栈

f为数字,输出

右括号,栈中元素一直出栈,直到遇到左括号,所以+出栈,左括号出栈但不输出

*为运算符,其他,栈顶元素为+,优先级低于*,*入栈

g为数字,输出

将栈中元素依次出栈

最后得到结果abc*+de*f+g*+

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值