括号匹配是栈的一种应用,主要思路是遇到字符串的左括号入栈,字符串移动遇到相同类型的右括号弹栈,以下是代码实现:
#include<stdio.h>
#include<stdlib.h>
#define STACK_SIZE_MAX 10
typedef struct CharStack {
int top;
int data[STACK_SIZE_MAX];
}*CharStackPtr;
void outputStack(CharStackPtr paraStack)
{
for (int i = 0; i <= paraStack->top; i++)
{
printf("%c ", paraStack->data[i]);
}//off for
printf("\r\n");
}//off outputStack
CharStackPtr initStack()
{
CharStackPtr resultPtr = (CharStackPtr)malloc(sizeof(struct CharStack));
resultPtr->top = -1;
return resultPtr;
}//off initStack
void push(CharStackPtr paraStack, int paraValue)
{
if (paraStack->top >= STACK_SIZE_MAX - 1)
{
printf("Cannot push this element:stack full\r\n");
return;
}//off if
paraStack->top++;
paraStack->data[paraStack->top] = paraValue;
}//off push
char pop(CharStackPtr paraStack)
{
if (paraStack->top == -1)
{
printf("Cannot pop element:stack empty\r\n");
return '\0';
}//off if
paraStack->top--;
return paraStack->data[paraStack->top + 1];
}//off pop
void pushpopTest()
{
printf("---- pushpopTest begins ----\r\n");
char ch;
CharStackPtr tempStack = initStack();
printf("After initalization the stack is: ");
outputStack(tempStack);
for (ch = 'a'; ch < 'm'; ch++)
{
printf("pushing %c\r\n", ch);
push(tempStack, ch);
outputStack(tempStack);
}//off for ch
for(int i = 0; i < 3; i++)
{
ch = pop(tempStack);
printf("Pop %c\r\n", ch);
outputStack(tempStack);
}//off for i
printf("---- pushpopTest ends ----\r\n");
}//off pushpopTest
bool bracketMatching(const char* paraString, int paraLength)
{
CharStackPtr tempStack = initStack();
push(tempStack, '#');
char tempChar, tempPopedChar;
for (int i = 0; i < paraLength; i++)
{
tempChar = paraString[i];
switch (tempChar)
{
case '(':
case '[':
case '{':
push(tempStack, tempChar);
break;
case ')':
tempPopedChar = pop(tempStack);
if (tempPopedChar != '(')
{
return false;
}//off if
break;
case ']':
tempPopedChar = pop(tempStack);
if (tempPopedChar != '[')
{
return false;
}//off if
break;
case '}':
tempPopedChar = pop(tempStack);
if (tempPopedChar != '{')
{
return false;
}//off if
break;
default:
break;
}//off switch
}//off for i
tempPopedChar = pop(tempStack);
if (tempPopedChar != '#')
{
return true;
}//off if
return true;
}//off braketMatching
void bracketMatchingTest()
{
const char* tempExpression = "[2 + (1 - 3)] * 4";
bool tempMatch = bracketMatching(tempExpression, sizeof(tempExpression));
printf("is the expression %s bracket match ? %d\r\n", tempExpression, tempMatch);
tempExpression = "( ) )";
tempMatch = bracketMatching(tempExpression, sizeof(tempExpression));
printf("is the expression %s bracket match ? %d\r\n", tempExpression, tempMatch);
tempExpression = "()()(())";
tempMatch = bracketMatching(tempExpression, sizeof(tempExpression));
printf("is the expression %s bracket match ? %d\r\n", tempExpression, tempMatch);
tempExpression = "({}[])";
tempMatch = bracketMatching(tempExpression, sizeof(tempExpression));
printf("is the expression %s bracket match ? %d\r\n", tempExpression, tempMatch);
tempExpression = ")(";
tempMatch = bracketMatching(tempExpression, sizeof(tempExpression));
printf("is the expression %s bracket match ? %d\r\n", tempExpression, tempMatch);
}
int main()
{
//pushpopTest();
bracketMatchingTest();
return 0;
}
该代码的入栈弹栈由push函数和pop函数实现,其中push函数为入栈函数
void push(CharStackPtr paraStack, int paraValue)
{
if (paraStack->top >= STACK_SIZE_MAX - 1)
{
printf("Cannot push this element:stack full\r\n");
return;
}//off if
paraStack->top++;
paraStack->data[paraStack->top] = paraValue;
}//off push
puh函数传入表示栈的结构体定义和一个新的元素,当记录储存字符串数组长度的整形top大于或等于数组的最大下标-1时,数组无法继续存储元素,提示栈满,否则top+1,在top+1的下标储存新的元素。
pop为弹栈函数
char pop(CharStackPtr paraStack)
{
if (paraStack->top == -1)
{
printf("Cannot pop element:stack empty\r\n");
return '\0';
}//off if
paraStack->top--;
return paraStack->data[paraStack->top + 1];
}//off pop
pop函数传入表示栈的结构体定义,当整形top小于数组的最小下标时,提示空栈,返回'\0'。否则top-1,返回原本top下标的元素。
在入栈弹栈测试函数中,可以清楚看到这两个代码的运行逻辑
我们知道运算在引入括号时,越先引入的左括号,越后才能引入右括号,比如{ [ ( ) ] },左括号 '{' 在第一位,'}' 则到了第六位,但是 '(' 在第三位,而 ')' 在第四位,括号运用法则符合栈的先进后出,后进先出,所以我们可以用栈来检查括号是否匹配。在括号匹配测试函数中,我们只管括号是否匹配,所以在入栈的时候,除括号类型外,通通跳过不入栈,或者也可以新建两个栈分别存储数字和运算符来完成一个表达式的计算。入栈时只入括号类型的左括号,这样字符串移动识别到相同类型的右括号时,栈的长度top减一,删除表示栈的数组的末下标元素表示弹栈,当右括号与栈数组的末下标元素不匹配时返回false,表示括号不匹配。