设计一个判别表达式中左、右括号是不是配对出现的算法,采用啥数据结构最佳。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计一个判别表达式中左、右括号是不是配对出现的算法,采用啥数据结构最佳。相关的知识,希望对你有一定的参考价值。

使用“栈” 这种数据结构。

栈 (Stack)是一种后进先出(last in first off,LIFO)的数据结构。

算法基本思想:依次判断表达式中的每个字符,若是左括号就入栈,如果是右括号则出栈,出栈的时候判断是否为空,如果为空,则说明不匹对,最后读到表达式末尾没有字符了,再判断一下栈是否为空,如果为空,则说明匹配,不为空,说明不匹配。

参考如下代码,引用地址(http://blog.csdn.net/kkkkkxiaofei/article/details/8293980)

#include <stdio.h>
#include <malloc.h>   //malloc,realloc
#include <math.h>     //含有overflow
#include <process.h>  //exit()
#define S_SIZE 100   //栈的空间大小
#define STACKINCREAMENT 10//增加空间
struct SqStack
int *base; //栈底
int *top;  //栈顶
int stacksize;   //栈当前的存储空间
;
void main()
//子函数声明
void InitStack(SqStack &S);//初始化空栈
int StackEmpty(SqStack S);//判空
void push(SqStack &S,int e);//进栈
    void pop(SqStack &S,int &e);//出栈
//主函数开始
SqStack s;//初始化空栈
InitStack(s);
char ch[100],*p;int e;
p=ch;
printf("输一个含义有()[]的括号表达式:\\n");
gets(ch);
    while(*p)
 
switch (*p)

case '':
case '[':
case '(': push(s,*p++);break;//只要是左括号就入栈
case '':
case ']':
case ')':pop(s,e);
     if ((e=='' && *p=='') ||(e=='[' && *p==']') || (e=='(' && *p==')'))
 p++;
 else
 printf("括号不匹配!");exit(OVERFLOW);
 break;
default :p++;//其他字符就后移


    if (StackEmpty(s))
      printf("括号匹配成功");
else
      printf("缺少右括号!");
printf("\\n");

void InitStack(SqStack &S)
S.base=(int *)malloc(S_SIZE*sizeof(int));
S.stacksize=S_SIZE;
S.top=S.base;//初始化空栈

int StackEmpty(SqStack S)

if(S.base==S.top)
return 1;
else
return 0;

void push(SqStack &S,int e)
//进栈
if(S.top-S.base>=S.stacksize)
S.base=(int *)realloc(S.base,(S.stacksize+STACKINCREAMENT)*sizeof(int));
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREAMENT;
*(S.top)=e;
S.top++;   

void pop(SqStack &S,int &e)
//出栈
if(S.base!=S.top)
S.top--;
e=*S.top;

参考技术A

当然用栈这个数据结构,设置两个栈,我有相关实现的代码给你参考一下

//栈数据结构的实现
MyStack.h 
#ifndef MYSTACK_H
#define MYSTACK_H
template<typename T>
class MyStack

public:
    MyStack(int _size);
    ~MyStack();
    bool StackEmpty();
    bool StackFull();
    void ClearStack();
    int  StackLength();
    void StackTraverse();
    bool push(T& _element);
    T& pop();
private:
    T* m_pBuffer;  //栈的内存空间的地址
    int  m_iCapacity; // 栈的容量
    int  m_iTop;  //栈顶位置,栈底位置是确定的
;
#endif
-------------------------------------------
MyStack.cpp 模板类的声明和实现在使用的时候不能分开,可以把声明和实现放在一个文件中,也可以在主文件中包含实现的文件
#include "MyStack.h"
template<typename T> //模板类的成员函数的写法要完整,指定模板参数
MyStack<T>::MyStack(int _size)

    this->m_iCapacity =_size;
    this->m_pBuffer =new T[_size];
    this->m_iTop=0;

template<typename T>
MyStack<T>::~MyStack()

    delete[] this->m_pBuffer;
    this->m_pBuffer =NULL;

template<typename T>
bool MyStack<T>::StackEmpty()

    return this->m_iTop ==0?true:false;

template<typename T>
bool MyStack<T>::StackFull()

    return this->m_iCapacity == this->m_iTop?true:false;

template<typename T>
void MyStack<T>::ClearStack()

    this->m_iTop =0;

template<typename T>
int  MyStack<T>::StackLength()

    return this->m_iTop;

template<typename T>
bool MyStack<T>::push(T& _element)

    try
    
        if (this->StackFull())
        
            throw string("Stack Overflow");
        
        else
        
            this->m_pBuffer[this->m_iTop] =_element;
            this->m_iTop++;
            return true;
        
    
    catch(string& str) // 有未处理的异常错误是这里的函数参数不应该是string类型的指针,很显然啊,抛出的是一个字符串常量 。一开始用默认填充的string* 总是出错
    
        cout<<str<<endl;
    

template<typename T> // 最有意义的一部分,更改了弹出栈的实现,以函数参数的方式实在太不人性化了
T& MyStack<T>::pop()

    try
    
        if (this->StackEmpty())
        
            throw string(" Stack Empty");  //哪里出现异常,就在哪里捕获,不应该在外部进行异常捕获,否则不易定位到异常的地点
        
        else
        
            this->m_iTop--;
            return this->m_pBuffer[this->m_iTop];

        
    
    catch(string& str)
    
        cout<<str<<endl;
    

template<typename T>
void MyStack<T>::StackTraverse()

    for (int i =this->m_iTop-1; i>=0; i--)
    
        cout<<this->m_pBuffer[i]; //如果是自定义的类型需要重载<<操作符
    

--------------------------------------------------------
main.cpp 测试部分
#include <stdlib.h>
#include "MyStack.cpp"
#include "Customer.h"
int main()

    MyStack<Customer>* ps =new MyStack<Customer>(5);
    ps->push(Customer("Selina",22));
    ps->push(Customer("Johnaon",54));
    ps->push(Customer("Richard",38));
    ps->push(Customer("Alice",18));
    ps->push(Customer("Elizabeth",89));
    ps->StackTraverse();
    cout<<"-------------------"<<endl;
    ps->push(Customer("Stephen",67));
    cout<<"-------------------"<<endl;
    cout<<ps->pop(); //异常Stack Empty,不能够在回调printInfo()函数了,否则会出现另一个异常
    cout<<"-------------------"<<endl;
    ps->StackTraverse(); //弹出的元素已不在
    delete ps;
    ps=NULL;
    system("pause");
    return 0;

---利用上面实现的栈结构,完成表达式括号的匹配任务
栈:实现判断字符串中的括号是否匹配,要考虑的情况还挺多的
#include <stdlib.h>
#include "MyStack.cpp"
int main()

    char str[] ="[]"; //strlen()函数的参数是char* 类型,这里不能使用string定义一个字符串常量
    char currentNeed =0; //当前栈顶需要匹配的字符串
    MyStack<char>* ps1 =new MyStack<char>(20);
    MyStack<char>* ps2 =new MyStack<char>(20);
    for (int i=0; i<strlen(str); i++)
    
        if (str[i] != currentNeed)
        
            ps1->push(str[i]);
            switch(str[i])
            
                case '':
                    if (currentNeed !=0)
                    
                     ps2->push(currentNeed);
                    
                    currentNeed ='';
                    break;
                case '[':
                    if (currentNeed !=0)
                    
                      ps2->push(currentNeed);
                    
                    currentNeed =']';
                    break;
                case '(':
                    if (currentNeed !=0)
                    
                        ps2->push(currentNeed);
                    
                    currentNeed =')';
                    break;
                default: //如果最后还剩一个不是上面三种字符的情况,字符串括号的匹配肯定是不成功的,这时候可以直接判断不成功
                    cout<<"字符串中的括号不匹配"<<endl;
                    system("pause");
                    return 0;
            
        
        else
        
            //匹配成功两个栈的栈顶都弹出,为了后面的判断
            ps1->pop();
            currentNeed =ps2->pop(); //上一次匹配成功之后,进入下一次匹配的时候首先要保证匹配永远都是和被匹配栈的栈顶匹配
            //如果被匹配ps2的栈以完全出栈,这时候匹配的栈ps1还有值,这时候字符串的括号肯定是不匹配的,所以在执行最后一次循环的之前把当前匹配的字符设定为0
            /*if (ps2->StackEmpty()")
            
                currentNeed =0;
            */
            // 这里有点缺陷,由于我的pop()方法在栈空的时候是报错的,无法再重置currentNeed的值,得到的是一个非法的值,执行结果正确,有瑕疵
        
    
    if (ps1->StackEmpty())
    
        cout<<"字符串中的括号匹配成功"<<endl;
    
    else
        cout<<"字符串中的括号不匹配"<<endl;
    
    system("pause");
    return 0;

参考技术B 很明显,用栈
如果是左括号,入栈
如果是右括号,看栈顶是不是左括号,如果是就把那个左括号出栈;否则不配对(可以直接结束算法)
处理完所有符号后,栈为空则配对成功,否则不配对

括号匹配算法思想

1)凡出现左括弧,则进栈;
2)凡出现右括弧,首先检查栈是否空
若栈空,则表明该“右括弧”多余,
否则和栈顶元素比较,
若相匹配,则“左括弧出栈” ,
否则表明不匹配。
3)表达式检验结束时,
若栈空,则表明表达式中匹配正确,
否则表明“左括弧”有余


有种匹配是:
添加了两个变量 left 和 right ,记录左右括号的数量,若不相等,则说明没有完成配对。

以上是关于设计一个判别表达式中左、右括号是不是配对出现的算法,采用啥数据结构最佳。的主要内容,如果未能解决你的问题,请参考以下文章

数据挖掘2020奇安信秋招算法方向试卷3 笔试题解析

在Java中,设计一个算法,判断一个算术表达式中的括号是不是配对。

括号匹配问题

栈(括号匹配)

括号匹配算法思想

试编写一个算法从检查一个Java语言中的大括号方括号小括号是不是配对,若能够全?