c++ 数据结构之用自定义链式栈实现括号成对匹配检测

链式栈

链式栈其实和顺序栈差不太多,只是节点之间不再是连续的,而是改成用指针相连。实现自己的链式栈,有助于理解数据结构中的链表和栈。另外这里结合了一个括号成对匹配检测,也就是给定了一个表达式,判断里面的括号是不是成对出现的。个人感觉除了小括号,要是同时需要检测其他括号,只需要加多几个栈,同时进行出栈入栈即可。

判断括号是否成对

从左往右,遇到左括号入栈,遇到右括号出栈。有两种情况不匹配,一是遇到右括号的时候,栈已经空了,这是左括号缺失。而是整个字符串已经遍历完了,而栈还是非空的。这就是右括号缺失了。先观摩一下效果图:
这里写图片描述
面试应该偶尔会遇到吧。

代码

在c++中用c语法写的:

#include<cstdlib>
#include<cstdio>
#include<cstring>
using namespace std;

//用链表实现的后入先出的栈


//链表节点
typedef struct LINKNODE
{
    //注意是指针
    struct LINKNODE* next;
}LinkNode;
//栈,每个节点都是一个链表节点
typedef struct STACK
{
    LinkNode head;
    int size;
}Stack;
//自定义一个数据类型,且第一个元素放节点指针,也就是Person* 和 LinkNode*可以无缝互转
typedef struct PERSON
{
    LinkNode *node;
    int age;
    char name[64];
}Person;
//创建一个空栈
Stack* init()
{
    Stack* stack = (Stack*)malloc(sizeof(Stack));
    stack->size = 0;
    stack->head.next = NULL;
}

//push,栈底在最后面栈顶和head连在一起
void push(Stack* stack,LinkNode* data)
{
    if(stack==NULL || data == NULL)
    {
        return;
    }
    data->next = stack->head.next;
    stack->head.next = data;
    //每次记得size+1啊
    stack->size ++;
}
//获得栈顶
LinkNode* top(Stack* stack)
{
    if(stack==NULL || stack->size == 0)
    {
        return NULL;
    }
    return stack->head.next;
}
//出栈
void pop(Stack* stack)
{
    if(stack==NULL || stack->size ==0)
    {
        return;
    }
    stack->head.next = stack->head.next->next;
    //这里之前忘记--了
    stack->size --;
}

void test()
{
    Stack* stack = init();
    Person p1;
    Person p2;
    Person p3;
    Person p4;
    Person p5;
    printf("test\n");
    strcpy(p1.name,"aaa");
    strcpy(p2.name,"bbb");
    strcpy(p3.name,"ccc");
    strcpy(p4.name,"ddd");
    strcpy(p5.name,"eee");
    p1.age = 1;
    p2.age = 2;
    p3.age = 3;
    p4.age = 4;
    p5.age = 5;
    push(stack,(LinkNode*)&p1);
    push(stack,(LinkNode*)&p2);
    push(stack,(LinkNode*)&p3);
    push(stack,(LinkNode*)&p4);
    push(stack,(LinkNode*)&p5);
    //后入先出
    for(int i = 0;i<5;i++)
    {
        printf("%d:%s\n",((Person*)top(stack))->age,((Person*)top(stack))->name);
        pop(stack);

    }
}

//----------------------------下面是括号检测


//要自定义一个变量类型,也是一个链表节点,带有编号和字符,方便知道哪里缺失
typedef struct MYDATA
{
    LinkNode* node;
    char c;
    int index;
}MyData;

//判断是左括号
int isLeft(char c)
{   
    if(c=='(')
        return 1;
    return 0;
}
//判断右括号
int isRight(char c)
{   
    if(c==')')
        return 1;
    return 0;
}
//看看是哪个位置缺括号了
void lackPos(char* c,int pos)
{
    printf("%s\n",c);
    for(int i = 0;i<pos;i++)
    {
        printf(" ");
    }
    printf("↑\n");
}

//括号检测的主程序
void test2()
{
    //需要检测的自定义表达式
    char* str = "(a-b)(a2+ab+(b2)";
    char* p = str;
    Stack* stack = init();
    //开始判断到底成对不
    int i = 0;
    while(*p!='\0')
    {
        if(isLeft(*p))
        {
            //遇到左括号入栈
            MyData* data = (MyData*)malloc(sizeof(MyData));
            data->index = i;
            push(stack,(LinkNode*)data);
        }
        if(isRight(*p))
        {
            if(stack->size == 0 || stack ==NULL)
            {
                //遇到右括号且栈已经空了,括号不匹配
                lackPos(str,i);
                printf("这个位置左括号缺失\n");
                return;
            }
            //遇到右括号且不为空出栈
            pop(stack);
        }
        p++;
        i++;
    }
    if(stack->size == 0)
    {
        printf("完美对称\n");
    }else
    {
        //右括号已经配对完了且栈还有内容,括号不匹配
        lackPos(str,((MyData*)top(stack))->index);
        printf("这个位置右括号缺失\n");
    }


}


int main()
{
    //test();//测试栈
    test2();//测试括号匹配
    return 0;
}

后话

整个程序,在自定义数据类型那里比较精妙。还有感觉这个箭头也不错,可以再多思考。

猜你喜欢

转载自blog.csdn.net/hiudawn/article/details/80189484
今日推荐