前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Leetcode】2道题彻底理解栈和队列

【Leetcode】2道题彻底理解栈和队列

作者头像
平凡的人1
发布2022-11-15 15:05:03
1720
发布2022-11-15 15:05:03
举报
文章被收录于专栏:从小白开始修炼

前言🎬

好的,前面具体的学习了栈和队列的知识,然后本篇博客的主要内容是做3道OJ题,学完之后,一定要及时地去刷题,对其加深理解和巩固,不然很难有所进步,有利于我们更好的学习数据结构的栈和队列。然后,对栈和队列还不够熟悉的,可以看看我之前写的博客

✨栈:👉 点我 ✨队列:👉点我

ok,下面我们开始把

1.有效的括号

leetcode传送门⏩:20. 有效的括号

📄题目内容

吐槽一下😝:哈哈,这道题第一次打开leetcode的时候就看到了,那时候就想把这道题解决掉,觉得会很简单,可奈何那时的知识储备实在太少,自然无功而返,今天,重新把这道题拿出来,这也算是一种回忆把。感觉很不一样。

🔑 思路分析:

首先一上来,我们就要告诉自己,这是一道非常简单的题。

不知道你是否会有这样的想法:只需要看左括号有多少个,右括号有多少个,比较一下就行了?恭喜你,搞错了,请看示例4。

这道题其实很容易想到我们前面学的栈来解决非常合适。怎么去解决?我概括成以下几点:

Step1:.左括号,入栈,算法结束 Step2:右括号,出栈顶的左括号与右括号是否匹配 如果匹配,继续。不匹配,终结,算法结束

不过很可惜的是,在c语言版本中并没有可以提供栈的函数,我们需要自己手动创建一个栈,包括操作,我们可以拷贝之前博客的代码实现栈的操作。所以,实际上,对于后面一些数据结构用c去实现是非常麻烦的。别人一个类就能几行代码能够解决的事情,你需要很多行,多说了几句。好啦,下面直接上手代码

🔎代码运行:

主要部分

 完整代码:

代码语言:javascript
复制
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;


}

注:不要觉得代码很长哦,前面一大部分只是为了构造堆及其操作👇 

 2.用队列实现栈

leetcode传送门⏩:225. 用队列实现栈

📄题目内容

 这道题有点冗长,不过却是比较容易理解的,就是字面意思。我们最终要的是一个栈

🔑 思路分析:

我们前面说过栈可以用数组或链表去实现,这道题却是出其不意,让我们用两个队列去实现,这同时是在告诉我们,要懂得学会灵活变通。

这道题关键在于我们如何利用两个队列,还有这道题最大的特点就是给了我们比较多的接口,这是之前没有遇到过的。同样的,这道题对于C语言来说太不友好的,不过幸运的是我们之前实现过了队列的相关操作!先来捋捋我们的栈和队列(q1和q2)

 我们可以这样做:

Step1.入数据,往不为空的队列入(我们要有一个空的队列,作为逆序) Step2.出数据,把不为空的队列数据倒入为空的队列,直到只剩最后一个

🔎代码运行: 

主要部分:

 完整代码:

代码语言:javascript
复制
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);
*/

结束语

其实代码量长的主要原因是由于我们需要自己去造“”“轮子”,自己手动去实现栈和队列,主要的逻辑还是易于去理解的。好啦。本次先到这里结束了

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言🎬
  • 1.有效的括号
    • 📄题目内容:
      • 🔑 思路分析:
        • 🔎代码运行:
        •  2.用队列实现栈
          • 📄题目内容:
            • 🔑 思路分析:
              • 🔎代码运行: 
              • 结束语
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档