用栈实现括号匹配
来源:互联网 发布:我想在淘宝上卖东西 编辑:程序博客网 时间:2024/06/07 03:04
括号匹配的意思
假设只允许出现两种括号:圆括号和方括号,其嵌套顺序随意,即不管[([])]或[([])]等都为正确匹配,但是形如([][)就成为错误的匹配。
实现的算法
可以用“期待的紧急程度”的概念来描述:
如 [([][])] 共8个括号,从左往右依次标代号为1-8,即第一个[代号为1,第二个(代号为2,第三个[代号为3,依次类推
当计算机收到了第一个括号后,期待它与第八个括号匹配,然而等来的却是第二个括号,此时第一个括号‘[’只能暂时靠边,第二个括号的急迫程度又大于第一个括号,期待与之匹配的第七个括号的到来,然而却等来了第三个括号,这时第二个括号又要暂时靠边,第三个括号的急迫程度比第二个括号大,期待与之匹配的第四个括号的到来,第四个括号到来后与第三个括号相匹配,所以第三个括号的急迫就解决了。此时急迫程度最大的变成了第二个括号了,依次类推下去。
啊,我估计各位看完上面一小段的描述之后,可能觉得天花乱坠,云里雾里的。下面就用比较通俗的语言来说一下。
代码的设计思路:
首先计算机接收一串括号表达式,如[([][])],这时一个一个括号的检查。
1.建立一个空栈,用于存放左括号和表达相应左括号的急迫程度,栈顶的左括号的急迫程度为1,其他非栈顶左括号的急迫程度为0,显然栈顶左括号的急迫程度大于非栈顶的左括号急迫程度;
2.若第一个括号是左括号,不管是‘(’还是‘[’,都被压栈,急迫度为1,进入第三步;若第一个括号为右括号,不管是‘)’还是‘]’,就是错误的。因为栈顶没有与之相匹配的左括号,此时弹出出错提示,重新进入第一步;
3.若第二个括号为左括号,则被压栈,急迫度为1,刚刚压栈的左括号急迫度变为0,进入第四步;若为右括号,则查看是否与栈顶的左括号相匹配,若匹配成功,则删除栈顶左括号,若匹配失败,则弹出出错提示,重新进入第一步;
4.依次类推下去
总而言之一句话:是左括号的,压栈,急迫度为1,是右括号的,则看其是否与栈顶的左括号相匹配,若匹配,则删除栈顶括号,若不匹配,出错。
代码:
1.match_pa.h
//Headfile
// match paren
//History
// Xinspace 5 Mar First release
#ifndef xinspace_
#define xinspace_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <pthread.h>
#define error_show(function) \
do \
{ \
fprintf(stderr, “in file:%s, in function:%s, at line %d, %s : %s\n”, __FILE__, __FUNCTION__, __LINE__, function, strerror(errno)); \
exit(-1); \
}while(0)
#define MAX 10
void start(); //开始函数,包含在main函数内
void judge(char **st, char *sb, char pa);//判断一个右括号是否与栈顶的左括号匹配的函数,char **st是栈顶左括号指针的地址,sb是栈底指针,pa表示一个右括号
char *create_stack();//创建栈
char pop(char *st, char *sb);//出栈
void push(char *st, char pa);//压栈
#endif
2.主函数 main.c
//Program
// paren match
//History
// Xinspace 5 Mar First release
#include “match_pa.h”
int main(void)
{
char con = ‘y’;//这是一个选项,y表示再执行一遍程序,n表示不执行程序了,退出
while(1)
{
if(con == ‘y’ || con == ‘Y’)//如果选项为y,则执行start函数
start();
else//否则,退出程序
{
printf(“you quit!\n”);
break;
}
fflush(NULL);
printf(“continue? y/n\n”);
getchar();//这个getchar函数是用来接收回车符的,这个回车符是当你在屏幕上输入选项y或n之后敲回车的那个回车产生的。
con = getchar();//这个才是真正的选项y或n
}
return 0;
}
void start()
{
printf(“please input a trial of parens\n”);
char array[MAX*2]; //用来保存一串括号表达式
scanf(“%s”, array);
char *sp, *st, *sb;//sp是指栈底指针,st是栈顶指针,sb是栈底指针
int count = 0;//括号的数量,大于等于0小于strlen(array)
sp = create_stack();//创建栈
st = sb = sp;
while(count < strlen(array))
{
switch(array[count])
{
case ‘(‘://如果是左括号,则压栈
case ‘[':
push(st++, array[count]);
break;
case ‘)’://如果是右括号,则先检查是否与栈顶的左括号匹配,如果不匹配,则出错,若匹配,则继续
judge(&st, sb, ‘)’);
break;
case ‘]’:
judge(&st, sb, ‘]’);
break;
default:
fprintf(stderr, “wrong paren!please reinput\n”);
}
count++;
}
if(st != sb) //如果出错了,即左右括号不匹配的时候,栈中肯定还存在一些左括号没有被匹配,即st与sb不相等,把这些括号依次出栈打印到屏幕上
{
printf(“the paren stack is still left(right to left):”);
while(st != sb)
{
putchar(pop(–st, sb));
}
putchar(10);
}
}
3.附加文件match_pa.c
//Program
// match paren
//History
// Xinspace 5 Mar First release
//
#include “match_pa.h”
char *create_stack()//创建栈
{
char *sp = (char *)malloc(sizeof(char) * MAX);
if(!sp)
error_show(“malloc”);
return sp;
}
void push(char *st, char pa)//压栈
{
*st = pa;
// printf(“insert %c\n”, *st);
}
char pop(char *st, char *sb)//出栈
{
if(st < sb)
{
fprintf(stderr, “stack is NULL!\n”);
exit(1);
}
return *st;
}
void judge(char **st, char *sb, char pa)//判断一个右括号是否与栈顶的左括号匹配
{
if(pa == ‘)’)
{
if(pop(*st – 1, sb) == ‘(‘)
pop(–*st, sb);
else
{
fprintf(stderr, “before ‘)’ must be ‘(‘, but your is %c!\n”, pop(*st – 1, sb));
return;
}
}
else if(pa == ‘]’)
{
if(pop(*st – 1, sb) == ‘[')
pop(--*st, sb);
else
{
fprintf(stderr, "before ']‘ must be ‘[‘, but your is %c!\n”, pop(*st – 1, sb));
return;
}
}
else
{
fprintf(stderr, “paren wrong!please reinput\n”);
}
}
更多文章请见blog.xinspace.name
三个文件的下载地址:
match_pa.h
main.c
match_pa.c
- 用栈实现括号匹配
- 用栈实现括号匹配
- 用栈实现括号匹配
- 栈实现括号匹配
- 栈实现括号匹配
- 栈实现括号匹配
- 栈实现括号匹配
- 括号匹配---栈实现
- 栈实现括号匹配
- 栈实现括号匹配
- 括号匹配,栈实现
- 栈实现括号匹配
- 用顺序栈实现匹配括号功能
- 用栈实现括号匹配的检验
- 用栈实现括号匹配的检验
- 用栈实现括号匹配的检验
- 括号匹配问题,用栈实现
- 用栈实现括号匹配的算法
- 值得一看的技术类书籍
- github
- ACTIVE X控件 为控件CAB文件指定解包路径及INF文件详解
- 【HACK】破解APK并注入自己的代码
- 每天一个Linux命令-----rm
- 用栈实现括号匹配
- IOS延时函数和Timer的使用(转)
- MFC INI文件读写
- Extjs 的GridPanel剔除隐藏列在menuDisabled 显示
- disable 主菜单
- 时钟中断导致的内核模块死锁
- [Python]多线程--threading模块实现
- 用栈实现数制转换
- List collides with another import statement 同一个类相同包名碰撞