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

前言

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

✨栈: 点我

✨队列:点我

ok,下面我们开始把

1.有效的括号

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

 题目内容

【Leetcode】2道题彻底理解栈和队列_第1张图片

【Leetcode】2道题彻底理解栈和队列_第2张图片

 【Leetcode】2道题彻底理解栈和队列_第3张图片

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

【Leetcode】2道题彻底理解栈和队列_第4张图片

 思路分析:

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

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

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

Step1:.左括号,入栈,算法结束

Step2:右括号,出栈顶的左括号与右括号是否匹配

如果匹配,继续。不匹配,终结,算法结束

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

代码运行:

主要部分

【Leetcode】2道题彻底理解栈和队列_第5张图片

 完整代码:

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】2道题彻底理解栈和队列_第6张图片

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

 2.用队列实现栈

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

  题目内容

【Leetcode】2道题彻底理解栈和队列_第7张图片

 【Leetcode】2道题彻底理解栈和队列_第8张图片

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

【Leetcode】2道题彻底理解栈和队列_第9张图片

 思路分析:

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

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

【Leetcode】2道题彻底理解栈和队列_第10张图片

 我们可以这样做:

Step1.入数据,往不为空的队列入(我们要有一个空的队列,作为逆序)

Step2.出数据,把不为空的队列数据倒入为空的队列,直到只剩最后一个

代码运行: 

主要部分:【Leetcode】2道题彻底理解栈和队列_第11张图片

 完整代码:

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);
*/

【Leetcode】2道题彻底理解栈和队列_第12张图片

 

结束语

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

你可能感兴趣的:(小菜鸟刷题,leetcode,c语言,数据结构)