栈的概念 :一种特殊的线性表,其只允许在固定的一段进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。不含任何元素的栈称为空栈,栈有称为后进先出的线性表。
栈的特性:后进先出(LILO)特殊线性表
栈功能:将数据从一种序列改变到另一种序列
括号匹配问题:
思路:
1.检测该字符是否为括号,是括号继续,否则返回
2.如果是左括号,入栈
3.如果是右括号,判断栈是否为空,如果栈为空匹配失败(右括号比左括号多),否则检测概括好是否与栈顶括号匹配
匹配成功:将栈顶元素出栈
匹配失败:括号匹配失败,退出
4.取完所有括号,栈内仍有元素,匹配失败(左括号比右括号多)
#include<assert.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define max 100
typedef char DataType;
typedef struct Stack
{
int top;
DataType stack[max];
}Stack;
enum {Data,Add,Sub,Mul,Div}operate;
typedef struct Cell
{
enum operate op;
int data;
}cell;
void StackInit(Stack* p);//初始化栈
void StackPush(Stack* p,DataType data);//入栈
int StackPop(Stack* p);//出栈
void MatchBrackets(char* array, int sz);//括号匹配
void StackInit(Stack* p)
{
assert(p);
p->top = 0;
}
void StackPush(Stack* p, DataType data)
{
assert(p);
if (p->top <= max)
{
p->stack[p->top] = data;
p->top++;
}
else
{
printf("stack full\n");
}
}
int StackPop(Stack* p)
{
//int ch;
assert(p);
if (p->top != 0)
{
p->top--;
//ch = p->stack[p->top];
return p->stack[p->top];
}
}
int StackNum(Stack* p)
{
assert(p);
return p->top;
}
int StackTop(Stack* p)
{
int n;
assert(p);
if(p->top)
{
n = p->top;
return p->stack[n-1];
}
return 0;
}
int IsBrackets(DataType data)
{
if (')' == data || ']' == data || '}' == data || '(' == data || '[' == data || '{' == data)
return 1;
return 0;
}
void MatchBrackets(char* array, int sz)//括号匹配
{
int i = 0;
Stack s;
assert(array);
StackInit(&s);
for (; i < sz; i++)
{
if (IsBrackets(array[i]))//判断是否是括号
{
if (('(' == array[i]) || ('[' == array[i]) || ('{' == array[i]))//左括号
{
StackPush(&s, array[i]);
continue;
}
else //右括号
{
if (StackNum(&s)) //栈是否为空
{
DataType ch = StackTop(&s);
if (('(' == ch && ')' == array[i]) ||
('[' == ch && ']' == array[i]) ||
('{' == ch && '}' == array[i]))
{
StackPop(&s);
continue;
}
else
{
printf("匹配失败\n");
return ;
}
}
printf("右括号比左括号多\n");
return;
}
}
}
if (StackNum(&s))
printf("左括号比右括号多\n");
else
printf("匹配成功\n");
}
int CalRPN(cell* RPN, int sz)//逆波兰表达式(后缀表达式)
{
int i = 0;
Stack s;
assert(RPN);
StackInit(&s);
for (; i < sz; i++)
{
int left = 0;
int right = 0;
switch (RPN[i].op)
{
case Data:
StackPush(&s, RPN[i].data);
break;
case Add:
right = StackPop(&s);
left = StackPop(&s);
StackPush(&s, right + left);
break;
case Sub:
right = StackPop(&s);
left = StackPop(&s);
StackPush(&s, left - right);
break;
case Mul:
right = StackPop(&s);
left = StackPop(&s);
StackPush(&s, left * right);
break;
case Div:
right = StackPop(&s);
left = StackPop(&s);
if (0 == right)
printf("除数非法\n");
else
StackPush(&s, left / right);
break;
}
}
return StackTop(&s);
}
void test()//测试栈的基本操作
{
Stack p;
StackInit(&p);
StackPush(&p,1);
StackPush(&p, 2);
StackPush(&p, 3);
StackPush(&p, 4);
int c = StackPop(&p);
int b = StackPop(&p);
printf("%d %d\n", c,b);
}
void BracketsTest()//测试括号是否匹配函数
{
char a[] = "(())abc{[(])}";//不匹配
char b[] = "(()))abc{[]}";//右括号多于左括号
char c[] = "(()()abc{[]}";//左括号多余右括号
char d[] = "(())abc{[]()}";//左右括号匹配正确
int sz = strlen(d);
//MatchBrackets(a, sz);
//MatchBrackets(b, sz);
//MatchBrackets(c, sz);
MatchBrackets(d, sz);
}
void RPNTest()
{
cell RPN[] = { {Data,12},{Data,3},{Data,4},{Add,0},{Mul,0},{Data,6},{Sub,0},{Data,8},{Data,2},{Div,0},{Add,0} };
int sz = sizeof(RPN) / sizeof(RPN[0]);
int ret = CalRPN(RPN, sz);
printf("%d\n", ret);
}
int main()
{
test();
//BracketsTest();
RPNTest();
system("pause");
return 0;
}
本篇文章中有关栈的基本操作可以直接用于之前博客中调用。