当前位置:   article > 正文

LeetCode_栈和队列相关OJ

LeetCode_栈和队列相关OJ

 

0c76f4c1e358481fbc51e89cd6e2e854.png

✨✨所属专栏:LeetCode刷题专栏✨✨

✨✨作者主页:嶔某✨✨

上一篇:数据结构_栈和队列(Stack & Queue)-CSDN博客 

 有效的括号

fa8665e0221848ac8d681622763fdf99.png

解析:

这里我们用数组实现的栈来解决这个问题,在有了栈的几个基础接口之后,我们运用这几个接口解决问题。

首先新建一个栈并初始化,进入循环如果当前指针指向的字符元素为左括号 {([ 就入栈,反之就出栈,之后判断指针指向的字符是否和出栈的字符左右括号相匹配。

(  (top == '{'&& *s != '}')  ||  (top == '['&& *s != ']')  ||  (top == '('&& *s !=')')  )

 每次循环后s++,如果 *s != '\0' 就进行下一次循环。

写完后提交会发现当只有一个元素的时候这种写法是不能过的

e66b9b3067d24488a17ef5e12181c92a.png

 这里我们在else里面做一个判空,因为如果进了else里面,就说明这是个右括号,那么栈里面一定有其所对应的左括号,如果这时后栈为空,那么显然括号之间是不匹配的。这样就很好的解决了诸如此类的问题。

if(STEmpty(&S))
{
        STDestroy(&S);
        return false;

}

最后s遇到了 '\0' 循环结束,我们判断栈是否为空,如果为空返回true,否则栈中还有元素括号之间也是不匹配的。

return STEmpty(&S);

 可以这么理解这两段代码:一个判断了左括号是否多了,一个判断了右括号是否多了。

 示例代码:

 function/数据结构_栈 · 钦某/c-language-learning - 码云 - 开源中国 (gitee.com)https://gitee.com/wang-qin928/c-language-learning/tree/master/function/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84_%E6%A0%88

  1. bool isValid(char* s)
  2. {
  3. ST S;
  4. STInit(&S);
  5. while(*s)
  6. {
  7. if(*s == '{' || *s == '[' || *s == '(')
  8. {
  9. STPush(&S,*s);
  10. }
  11. else
  12. {
  13. if(STEmpty(&S))
  14. {
  15. STDestroy(&S);
  16. return false;
  17. }
  18. char top = STTop(&S);
  19. STPop(&S);
  20. if((top == '{'&& *s != '}')||
  21. (top == '['&& *s != ']') ||
  22. (top == '('&& *s !=')'))
  23. {
  24. STDestroy(&S);
  25. return false;
  26. }
  27. }
  28. s++;
  29. }
  30. return STEmpty(&S);
  31. }

 用队列实现栈

3aeb55e96b4742ab99063dab48a0291b.png

解析:

这里我们使用数组实现的队列,只需要创建两个队列,把数据在两个队列之间互相导就行了。

定义结构体MyStack:

将mystack结构体里面创建两个队列q1、q2。

myStackCreate函数:

malloc出结构体pst的内存空间 ,并将q1、q2交给 QueueInit函数,返回这个结构体。

myStackPush函数:

将数据方放进 QueuePush,入队列q1就行。

myStackPop函数:

将q1队列的数据转到q2里面,最后剩一个数据不转,直接删除,之后再将数据从q2转到q1里面。返回删除的那个数据。

myStackTop函数:

和上一个函数一样,只不过myStackTop不删除数据,直接返回就好了。

myStackEmpty函数:

return !QueueSize(&(obj->q1));

 myStackFree函数:

这里一定要先释放q1、q2的空间之后再释放pst。

示例代码:

function/队列 · 钦某/c-language-learning - 码云 - 开源中国 (gitee.com)https://gitee.com/wang-qin928/c-language-learning/tree/master/function/%E9%98%9F%E5%88%97

  1. typedef struct {
  2. Queue q1;
  3. Queue q2;
  4. } MyStack;
  5. MyStack* myStackCreate() {
  6. MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
  7. QueueInit(&(pst->q1));
  8. QueueInit(&(pst->q2));
  9. return pst;
  10. }
  11. void myStackPush(MyStack* obj, int x) {
  12. QueuePush(&(obj->q1),x);
  13. }
  14. int myStackPop(MyStack* obj) {
  15. while(QueueSize(&(obj->q1)) != 1)
  16. {
  17. QueuePush(&(obj->q2),QueueFront(&(obj->q1)));
  18. QueuePop(&(obj->q1));
  19. }
  20. int tmp = QueueFront(&(obj->q1));
  21. QueuePop(&(obj->q1));
  22. while(QueueSize(&(obj->q2)))
  23. {
  24. QueuePush(&(obj->q1),QueueFront(&(obj->q2)));
  25. QueuePop(&(obj->q2));
  26. }
  27. return tmp;
  28. }
  29. int myStackTop(MyStack* obj) {
  30. return QueueBack(&(obj->q1));
  31. }
  32. bool myStackEmpty(MyStack* obj) {
  33. return !QueueSize(&(obj->q1));
  34. }
  35. void myStackFree(MyStack* obj) {
  36. Destory(&(obj->q1));
  37. Destory(&(obj->q2));
  38. free(obj);
  39. }

 用栈实现队列

55a9b73110954d878af70071ad863d35.png

解析:

此题与上题思路差不多,有一些细节上的改变,我们在代码里面细说。

定义结构体MyQueue:

创建两个栈st1、st2

myQueueCreate函数:

为MyQueue结构体malloc一块空间,将里面的st1、st2交给 STInit函数。

myQueuePush函数:

直接利用STPush函数插入就行。

myQueuePeek函数:

这里判断一下,如果st2为空的话,就将st1的数据转到st2来,取栈顶元素返回(转过来的时候数据会反过来)如果st2不为空,就直接返回st2栈顶元素。

myQueuePop函数:

这里本来也是要进行判断、转数据的,但是我们可以简化一下代码,直接调用myQueuePeek返回值存起来,这样st2必然就有数据,我们就可以直接pop掉st2里面的数据。

myQueueEmpty函数:

只有st1、st2同时为空,这个队列才为空。

myQueueFree函数:

先用 STDestroy释放掉st1、st2的空间,之后再free掉obj。

总结:此题目不用将st2的数据再转回到st1里,相当于st2是专门用来出数据的,st1专门用来入数据的。

示例代码:

function/数据结构_栈 · 钦某/c-language-learning - 码云 - 开源中国 (gitee.com)https://gitee.com/wang-qin928/c-language-learning/tree/master/function/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84_%E6%A0%88

  1. typedef struct {
  2. ST st1;
  3. ST st2;
  4. } MyQueue;
  5. MyQueue* myQueueCreate() {
  6. MyQueue* Q = (MyQueue*)malloc(sizeof(MyQueue));
  7. STInit(&(Q->st1));
  8. STInit(&(Q->st2));
  9. return Q;
  10. }
  11. void myQueuePush(MyQueue* obj, int x) {
  12. STPush(&(obj->st1),x);
  13. }
  14. int myQueuePop(MyQueue* obj) {
  15. int tmp = myQueuePeek(obj);
  16. STPop(&(obj->st2));
  17. return tmp;
  18. }
  19. int myQueuePeek(MyQueue* obj) {
  20. if(STEmpty(&(obj->st2)))
  21. {
  22. while(!STEmpty(&(obj->st1)))
  23. {
  24. STPush(&(obj->st2),STTop(&(obj->st1)));
  25. STPop(&(obj->st1));
  26. }
  27. return STTop(&(obj->st2));
  28. }
  29. else
  30. {
  31. return STTop(&(obj->st2));
  32. }
  33. }
  34. bool myQueueEmpty(MyQueue* obj) {
  35. return (STEmpty(&(obj->st1)) && STEmpty(&(obj->st2)));
  36. }
  37. void myQueueFree(MyQueue* obj) {
  38. STDestroy(&(obj->st1));
  39. STDestroy(&(obj->st2));
  40. free(obj);
  41. }

设计循环队列 

7695610debf84b95b303e6eb554eeb23.png

解析:

用数组实现,多开辟一块空间,防止假溢出。或多定义一个size元素记录数组元素个数。主要都是为了解决判空和判满的问题。

定义MyCircularQueue结构体:

一个int*指针、一个head、一个tail、一个k表示队列容量。

myCircularQueueCreate函数:

为MyCircularQueue建立空间,并为data建立空间,其他值:obj->head = obj->tail = 0,obj->k = k。

myCircularQueueIsEmpty函数:

如果obj->head == obj->tail就为空,返回true,反之返回false。

09c5a4dc0d664cceb48796cde149f93b.png

myCircularQueueIsFull函数:

如果obj->head == (obj->tail+1)%(obj->k+1)就为满,返回true,反之返回false。

2504324f2bc347de88ad48254f13d16a.png

myCircularQueueEnQueue函数:

先判断是否为满,之后再往里面插入数据。注意这里tail的变化:

(obj->tail) %= (obj->k+1);

myCircularQueueDeQueue函数:

先判断是否为空,之后再删除数据。注意head的变化:

 (obj->head) %= (obj->k+1);

myCircularQueueFront函数:

return myCircularQueueIsEmpty(obj)?-1:obj->data[obj->head];

myCircularQueueRear函数:

return myCircularQueueIsEmpty(obj)?-1:obj->data[(obj->tail+obj->k)%(obj->k+1)];

注意这里tail+1后可能回超出范围,所以我们要在这里模上(k+1)。

myCircularQueueFree函数:

先free掉obj->data,之后free掉obj。

总结:

我们要时刻注意,tail和head的范围,不能超过k,否则就应该模上(k+1)。其次这道题用单链表写会麻烦很多,因为不好处理循环的问题。如果你用双向循环链表,当我没说……(我们要用最少的消耗,干最多的事儿!)

示例代码:

  1. typedef struct {
  2. int *data;
  3. int head;
  4. int tail;
  5. int k;
  6. } MyCircularQueue;
  7. MyCircularQueue* myCircularQueueCreate(int k) {
  8. MyCircularQueue* CQ = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
  9. CQ->data = (int*)malloc(sizeof(int)*(k+1));//data需另外开辟空间
  10. CQ->head = 0;
  11. CQ->tail = 0;
  12. CQ->k = k;
  13. return CQ;
  14. }
  15. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
  16. return obj->head == obj->tail;
  17. }
  18. bool myCircularQueueIsFull(MyCircularQueue* obj) {
  19. return (obj->tail+1) % (obj->k + 1) == obj->head;
  20. }
  21. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
  22. if(myCircularQueueIsFull(obj))
  23. return false;
  24. obj->data[obj->tail] = value;
  25. obj->tail++;
  26. (obj->tail) %= (obj->k+1);
  27. return true;
  28. }
  29. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
  30. if(myCircularQueueIsEmpty(obj))
  31. return false;
  32. obj->head++;
  33. (obj->head) %= (obj->k+1);
  34. return true;
  35. }
  36. int myCircularQueueFront(MyCircularQueue* obj) {
  37. return myCircularQueueIsEmpty(obj)?-1:obj->data[obj->head];
  38. }
  39. int myCircularQueueRear(MyCircularQueue* obj) {
  40. return myCircularQueueIsEmpty(obj)?-1:obj->data[(obj->tail+obj->k)%(obj->k+1)];
  41. }
  42. void myCircularQueueFree(MyCircularQueue* obj) {
  43. free(obj->data);
  44. free(obj);
  45. }

本期博客到这里就结束了,如果有什么错误,欢迎指出,如果对你有帮助,请点个赞,谢谢!

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/620910
推荐阅读
相关标签
  

闽ICP备14008679号