链式栈
链式栈其实和顺序栈差不太多,只是节点之间不再是连续的,而是改成用指针相连。实现自己的链式栈,有助于理解数据结构中的链表和栈。另外这里结合了一个括号成对匹配检测,也就是给定了一个表达式,判断里面的括号是不是成对出现的。个人感觉除了小括号,要是同时需要检测其他括号,只需要加多几个栈,同时进行出栈入栈即可。
判断括号是否成对
从左往右,遇到左括号入栈,遇到右括号出栈。有两种情况不匹配,一是遇到右括号的时候,栈已经空了,这是左括号缺失。而是整个字符串已经遍历完了,而栈还是非空的。这就是右括号缺失了。先观摩一下效果图:
面试应该偶尔会遇到吧。
代码
在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;
}
后话
整个程序,在自定义数据类型那里比较精妙。还有感觉这个箭头也不错,可以再多思考。