括号匹配检验
栈里存放的是左括号,右括号则与栈顶元素进行匹配。
- 若读入的是左括号,入栈
- 若读入的是右括号,则与栈顶元素进行匹配。若与栈顶的左括号是同类型的,则二者匹配,将栈顶的左括号出栈;若不是同类型的,则括号匹配检验出错误。
#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*+