前言
括号匹配问题算是栈应用中比较经典的问题了,在数据结构的书中还有各种考试中会出现。最近刷题的时候也遇到了,就想写一篇文章整理一下。
代码
方法一:这里我使用了两个栈进行括号匹配的核心算法
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STACK 20
#define STACKINCREMENT 10
static int line_number = 1,i=0,j=0;
typedef struct
{
char *base; // 栈底指针
char *top; // 栈顶指针
int stackSize; // 栈大小
int a[1000];
} sqStack;
void InitStack(sqStack *s)
{
s->base = (char *)malloc(STACK * sizeof(char)); // 为栈分配内存
if (!s->base)
exit(0); // 分配失败则退出程序
s->top = s->base;
s->stackSize = STACK;
}
void Push(sqStack *s, char e)
{
if (s->top - s->base >= s->stackSize)
{
s->base = (char *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(char)); // 栈满时重新分配内存
// if (!s->base)
// exit(0);
s->top = s->base + s->stackSize;
s->stackSize = s->stackSize + STACKINCREMENT;
}
*(s->top) = e; // 将元素压入栈顶
s->top++;
}
int Pop(sqStack *s, char *e)
{
if (s->top == s->base)
return 1; // 栈空,出栈失败
*e = *--(s->top); // 弹出栈顶元素
return 0;
}
int match(char e, char c)
{
if( e=='(' && c==')' )
return 1;
return 0;
}
int match1(char e, char c)
{
if( e=='{' && c=='}' )
return 1;
return 0;
}
int StackLen(sqStack s)
{
return (s.top - s.base); // 返回栈长度
}
int main()
{
sqStack s,ss;
char c, e;
InitStack(&s);
InitStack(&ss);
printf("Please enter the name of the file: ");
char filename[100];
scanf("%s", filename);
FILE *file = fopen(filename, "r");
if (!file)
{
printf("File not found or cannot be opened.\n");
return 1; // 无法打开文件,程序退出
}
int n = 0;
while ((c = fgetc(file)) != EOF)
{
if(c=='/'){
c=fgetc(file);
if(c=='*'){
do{c = fgetc(file);}while(c!='*');
}
}
if (c == '\n')
{
line_number++; // 更新行号
continue;
}
if( c=='(' || c==')' )
{ // 如果是括号,就进栈
if( !StackLen(s) ) //如果栈的长度为空,c直接进栈
{
Push(&s, c); //存入c
}
else //如果c放入时,栈已经不空了,
{
Pop(&s, &e);
//取出栈顶元素来判断与新放入的c是否匹配
if( !match(e, c) )
//如果match执行结果为假,即不匹配
{
Push(&s, e);
//原栈顶元素重新入栈
Push(&s, c);
s.a[i++]=line_number;
//将输入的括号字符入栈
}
else if(match(e,c))
{
i--;
}
}
}
else if( c=='{' || c=='}' )
{ // 如果是括号,就进栈
if( !StackLen(ss) ) //如果栈的长度为空,c直接进栈
{
Push(&ss, c); //存入c
}
else //如果c放入时,栈已经不空了,
{
Pop(&ss, &e);
//取出栈顶元素来判断与新放入的c是否匹配
if( !match1(e, c) )
//如果match执行结果为假,即不匹配
{
Push(&ss, e);
//原栈顶元素重新入栈
Push(&ss, c);
ss.a[j++]=line_number;
//将输入的括号字符入栈
}
else if(match1(e,c))
{
j--;
}
}
}
}
fclose(file);
for(Pop(&s, &e),i=i-1;e;Pop(&s, &e),i--)
{
printf("Unmatched %c at end of file in line %d\n", e, s.a[i]); // 输出未匹配的括号错误
n++;
strcpy(&e,"\0");
}
for (Pop(&ss, &e),j=j-1;e;Pop(&ss, &e),j--)
{
printf("Unmatched %c at end of file in line %d\n", e, ss.a[j]); // 输出未匹配的括号错误
n++;
strcpy(&e,"\0");
}
if (n == 0)
{
printf("All parentheses in the input file match exactly.\n"); // 输出所有括号匹配正确
}
else
{
printf("There are unmatched parentheses in the input file.\n"); // 输出存在未匹配括号的错误
}
return 0;
}
方法二:适合简单方面的括号匹配(易看懂)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STACK 20
#define STACKINCREMENT 10
typedef struct
{
char *base;//栈底
char *top; //栈顶
int stackSize;
}sqStack;
InitStack(sqStack *s)
{
s->base = (char *)malloc(STACK * sizeof(char));
if( !s->base )
exit(0);
s->top = s->base;
s->stackSize = STACK;
}
Push(sqStack *s, char e)
{
if( s->top - s->base >= s->stackSize )
{
s->base = (char *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(char));
if( !s->base )
exit(0);
s->top = s->base + s->stackSize;
s->stackSize = s->stackSize + STACKINCREMENT;
}
*(s->top) = e;
s->top++;
}
Pop(sqStack *s, char *e)
{
if( s->top == s->base )
return 1;
*e = *--(s->top);
}
int StackLen(sqStack s)
{
return (s.top - s.base); //返回长度:顶-底
}
int match(char e, char c)
{
if( e=='(' && c==')' )
return 1;
if( e=='{' && c=='}' )
return 1;
return 0;
}
int main()
{
sqStack s;//栈
char c, e;
InitStack( &s );//初始化
printf("Please enter the program:");
scanf("%c", &c);
while( c !='@')
{
if( c=='(' || c==')' || c=='{' || c=='}' )
{ // 如果是括号,就进栈
if( !StackLen(s) ) //如果栈的长度为空,c直接进栈
{
Push(&s, c); //存入c
}
else //如果c放入时,栈已经不空了,
{
Pop(&s, &e);
//取出栈顶元素来判断与新放入的c是否匹配
if( !match(e, c) )
//如果match执行结果为假,即不匹配
{
Push(&s, e);
//原栈顶元素重新入栈
Push(&s, c);
//将输入的括号字符入栈
}
}
}
scanf("%c", &c);
}
if( !StackLen(s) )
{
printf("\nThe parentheses in the input string match exactly \n");
}
else
{
char p;
Pop(&s, &p);
char q;
if(p=='{'){strcpy(&q,"}");}
if(p=='}'){strcpy(&q,"{");}
if(p=='('){strcpy(&q,")");}
if(p==')'){strcpy(&q,"(");}
printf("\nThe parentheses in the input string do not exactly match is lack:%c\n",q);
char w,y;
for(Pop(&s, &w);w;Pop(&s, &w)){
if(w=='{'){strcpy(&y,"}");}
if(w=='}'){strcpy(&y,"{");}
if(w=='('){strcpy(&y,")");}
if(w==')'){strcpy(&y,"(");}
printf("and:%c\n",y);
strcpy(&w,"\0");
}
}
return 0;
}
方法三:方法一的简易版但不完整
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STACK 20
#define STACKINCREMENT 10
typedef struct
{
char *base; // 栈底指针
char *top; // 栈顶指针
int stackSize; // 栈大小
} sqStack;
void InitStack(sqStack *s)
{
s->base = (char *)malloc(STACK * sizeof(char)); // 为栈分配内存
if (!s->base)
exit(0); // 分配失败则退出程序
s->top = s->base;
s->stackSize = STACK;
}
void Push(sqStack *s, char e)
{
if (s->top - s->base >= s->stackSize)
{
s->base = (char *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(char)); // 栈满时重新分配内存
if (!s->base)
exit(0);
s->top = s->base + s->stackSize;
s->stackSize = s->stackSize + STACKINCREMENT;
}
*(s->top) = e; // 将元素压入栈顶
s->top++;
}
int Pop(sqStack *s, char *e)
{
if (s->top == s->base)
return 1; // 栈空,出栈失败
*e = *--(s->top); // 弹出栈顶元素
return 0;
}
int match(char e, char c)
{
if( e=='(' && c==')' )
return 1;
if( e=='{' && c=='}' )
return 1;
return 0;
}
int StackLen(sqStack s)
{
return (s.top - s.base); // 返回栈长度
}
int main()
{
sqStack s;
char c, e;
InitStack(&s);
printf("Please enter the name of the file: ");
char filename[100];
scanf("%s", filename);
FILE *file = fopen(filename, "r");
if (!file)
{
printf("File not found or cannot be opened.\n");
return 1; // 无法打开文件,程序退出
}
int n = 0;
int line_number = 1;
while ((c = fgetc(file)) != EOF)
{
if (c == '\n')
{
line_number++; // 更新行号
continue;
}
if( c=='(' || c==')' || c=='{' || c=='}' )
{ // 如果是括号,就进栈
if( !StackLen(s) ) //如果栈的长度为空,c直接进栈
{
Push(&s, c); //存入c
}
else //如果c放入时,栈已经不空了,
{
Pop(&s, &e);
//取出栈顶元素来判断与新放入的c是否匹配
if( !match(e, c) )
//如果match执行结果为假,即不匹配
{
Push(&s, e);
//原栈顶元素重新入栈
Push(&s, c);
//将输入的括号字符入栈
}
}
}
}
fclose(file);
while (Pop(&s, &e)== 0)
{
printf("Unmatched %c at end of file in line %d\n", e, line_number); // 输出未匹配的括号错误
n++;
}
if (n == 0)
{
printf("All parentheses in the input file match exactly.\n"); // 输出所有括号匹配正确
}
else
{
printf("There are unmatched parentheses in the input file.\n"); // 输出存在未匹配括号的错误
}
return 0;
}
方法四:双栈进行套用
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
typedef struct {
char bracket;
int line;
} BracketInfo;
typedef struct {
BracketInfo data[MAX_SIZE];
int top;
} Stack;
void initializeStack(Stack *s) {
s->top = -1;
}
int isEmpty(Stack *s) {
return s->top == -1;
}
void push(Stack *s, char bracket, int line) {
if (s->top == MAX_SIZE - 1) {
printf("Stack overflow\n");
exit(1);
}
s->top++;
s->data[s->top].bracket = bracket;
s->data[s->top].line = line;
}
BracketInfo pop(Stack *s) {
if (isEmpty(s)) {
BracketInfo emptyInfo = {'\0', -1};
return emptyInfo;
}
BracketInfo popped = s->data[s->top];
s->top--;
return popped;
}
int main() {
char filename[100];
scanf("%s", filename);
FILE *file = fopen(filename, "r");
if (!file)
{
printf("File not found or cannot be opened.\n");
return 1; // 无法打开文件,程序退出
}
Stack s;
initializeStack(&s);
char lineBuffer[1000];
int lineNum = 0;
while (fgets(lineBuffer, sizeof(lineBuffer), file)) {
lineNum++;
for (int i = 0; lineBuffer[i] != '\0'; i++) {
if (lineBuffer[i] == '(' || lineBuffer[i] == '{') {
push(&s, lineBuffer[i], lineNum);
}
else if (lineBuffer[i] == ')' || lineBuffer[i] == '}') {
if (isEmpty(&s)) {
// printf("Unmatched %c at line %d\n", lineBuffer[i], lineNum);
} else {
BracketInfo popped = pop(&s);
if ((popped.bracket == '(' && lineBuffer[i] != ')') ||(popped.bracket == '{' && lineBuffer[i] != '}')) {
//printf("Mismatched %c at line %d, should be %c\n", lineBuffer[i], lineNum, popped.bracket);
}
}
}
}
}
while (!isEmpty(&s)) {
BracketInfo popped = pop(&s);
printf("Unmatched %c at line %d\n", popped.bracket, popped.line);
}
fclose(file);
return 0;
}
方法五:适合相邻括号进行匹配
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STACK 20
#define STACKINCREMENT 10
int line_number = 1,i=0;
typedef struct
{
char *base; // 栈底指针
char *top; // 栈顶指针
int stackSize; // 栈大小
int a[10000];
} sqStack;
void InitStack(sqStack *s)
{
s->base = (char *)malloc(STACK * sizeof(char)); // 为栈分配内存
if (!s->base)
exit(0); // 分配失败则退出程序
s->top = s->base;
s->stackSize = STACK;
}
void Push(sqStack *s, char e)
{
if (s->top - s->base >= s->stackSize)
{
s->base = (char *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(char)); // 栈满时重新分配内存
if (!s->base)
exit(0);
s->top = s->base + s->stackSize;
s->stackSize = s->stackSize + STACKINCREMENT;
}
*(s->top) = e; // 将元素压入栈顶
s->top++;
}
int Pop(sqStack *s, char *e)
{
if (s->top == s->base)
return 1; // 栈空,出栈失败
*e = *--(s->top); // 弹出栈顶元素
return 0;
}
int match(char e, char c)
{
if( e=='(' && c==')' )
return 1;
if( e=='{' && c=='}' )
return 1;
return 0;
}
int StackLen(sqStack s)
{
return (s.top - s.base); // 返回栈长度
}
int main()
{
sqStack s;
char c, e;
InitStack(&s);
printf("Please enter the name of the file: ");
char filename[100];
scanf("%s", filename);
FILE *file = fopen(filename, "r");
if (!file)
{
printf("File not found or cannot be opened.\n");
return 1; // 无法打开文件,程序退出
}
int n = 0;
while ((c = fgetc(file)) != EOF)
{
if(c=='/'){
c=fgetc(file);
if(c=='*'){
do{c = fgetc(file);}while(c!='*');
}
}
if (c == '\n')
{
line_number++; // 更新行号
continue;
}
if( c=='(' || c==')' || c=='{' || c=='}' )
{ // 如果是括号,就进栈
if( !StackLen(s) ) //如果栈的长度为空,c直接进栈
{
Push(&s, c);
s.a[i++]=line_number; //存入c
}
else //如果c放入时,栈已经不空了,
{
Pop(&s, &e);
//取出栈顶元素来判断与新放入的c是否匹配
if( !match(e, c) )
//如果match执行结果为假,即不匹配
{
Push(&s, e);
//原栈顶元素重新入栈
Push(&s, c);
s.a[i++]=line_number;
//将输入的括号字符入栈
}
if(match(e,c))
{
i--;
}
}
}
}
fclose(file);
for (Pop(&s, &e),i=i-1;e;Pop(&s, &e),i--)
{
printf("Unmatched %c at end of file in line %d\n", e, s.a[i]); // 输出未匹配的括号错误
n++;
strcpy(&e,"\0");
}
if (n == 0)
{
printf("All parentheses in the input file match exactly.\n"); // 输出所有括号匹配正确
}
else
{
printf("There are unmatched parentheses in the input file.\n"); // 输出存在未匹配括号的错误
}
return 0;
}
方法六: 底层代码不全可以查看思路
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STACK 20
#define STACKINCREMENT 10
int line_number = 1,i=0,j=0;
typedef struct
{
char *base; // 栈底指针
char *top; // 栈顶指针
int stackSize; // 栈大小
int a[10000];
} sqStack;
void InitStack(sqStack *s)
{
s->base = (char *)malloc(STACK * sizeof(char)); // 为栈分配内存
if (!s->base)
exit(0); // 分配失败则退出程序
s->top = s->base;
s->stackSize = STACK;
}
void Push(sqStack *s, char e)
{
if (s->top - s->base >= s->stackSize)
{
s->base = (char *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(char)); // 栈满时重新分配内存
if (!s->base)
exit(0);
s->top = s->base + s->stackSize;
s->stackSize = s->stackSize + STACKINCREMENT;
}
*(s->top) = e; // 将元素压入栈顶
s->top++;
}
int Pop(sqStack *s, char *e)
{
if (s->top == s->base)
return 1; // 栈空,出栈失败
*e = *--(s->top); // 弹出栈顶元素
return 0;
}
int match(char e, char c)
{
if( e=='(' && c==')' )
return 1;
if( e=='{' && c=='}' )
return 1;
return 0;
}
int StackLen(sqStack s)
{
return (s.top - s.base); // 返回栈长度
}
int main()
{
sqStack s;
sqStack w;
char c, e;
InitStack(&s);
InitStack(&w);
printf("Please enter the name of the file: ");
char filename[100];
scanf("%s", filename);
FILE *file = fopen(filename, "r");
if (!file)
{
printf("File not found or cannot be opened.\n");
return 1; // 无法打开文件,程序退出
}
int n = 0;
while ((c = fgetc(file)) != EOF)
{
if(c=='/'){
c=fgetc(file);
if(c=='*'){
do{c = fgetc(file);}while(c!='*');
}
}
if (c == '\n')
{
line_number++; // 更新行号
continue;
}
if( c=='(' || c==')' )
{ // 如果是括号,就进栈
if( !StackLen(s) ) //如果栈的长度为空,c直接进栈
{
Push(&s, c);
s.a[i++]=line_number; //存入c
}
else //如果c放入时,栈已经不空了,
{
Pop(&s, &e);
//取出栈顶元素来判断与新放入的c是否匹配
if( !match(e, c) )
//如果match执行结果为假,即不匹配
{
Push(&s, e);
//原栈顶元素重新入栈
Push(&s, c);
s.a[i++]=line_number;
//将输入的括号字符入栈
}
if(match(e,c))
{
i--;
}
}
}
if( c=='{' || c=='}' )
{ // 如果是括号,就进栈
if( !StackLen(w) ) //如果栈的长度为空,c直接进栈
{
Push(&w, c);
w.a[j++]=line_number; //存入c
}
else //如果c放入时,栈已经不空了,
{
Pop(&w, &e);
//取出栈顶元素来判断与新放入的c是否匹配
if( !match(e, c) )
//如果match执行结果为假,即不匹配
{
Push(&w, e);
//原栈顶元素重新入栈
Push(&w, c);
w.a[j++]=line_number;
//将输入的括号字符入栈
}
if(match(e,c))
{
j--;
}
}
}
}
fclose(file);
for (Pop(&s, &e),i=i-1;e;Pop(&s, &e),i--)
{
printf("Unmatched %c at end of file in line %d\n", e, s.a[i]); // 输出未匹配的括号错误
n++;
strcpy(&e,"\0");
}
for (Pop(&w, &e),j=j-1;e;Pop(&w, &e),j--)
{
printf("Unmatched %c at end of file in line %d\n", e, w.a[j]); // 输出未匹配的括号错误
n++;
strcpy(&e,"\0");
}
if (n == 0)
{
printf("All parentheses in the input file match exactly.\n"); // 输出所有括号匹配正确
}
else
{
printf("There are unmatched parentheses in the input file.\n"); // 输出存在未匹配括号的错误
}
return 0;
}
运行结果 :封面