好的,前面具体的学习了栈和队列的知识,然后本篇博客的主要内容是做3道OJ题,学完之后,一定要及时地去刷题,对其加深理解和巩固,不然很难有所进步,有利于我们更好的学习数据结构的栈和队列。然后,对栈和队列还不够熟悉的,可以看看我之前写的博客
✨栈: 点我
✨队列:点我
ok,下面我们开始把
leetcode传送门⏩:20. 有效的括号
吐槽一下:哈哈,这道题第一次打开leetcode的时候就看到了,那时候就想把这道题解决掉,觉得会很简单,可奈何那时的知识储备实在太少,自然无功而返,今天,重新把这道题拿出来,这也算是一种回忆把。感觉很不一样。
首先一上来,我们就要告诉自己,这是一道非常简单的题。
不知道你是否会有这样的想法:只需要看左括号有多少个,右括号有多少个,比较一下就行了?恭喜你,搞错了,请看示例4。
这道题其实很容易想到我们前面学的栈来解决非常合适。怎么去解决?我概括成以下几点:
Step1:.左括号,入栈,算法结束
Step2:右括号,出栈顶的左括号与右括号是否匹配
如果匹配,继续。不匹配,终结,算法结束
不过很可惜的是,在c语言版本中并没有可以提供栈的函数,我们需要自己手动创建一个栈,包括操作,我们可以拷贝之前博客的代码实现栈的操作。所以,实际上,对于后面一些数据结构用c去实现是非常麻烦的。别人一个类就能几行代码能够解决的事情,你需要很多行,多说了几句。好啦,下面直接上手代码
主要部分
完整代码:
typedef char STDataType;
typedef struct Stack
{
STDataType* a;
int top;//栈顶
int capacity;
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
//栈顶插入删除数据
//入栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);
void StackInit(ST* ps)
{
assert(ps);
ps->a = malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
printf("malloc fail\n");
exit(-1);
}
ps->capacity = 4;
ps->top = 0;
}
void StackDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
//栈顶插入删除数据
//入栈
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//满了--增容
if (ps->top == ps->capacity)
{
STDataType* tmp = realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
ps->a = tmp;
ps->capacity *= 2;
}
}
ps->a[ps->top] = x;
ps->top++;
}
//出栈
void StackPop(ST* ps)
{
assert(ps);
//栈空了,调用Pop,直接终止程序报错
assert(ps->top);
ps->top--;
}
STDataType StackTop(ST* ps)
{
assert(ps);
//栈空了,调用Top,直接终止程序报错
assert(ps->top > 0);
return ps->a[ps->top - 1];
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
bool isValid(char * s){
ST st;
StackInit(&st);
while(*s != '\0')
{
switch(*s)
{
case '{':
case '[':
case '(':
{
StackPush(&st,*s);
++s;
break;
}
case '}':
case ']':
case ')':
{
if(StackEmpty(&st))
{
StackDestory(&st);
return false;
}
char top = StackTop(&st);
StackPop(&st);
//不匹配
if((*s == '}' && top !='{')
||(*s == ']' && top !='[')
||(*s == ')' && top !='('))
{
StackDestory(&st);
return false;
}
else{//匹配
++s;
}
break;
}
default:
break;
}
}
bool ret = StackEmpty(&st);
StackDestory(&st);
return ret;
}
注:不要觉得代码很长哦,前面一大部分只是为了构造堆及其操作
leetcode传送门⏩:225. 用队列实现栈
这道题有点冗长,不过却是比较容易理解的,就是字面意思。我们最终要的是一个栈
我们前面说过栈可以用数组或链表去实现,这道题却是出其不意,让我们用两个队列去实现,这同时是在告诉我们,要懂得学会灵活变通。
这道题关键在于我们如何利用两个队列,还有这道题最大的特点就是给了我们比较多的接口,这是之前没有遇到过的。同样的,这道题对于C语言来说太不友好的,不过幸运的是我们之前实现过了队列的相关操作!先来捋捋我们的栈和队列(q1和q2)
我们可以这样做:
Step1.入数据,往不为空的队列入(我们要有一个空的队列,作为逆序)
Step2.出数据,把不为空的队列数据倒入为空的队列,直到只剩最后一个
完整代码:
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestory(Queue* pq);
//队尾入
void QueuePush(Queue* pq, QDataType x);
//队头出
void QueuePop(Queue* pq);
//取队头数据
QDataType QueueFront(Queue* pq);
//取队尾数据
QDataType QueuBack(Queue* pq);
//个数
int QueueSize(Queue* pq);
//判断是否为空
bool QueueEmpty(Queue* pq);
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
void QueueDestory(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
//队尾入
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
//队头出
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head);
//1.一个(防止野指针)
//2.多个
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
QDataType QueuBack(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->tail->data;
}
int QueueSize(Queue* pq)
{
assert(pq);
int size = 0;
QNode* cur = pq->head;
while (cur)
{
++size;
cur = cur->next;
}
return size;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* ps = (MyStack*)malloc(sizeof(MyStack));
if(ps == NULL)
{
printf("malloc fail\n");
exit(-1);
}
QueueInit(&ps->q1);
QueueInit(&ps->q2);
return ps;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else{
QueuePush(&obj->q2,x);
}
}
int myStackPop(MyStack* obj) {
Queue*emptyQ = &obj->q1;
Queue*nonemptyQ = &obj->q2;
if(!QueueEmpty(&obj->q1))
{
emptyQ = &obj->q2;
nonemptyQ = &obj->q1;
}
//倒数据
while(QueueSize(nonemptyQ)>1)
{
QueuePush(emptyQ,QueueFront(nonemptyQ));
QueuePop(nonemptyQ);
}
int top = QueueFront(nonemptyQ);
QueuePop(nonemptyQ);
return top;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))
{
return QueuBack(&obj->q1);
}
else
{
return QueuBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)&& QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
QueueDestory(&obj->q1);
QueueDestory(&obj->q2);
free(obj);
}
/**
* Your MyStack struct will be instantiated and called as such:
* MyStack* obj = myStackCreate();
* myStackPush(obj, x);
* int param_2 = myStackPop(obj);
* int param_3 = myStackTop(obj);
* bool param_4 = myStackEmpty(obj);
* myStackFree(obj);
*/
其实代码量长的主要原因是由于我们需要自己去造“”“轮子”,自己手动去实现栈和队列,主要的逻辑还是易于去理解的。好啦。本次先到这里结束了