括号匹配问题 中缀表达式转换为后缀表达式

 堆栈的介绍

       栈是一种特殊的线性表,特点是:是一种后进先出的线性表,只能在栈顶对数据进行插入,删除和取元素等操作。一种比较形象的记忆法是假如你面前有一摞盘子,而最方便和约定俗成的方法是取最上面的盘子,添加盘子时也是把它放在最上面,而对于栈来说是必须要这么做的。

用数组实现的一个简单的栈 SeqStack.h

//顺序栈的操作实现
#include"stdio.h"
#include"stdlib.h"
#define MaxStackSize 20
typedef char DataType;
//结点的定义
typedef struct 
{                                                                                                                                                                                                                                                                                                                                   
  DataType  stack[MaxStackSize];
  int top;
}SeqStack;
//操作的定义
void Initiate(SeqStack *s)
{
	s->top=0;
}
int StackEmpty(SeqStack *s)
{
	if(s->top>0)
	   return 1;
	else
	  return 0;
}
//入栈
int  StackPush(SeqStack *s,DataType x)
{
	if(s->top<MaxStackSize)
	{
		s->stack[s->top]=x;
		s->top++;
	    return 1;
	
	}
	else
	  return 0;
}
//出栈
void StackPop(SeqStack *s,DataType *x)
{  
	if(s->top>0)
	{   s->top--;
		*x=s->stack[s->top];
	}
	else 
	{
	  printf("栈为空\n");
	}
}
void StackTop(SeqStack *s,DataType *d)
{
	if(s->top>0)
	{
		*d=s->stack[s->top-1];
	}
	else 
	{
	printf("栈为空\n");
	}
}
栈的应用 之一 进行括号匹配

        这里的括号所举的例子是圆括号,中括号和花括号。

         算法描述:顺序扫描要判断的字符串,当遇到左括号时,将字符串入栈。当扫描到右括号时,比较当前栈顶的括号和扫描到的右括号是否匹配,如匹配,将此时栈顶的元素退栈,继续扫描字符串,若当前的元素和栈顶的元素不匹配时,则匹配次序不成功,若字符串为某种类型的右括号,而栈已空,则说明,右括号多于左括号匹配不成功,若扫描结束后,栈不为空,则说明左括号多于右括号,匹配不成功。否则,匹配成功。

        功能函数 int  MatBrackets(char *a,int n)

          

int MatchBrackets(char *a,int n)
{
	//扫描字符串,将其中的左括号入栈
	SeqStack s;
	int i,j;
	char k;
	Initiate(&s);
	for(i=0;i<n;i++)
	{
	 if(a[i]=='('||a[i]=='['||a[i]=='{')
	 {   
		 //将其入栈
		 StackPush(&s,a[i]);
	} 
	else if(!(a[i]>='a'&&a[i]<='z'))
		 {
            if(StackEmpty(&s))//判断栈是否为空 非空为1
			   { 
				   StackTop(&s,&k);//取一下也是可以的
				  // printf("%c\n",k);
			   }
			else 
			{
			  printf("右括号多于左括号,不匹配\n");
			  return 0;
			}
	        if(a[i]==')')
	       {
			   if(k=='(')
			      StackPop(&s,&k); //出栈
			   else
			   {
			    printf("括号次序不匹配\n");
				return 0;
			   }
		    }
			if(a[i]=='}')
	       {
			   if(k=='{')
			      StackPop(&s,&k); //出栈
			    else
			   {
			    printf("括号次序不匹配\n");
				return 0;
			   }
		    }
			if(a[i]==']')
	       {
			   if(k=='[')
			      StackPop(&s,&k); //出栈
			    else
			   {
			    printf("括号次序不匹配\n");
				return 0;
			   }
		    }

	     }


	}
	//当遍历完了之后,出现的情况 有出现一些括号,然后栈为空。
	if(StackEmpty(&s))
	{
	  printf("左括号多于右括号,不匹配\n");
	}
	else 
	{  printf("括号匹配正确\n");
		return 1;
	}
}
将中缀表达式转换为后缀表达式 

       表达式的组成,分为操作数,运算符和分界符。例如表达式A+(B-C/D)*E中,A,B,C,D,E是操作数,+-/*是运算符,()括号是分界符,将之变为后缀表达式的结果是ABCD/-E*+,

       将中缀表达式转化为后缀表达式的算法是:

(1)初始化一个堆栈,初始化时将栈顶的元素置为#

(2)顺序读入中缀表达式,当读到操作数时,将其作为后缀表达式的一部分进行输出

(3)当读到运算符时,取出栈顶的元素a,此时扫描到的元素为b,比较a和b之间的优先级,若a的优先级要高于b的优先级,则将a出栈,作为后缀表达式的一部分进行输出,再取出栈顶的元素,与b进行比较,若新的栈顶元素a的还是大于b的优先级,则与上一步操作一样,若a的优先级要低于b的优先级,则将b进行入栈,在去读取字符串的下一个元素,若a的优先级等于b的优先级且a为(,b为),此时仅仅将a进行出栈操作,读取下一个元素,若a的优先级等于b的优先级,a为#,b为#,转换完成。

int Compare(char a1,char a2)
{   
	if((a1=='+'||a1=='-')&&(a2=='+'||a2=='-'||a2==')'||a2=='#'))
		 return 1;
	else if(a1=='+'||a1=='-')
		return -1;
	if((a1=='*'||a1=='/')&&(a2=='('))
		return -1;
	else if(a1=='*'||a1=='/')
		 return 1;
	if(a1=='('&&a2!=')')
		return -1;
	else if(a1=='('&&a2==')')
		  return 0;
	if(a1==')'&&a1!='(')
		return 1;
	if(a1=='#'&&a2=='#')
		return 0;
	else if(a1=='#'&&a2!=')')
		return -1;
}
char* PostExp(char *a,int n)
{   
	char *b;
	int i,j,m;
	char k;
	SeqStack s;
	b=(char*)malloc(sizeof(char )*n);
	j=0;
	i=0;
	Initiate(&s);
	StackPush(&s,'#');//将#进行进栈
	//第一遍遍历的之后将所有的数字先输出来
	for(;i<n;i++)
	{
	 if(a[i]>='0'&&a[i]<='9')
	 {
	   b[j]=a[i];
	   j++;
	  }
	
	 else 
	 {
		 StackTop(&s,&k);
	     m=Compare(k,a[i]);//比较栈顶元素和当前扫描到的元素
		 printf("扫描到的元素%c\n",a[i]);
		 printf("栈顶的元素%c\n",k);
	     if(m>0)// 栈顶的优先级要高于当前扫描到的优先级
		 {
			   while(StackEmpty(&s)&&m>0)
			   {
				 b[j]=k;
				 j++;
				 StackPop(&s,&k);
			     StackTop(&s,&k);
			     m=Compare(k,a[i]);
			   }
		  }
		 if(m<0)
		{ 
				StackPush(&s,a[i]);
	     }
		 if(m==0&&k=='('&&a[i]==')')
		 {
		    StackPop(&s,&k);
		 }
		 if(m==0&&a[i]=='#'&&k=='#')
			 {
			  printf("算法结束\n");
			  
			 }
	 
	 }
	 }

	b[j]='\0';
	 for(i=0;b[i]!='\0';i++)
		 printf("%c ",b[i]);
	return b;

}
//用于测试的主函数 test.c

   void main()

{
	char a[]="(())abc{[][[]()}";
	char b[]="(()))abc{[]}";
	char c[]="(()()abc{[]}";
	char d[]="(())abc{([]}";
	char e[]="3+(4-4/2)*7#";
	char g[]="(1+2)*3-(4-5)*6-7#";
	char *f;
	int i;
	int n1=strlen(a);
	int n2=strlen(b);
	int n3=strlen(c);
    int n4=strlen(d);
	int n5=strlen(g);
	int n6=strlen(e);
	MatchBrackets(a,n1);
	MatchBrackets(b,n2);  
	MatchBrackets(c,n3);
	MatchBrackets(d,n4);
	f=PostExp(g,n5);
	f=PostExp(e,n6);
}
         以上是我学习数据结构的一些笔记,大部分是按照数据结构(朱战立版)书上的描述,自己去动手实现的。写下来,与大家一起学习,同时自己也便于自己以后参考。



    

























      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值