栈是我们经常会用到的一种数据结构,下面我们就来看一下如何使用C语言来实现一个静态栈,并且使用它来解决一个经典的问题——括号匹配问题
首先我们来看一下栈的自定义类型,我们需要一个数组来存放栈中的元素,并且需要一个数字来表明目前栈顶所在的位置,所以栈的自定义类型如下
#define Max_Size 100
typedef char DataType;
typedef struct //自定义结构体stack
{
DataType _Stack[Max_Size];
DataType _top;
}Stack;
接下来就是栈的功能,我们需要它能实现以下功能
void StackInit(Stack* s); // 栈的初始化
void StackPush(Stack* s, DataType data); // 入栈
DataType StackTop(Stack* s); // 出栈
int StackSize(Stack* s); // 获取栈顶元素
void StackPop(Stack* s); // 获取栈中元素个数
int StackEmpty(Stack* s); // 检测栈是否为空
void Print(Stack* s); // 打印栈顶元素
具体实现方法如下
void StackInit(Stack* s) // 栈的初始化
{
assert(s); // 断言栈的地址有效
s->_top = 0;
}
void StackPush(Stack* s, DataType data) // 入栈
{
assert(s);
if (s->_top == Max_Size) {
printf("栈已满\n");
return;
}
s->_Stack[s->_top] = data;
s->_top++;
}
DataType StackTop(Stack* s) // 出栈
{
assert(s);
if (s->_top != 0) {
return (s->_Stack[s->_top - 1]);
}
printf("栈为空\n");
return 0;
}
int StackSize(Stack* s) // 获取栈顶元素
{
assert(s);
return s->_top;
}
void StackPop(Stack* s) // 获取栈中元素个数
{
assert(s);
if (s->_top) {
s->_top--;
return;
}
printf("栈已空\n");
}
int StackEmpty(Stack* s) // 检测栈是否为空
{
assert(s);
return (0 == s->_top);
}
void Print(Stack* s) // 打印栈顶元素
{
printf("%d\n",s->_Stack[s->_top - 1]);
}
实现了一个静态栈之后,我们来尝试使用它解决有关于括号匹配的问题
首先来看一下解决这个问题的思想
当所有字符串处理完毕之后,我们再查看一下栈中元素,如果栈中仍有左括号,则括号不匹配——左括号多于右括号,否则括号匹配无误
具体实现如下
int Bracket(char ch) //用来检测当前字符是否是括号
{
if (ch == '(' || ch == '[' || ch == '{') {
return 1; //标记1为左括号
}else if (ch == ')' || ch == ']' || ch == '}'){
return 2; //标记2为右括号
}
return 0;
}
void MatchBrackets(const char* str)
{
Stack s;
StackInit(&s); //建立一个栈并初始化
if (NULL == str) {
return;
}
int len = 0;
int flag = 0; //用来接收Bracket函数的返回值
len = (int)strlen(str);
for (int i=0; i<len; i++) {
if ((flag = Bracket(str[i]))) { //判断是否是括号,如果是进行下一步处理
switch (flag) {
case 1: //左括号,直接压栈
StackPush(&s, str[i]);
break;
case 2: //右括号,判断是否与当前栈顶括号匹配
if (StackEmpty(&s)) {
printf("右括号多于左括号\n"); //栈为空,右括号多于左括号
return;
}
char top = StackTop(&s);
if (str[i] == ')') {
if (top != '(') {
printf("左右括号不匹配\n"); //栈顶括号与当前括号不匹配
return;
}
}
if (str[i] == ']') {
if (top != '[') {
printf("左右括号不匹配\n");
return;
}
}
if (str[i] == '}') {
if (top != '{') {
printf("左右括号不匹配\n");
return;
}
}
StackPop(&s);
break;
}
}
}
if (!StackEmpty(&s)) {
printf("左括号多于右括号\n"); //如果字符串处理完毕,栈内仍有括号,则左括号多于右括号
return;
}
printf("括号匹配:)\n"); //无误,括号匹配
}
来测试一下
int main()
{
char a[] = "(())abc{[(])}"; // 左右括号次序匹配不正确
char b[] = "(()))abc{[]}"; // 右括号多于左括号
char c[] = "(()()abc{[]}"; // 左括号多于右括号
char d[] = "(())abc{[]()}"; // 左右括号匹配正确
MatchBrackets(a);
MatchBrackets(b);
MatchBrackets(c);
MatchBrackets(d);
return 0;
}
结果如下图
结果正确