当前位置:   article > 正文

OJ题目【栈和队列】

OJ题目【栈和队列】

目录

有效的括号

有效的括号【代码】

用队列实现栈

用队列实现栈【代码】

用栈实现队列

用栈实现队列【代码】

设计循环队列


有效的括号

https://leetcode.cn/problems/valid-parentheses/submissions/551394950/

思路:把左括号放到栈里,取出来栈顶和右括号匹配,匹配上了就出栈,然后在取出栈顶和下一个右括号匹配,一直匹配下去,


创建一个栈用来存放左括号,然后把字符串的首地址s给ps,让ps遍历到\0。


来看看循环里面,

第一步:判断把左括号全部放进栈里。

第二步:判断栈里是不是空,是空就没必要匹配了,没有左括号,直接返回false。

第三步:走到第三步,说明左括号全部放进栈里了,然后取出栈顶给ch,

然后左括号右括号进行匹配,匹配成功就出栈,匹配不成功就销毁,然后返回false。


解决只有一个左括号的情况。

布尔判断栈里是不是空,是空把true给tab,不是空返回false给tab。

销毁空间后,返回tab。


有效的括号【代码】
  1. typedef char data;
  2. typedef struct stack
  3. {
  4. data* arr;
  5. int koj;//空间大小
  6. int top;//栈顶
  7. }SL;
  8. //初始化
  9. void csh(SL* r)
  10. {
  11. r->arr = NULL;
  12. r->koj = r->top = 0;
  13. }
  14. //入栈
  15. void push(SL* r, data x)
  16. {
  17. //判断空间够不够
  18. if (r->koj == r->top)
  19. {
  20. int koj1 = r->koj == 0 ? 4 : 2 * r->koj;
  21. SL* tab = (SL*)realloc(r->arr, koj1 * sizeof(SL));
  22. if (tab == NULL)
  23. {
  24. perror("realloc");
  25. exit(1);
  26. }
  27. r->arr = tab;
  28. r->koj = koj1;
  29. }
  30. r->arr[r->top] = x;
  31. r->top++;
  32. }
  33. bool buer(SL* r)
  34. {
  35. assert(r);
  36. return r->top == 0;
  37. }
  38. //出栈
  39. void pop(SL* r)
  40. {
  41. assert(r);
  42. assert(!buer(r));
  43. --r->top;
  44. }
  45. //取栈顶
  46. data qzd(SL* r)
  47. {
  48. assert(r);
  49. assert(!buer(r));
  50. return r->arr[r->top-1];
  51. }
  52. //取有效个数
  53. data size(SL* r)
  54. {
  55. assert(r);
  56. return r->top;
  57. }
  58. //销毁
  59. void xiaoh(SL* r)
  60. {
  61. assert(r);
  62. if (r->arr != NULL)
  63. {
  64. free(r->arr);
  65. }
  66. r->arr = NULL;
  67. r->koj = r->top = 0;
  68. }
  69. //上面是栈需要的函数
  70. //下面是实现代码
  71. bool isValid(char* s) {
  72. //创建一个栈
  73. SL add;
  74. //把s给ps
  75. char*ps=s;
  76. //循环让ps往后走
  77. while(*ps!='\0')
  78. {
  79. //判断把左括号放进栈里
  80. if(*ps=='(' || *ps=='[' || *ps=='{')
  81. {
  82. push(&add,*ps);
  83. }
  84. else
  85. {
  86. //判断栈顶是不是空,是空返回false。
  87. if(buer(&add))
  88. {
  89. return false;
  90. }
  91. //取出左括号放进ch来
  92. char ch = qzd(&add);
  93. //判断左括号和右括号匹不匹配
  94. if((*ps==')'&&ch=='(')
  95. ||( *ps==']'&&ch=='[')
  96. || (*ps=='}'&& ch=='{'))
  97. {
  98. //匹配出栈
  99. pop(&add);
  100. }
  101. else
  102. {//不匹配直接销毁返回false
  103. xiaoh(&add);
  104. return false;
  105. }
  106. }
  107. ps++;
  108. }
  109. //布尔判断栈里是不是为空,是空把true赋值给tab。
  110. char tab = buer(&add) == true;
  111. xiaoh(&add);
  112. return tab;
  113. }

队列实现栈

https://leetcode.cn/problems/implement-stack-using-queues/description/

实现前先导入队列的函数

思路:创建2个队列

入栈不为空的队列Q1。

出栈的话把Q1的size-1的数据1和2插入Q2的队列,我们就可以把3出栈了。

https://leetcode.cn/problems/implement-stack-using-queues/


第一步:先创建2个队列来实现栈。

第二步:创建ps指向栈,然后初始化这2个队列。


入栈,为不为空的队列,入数据到队列。

if用布尔判断Q1队列是不是空,是空往Q2队列入数据,调用入队列函数。


第一步:把Q1给空队列,把Q2给不为空的队列。

第二步:判断Q1如果不为空,2个交换,把Q1给buko,把Q2给ko。

第三步:循环把有效个数-1的数据,给到为空的队列。

取出队头数据给tab,然后入队到空队列,再把不为空的队列出队。

第四步:把队列的最后一个数据,保存到pop,然后出队列,返回pop。


布尔判断,找不为空的队列,取出队尾数据,返回队尾。


布尔判断2个队列是不是空,2个都为真返回true,有1个或2个为假,返回false。


销毁直接调用销毁队列的函数就行了,然后把obj销毁,把obj置为NULL。


用队列实现栈【代码】
  1. typedef int data;
  2. typedef struct queuedata//单链表
  3. {
  4. data arr;//存放的数据
  5. struct queuedata* p;//指向下一个节点
  6. }queuedata;
  7. typedef struct Queue
  8. {
  9. queuedata* to; //队头——单链表的 头节点
  10. queuedata* wei;//队尾——单链表的 尾节点
  11. int size; //有效个数
  12. }Queue;
  13. //初始化
  14. void csh(Queue* r)
  15. {
  16. assert(r);
  17. r->to = r->wei = NULL;
  18. r->size = 0;
  19. }
  20. //入队尾
  21. void dui_wei(Queue* r,data x)
  22. {
  23. assert(r);
  24. //申请单链表空间
  25. queuedata* tab = (queuedata*)malloc(sizeof(queuedata));
  26. if (tab == NULL)
  27. {
  28. perror("malloc");
  29. exit(1);
  30. }
  31. //把x赋值给新申请空间的arr
  32. tab->arr = x;
  33. tab->p = NULL;
  34. //入队
  35. //判断队尾是不是空
  36. if (r->wei == NULL)
  37. {
  38. //是空,队头队尾指向新申请的空间
  39. r->to = r->wei = tab;
  40. }
  41. else//不是空
  42. {
  43. //队尾p指向新申请的空间
  44. r->wei->p = tab;
  45. //队尾走到新申请的空间
  46. r->wei = r->wei->p;
  47. }
  48. //有效个数加1
  49. r->size++;
  50. }
  51. //布尔类型
  52. bool buer(Queue* r)
  53. {
  54. assert(r);
  55. return r->to == NULL;
  56. }
  57. //出队,头
  58. void dui_to(Queue* r)
  59. {
  60. assert(r);
  61. //布尔类型,!把真变假,把假变真
  62. assert(!buer(r));
  63. //判断队头等于队尾,就说明只有一个节点
  64. if (r->to == r->wei)
  65. {
  66. //直接释放空间
  67. free(r->to);
  68. //把队头和队尾置为空
  69. r->to = r->wei = NULL;
  70. }
  71. else
  72. {
  73. //把队头的下一个节点给tab
  74. queuedata* tab = r->to->p;
  75. //释放当前队头节点
  76. free(r->to);
  77. //把tab节点给队头
  78. r->to = tab;
  79. }
  80. //有效个数减1
  81. --r->size;
  82. }
  83. //取队头数据
  84. data qto(Queue* r)
  85. {
  86. assert(r);
  87. assert(!buer(r));
  88. return r->to->arr;
  89. }
  90. //取尾
  91. data qwei(Queue* r)
  92. {
  93. assert(r);
  94. assert(!buer(r));
  95. return r->wei->arr;
  96. }
  97. //有效个数
  98. data size(Queue* r)
  99. {
  100. assert(r);
  101. return r->size;
  102. }
  103. //销毁
  104. void xiaoh(Queue* r)
  105. {
  106. assert(r);
  107. //assert(!buer(r));
  108. //把队头给tab
  109. queuedata* tab = r->to;
  110. //循环销毁单链表
  111. while (tab != NULL)
  112. {
  113. //add保存头节点的下一个节点
  114. queuedata* add = tab->p;
  115. //释放头节点
  116. free(tab);
  117. //把add给tab
  118. tab = add;
  119. }
  120. //把队头和队尾置为空
  121. r->to = r->wei = NULL;
  122. //有效个数赋值为0
  123. r->size = 0;
  124. }
  125. //上面是队列的函数
  126. /
  127. //下面是实现代码
  128. typedef struct {
  129. //创建2个队列来实现栈
  130. Queue Q1;
  131. Queue Q2;
  132. } MyStack;
  133. //栈初始化
  134. MyStack* myStackCreate()
  135. {
  136. //创建ps指向栈
  137. MyStack*ps=(MyStack*)malloc(sizeof(MyStack));
  138. //初始化这2个队列
  139. csh(&ps->Q1);
  140. csh(&ps->Q2);
  141. return ps;
  142. }
  143. //入栈
  144. void myStackPush(MyStack* obj, int x) {
  145. //往不为空的队列插入数据
  146. if(!buer(&obj->Q1))
  147. {
  148. dui_wei(&obj->Q1, x);
  149. }
  150. else
  151. {
  152. dui_wei(&obj->Q2, x);
  153. }
  154. }
  155. //出栈
  156. int myStackPop(MyStack* obj) {
  157. //空
  158. Queue* ko = &obj->Q1;
  159. //不为空
  160. Queue* buko = &obj->Q2;
  161. //找不为空的队列
  162. if(!buer(&obj->Q1))
  163. {
  164. buko = &obj -> Q1;
  165. ko = &obj -> Q2;
  166. }
  167. //把有数据的队列中size-1个数据导入到空队列中
  168. while(size(buko) > 1)
  169. {
  170. //取队头给tab
  171. int tab = qto(buko);
  172. //把tab的数据给 ko空队列
  173. dui_wei(ko , tab);
  174. //出队,头
  175. dui_to(buko);
  176. }
  177. //不为空的队列还剩下一个数据,给pop
  178. int pop = qto(buko);
  179. //最后一个数据出栈
  180. dui_to(buko);
  181. //返回pop
  182. return pop;
  183. }
  184. //取栈顶元素
  185. int myStackTop(MyStack* obj) {
  186. //找不为空的队列,取出队尾数据
  187. if(!buer(&obj->Q1))
  188. {
  189. return qwei(&obj->Q1);
  190. }
  191. else
  192. {
  193. return qwei(&obj->Q2);
  194. }
  195. }
  196. bool myStackEmpty(MyStack* obj) {
  197. //用布尔判断2个队列是不是空
  198. return buer(&obj->Q1) && buer(&obj->Q2);
  199. }
  200. //销毁
  201. void myStackFree(MyStack* obj) {
  202. //直接调用销毁队列的函数就行了
  203. xiaoh(&obj->Q1);
  204. xiaoh(&obj->Q2);
  205. //把我们申请的ps销毁,obj就是ps,返回了ps然后obj接收。
  206. free(obj);
  207. //置为空
  208. obj=NULL;
  209. }
  210. /**
  211. * Your MyStack struct will be instantiated and called as such:
  212. * MyStack* obj = myStackCreate();
  213. * myStackPush(obj, x);
  214. * int param_2 = myStackPop(obj);
  215. * int param_3 = myStackTop(obj);
  216. * bool param_4 = myStackEmpty(obj);
  217. * myStackFree(obj);
  218. */

用栈实现队列

https://leetcode.cn/problems/implement-queue-using-stacks/description/

实现前先导入栈的函数


思路:用2个栈Q1,Q2,

入队列:往Q1导入数值,

出队列(头):判断Q2是不是空,是就循环取出Q1栈顶,导入到Q2,Q2再出栈,出的就是队头了,对了还要先保存队头,再返回队头的数据。

取队头数据:判断Q2是不是空,不是空就说明数据已经导入到Q2了,直接取栈顶。

myQueueEmpty:判断队列是不是空。

销毁:调用销毁函数,销毁2个栈,再把申请的obj空间释放,然后置为空。


第一步:创建2个栈。

第二步:创建ps空间指向Q1和Q2,

然后初始化这2个栈,返回ps。


直接调用,入栈函数,为Q1导入数据就行了。


判断Q2栈是不是空,是空的话循环把Q1的全部数值,导入到Q2,

取出Q2栈顶给tab,Q2出栈,返回tab。


判断Q2栈是不是空,是空的话循环把Q1的全部数值,导入到Q2

返回Q2栈顶的元素就行了。


判断队列是不是空,是空返回false,不是空返回true。


把Q1和Q2的栈销毁,然后销毁obj,把obj置为空。


用栈实现队列【代码】
  1. typedef int data;
  2. typedef struct stack
  3. {
  4. data* arr;//存放数值
  5. int koj; //空间
  6. int top; //栈顶
  7. }stack;
  8. //初始化
  9. void stack_csh(SL* r)
  10. {
  11. assert(r);
  12. r->arr = NULL;
  13. r->koj = r->top = 0;
  14. }
  15. //入栈
  16. void stack_push(stack* r, data x)
  17. {
  18. assert(r);
  19. //空间大小等于栈顶,就说明空间不够
  20. if (r->koj == r->top)
  21. {
  22. int koj1 = r->koj == 0 ? 4 : 2 * r->koj;
  23. stack* tab = (stack*)realloc(r->arr, sizeof(stack));
  24. if (tab == NULL)
  25. {
  26. perror("realloc");
  27. exit(1);
  28. }
  29. //把新申请的空间给r
  30. r->arr = tab;
  31. r->koj = koj1;
  32. }
  33. //空间够直接入栈
  34. r->arr[r->top] = x;
  35. r->top++;
  36. }
  37. //布尔类型
  38. bool buer(stack* r)
  39. {
  40. assert(r);
  41. return r->top == 0;
  42. }
  43. //出栈
  44. void stack_pop(stack* r)
  45. {
  46. assert(r);
  47. //布尔类型
  48. assert(!buer(r));
  49. r->top--;
  50. }
  51. //取出栈顶
  52. data stack_top(stack* r)
  53. {
  54. assert(r);
  55. assert(!buer(r));
  56. return r->arr[r->top - 1];
  57. }
  58. //有效个数
  59. data stack_size(stack* r)
  60. {
  61. assert(r);
  62. return r->top;
  63. }
  64. //销毁
  65. void xiaoh(stack* r)
  66. {
  67. assert(r);
  68. if (r->arr != NULL)
  69. {
  70. free(r->arr);
  71. }
  72. r->arr = NULL;
  73. r->koj = r->top = 0;
  74. }
  75. //上面是栈的函数
  76. /
  77. //下面是实现代码
  78. typedef struct {
  79. //创建2个栈
  80. stack Q1;
  81. stack Q2;
  82. } MyQueue;
  83. //初始化
  84. MyQueue* myQueueCreate() {
  85. //创建指针指向Q1和Q2
  86. MyQueue* ps = (MyQueue*)malloc(sizeof(MyQueue));
  87. //初始化2个栈
  88. stack_csh(&ps->Q1);
  89. stack_csh(&ps->Q2);
  90. //返回ps
  91. return ps;
  92. }
  93. //入栈(入队列)
  94. void myQueuePush(MyQueue* obj, int x) {
  95. //调用入栈函数,为Q1入栈
  96. stack_push(&obj->Q1 , x);
  97. }
  98. //出栈(出队列,头)
  99. int myQueuePop(MyQueue* obj) {
  100. //判断Q2是不是空,不是空说明Q2栈里有数据
  101. if( buer(&obj->Q2) )
  102. {
  103. //是空,循环取出Q1的数值,导入Q2栈里
  104. while(!buer(&obj->Q1))
  105. {
  106. //入栈到Q2 取出Q1栈顶
  107. stack_push(&obj->Q2,stack_top(&obj->Q1));
  108. //Q1出栈
  109. stack_pop(&obj->Q1);
  110. }
  111. }
  112. //取出Q2的栈顶给tab(取队头)
  113. int tab = stack_top(&obj->Q2);
  114. //Q2出栈
  115. stack_pop(&obj->Q2);
  116. return tab;
  117. }
  118. //取栈顶(队头)
  119. int myQueuePeek(MyQueue* obj) {
  120. //判断Q2是不是空,不是空说明Q2栈里有数据
  121. if( buer(&obj->Q2) )
  122. {
  123. //是空,循环取出Q1的数值,导入Q2栈里
  124. while(!buer(&obj->Q1))
  125. {
  126. //入栈到Q2 取出Q1栈顶
  127. stack_push(&obj->Q2,stack_top(&obj->Q1));
  128. //Q1出栈
  129. stack_pop(&obj->Q1);
  130. }
  131. }
  132. //返回Q2的栈顶(返回队头)
  133. return stack_top(&obj->Q2);
  134. }
  135. bool myQueueEmpty(MyQueue* obj) {
  136. //判断这2个栈是不是都为空(判断队列是不是空)
  137. return buer(&obj->Q1) && buer(&obj->Q2);
  138. }
  139. void myQueueFree(MyQueue* obj) {
  140. //销毁
  141. xiaoh(&obj->Q1);
  142. xiaoh(&obj->Q2);
  143. //也把obj销毁
  144. free(obj);
  145. obj=NULL;
  146. }
  147. /**
  148. * Your MyQueue struct will be instantiated and called as such:
  149. * MyQueue* obj = myQueueCreate();
  150. * myQueuePush(obj, x);
  151. * int param_2 = myQueuePop(obj);
  152. * int param_3 = myQueuePeek(obj);
  153. * bool param_4 = myQueueEmpty(obj);
  154. * myQueueFree(obj);
  155. */

设计循环队列

https://leetcode.cn/problems/design-circular-queue/description/

这个队列底层使用数组,比较好实现。


结构体的参数,数组,头,尾,空间大小。


申请ps的一个结构体,

给arr申请一个数值的空间,我们申请的数值空间必须多一块空间,方便5%5等于0。

初始化:把头尾初始化为0,空间大小初始化为k,k就是4。


第一步:先判断队列是不是满了,满了直接返回false,没有满插入数据。

第二步:为arr数组wei下标位置插入数据,然后++,参考【1%5=1, 2%5=2 ,3%5=3, 4%5=4, 5%5=0】。

当wei走到下标为5,5%5=0,所以就会回到0,返回true。


第一步:判断队列是不是空,是空直接返回false。

第二步:头直接++就好了,1%5=1, 2%5=2 ,3%5=3, 4%5=4, 5%5=0

当to走到下标为5,5%5=0,所以就会回到0,返回true。


先判断是不是空,不是空返回头,是空返回-1。


第一步:判断队列是不是空。

第二步:把wei-1的数据赋值tab,为什么是wei-1呢?

上面这一张图,我们可以看到插入数据后就++了,所以我们取队尾,wei-1。

第三步:判断尾下标是不是0,这里是一种特殊情况0-1=-1,-1没有下标,

我们直接把空间大小给tab就是下标为4这个元素了。

返回arr下标为tab的数值。



设计循环队列代码
  1. typedef struct {
  2. int *arr;
  3. int to;//头
  4. int wei;//尾
  5. int kojdax;//空间大小
  6. } MyCircularQueue;
  7. //初始化
  8. MyCircularQueue* myCircularQueueCreate(int k) {
  9. //申请空间
  10. MyCircularQueue* ps = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
  11. // 4 * 5 = 20,就是5个空间
  12. ps->arr = (int*)malloc(sizeof(int) * (k + 1));
  13. //初始化
  14. ps->to = ps->wei = 0;
  15. ps->kojdax = k;
  16. return ps;
  17. }
  18. bool myCircularQueueIsFull(MyCircularQueue* obj) {
  19. //判断队列是不是满了,等于头就说明满了
  20. return (obj->wei+1) % (obj->kojdax+1) == obj->to;
  21. }
  22. //入队列
  23. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
  24. //队列满了不能插入数据
  25. if(myCircularQueueIsFull(obj))
  26. {
  27. return false;
  28. }
  29. //在wei位置插入数据,然后++
  30. obj->arr[obj->wei++] = value;
  31. //5 % 5 = 0,rear走到5下标的时候回到下标为0的位置。
  32. obj->wei %= obj->kojdax + 1;
  33. return true;
  34. }
  35. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
  36. //等于就说明队列是空
  37. return obj->to == obj->wei;
  38. }
  39. //出队列
  40. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
  41. //队列为空
  42. if(myCircularQueueIsEmpty(obj))
  43. {
  44. return false;
  45. }
  46. //队列不为空
  47. //头往后走就行
  48. obj->to++;
  49. //会越界所以:5 % 5 = 0,to走到5下标的时候回到下标为0的位置。
  50. obj->to %= obj->kojdax + 1;
  51. return true;
  52. }
  53. //取队头
  54. int myCircularQueueFront(MyCircularQueue* obj) {
  55. //判断队列是不是空
  56. if(myCircularQueueIsEmpty(obj))
  57. {
  58. return -1;
  59. }
  60. //返回头
  61. return obj->arr[obj->to];
  62. }
  63. //取队尾
  64. int myCircularQueueRear(MyCircularQueue* obj) {
  65. //判断队列是不是空
  66. if(myCircularQueueIsEmpty(obj))
  67. {
  68. return -1;
  69. }
  70. //把wei-1的数据给tab
  71. int tab = obj->wei - 1;
  72. //尾等于下标0
  73. if(obj->wei == 0)
  74. {
  75. //把有效个数4给tab
  76. tab = obj -> kojdax;
  77. }
  78. //返回tab
  79. return obj->arr[tab];
  80. }
  81. //销毁
  82. void myCircularQueueFree(MyCircularQueue* obj) {
  83. free(obj->arr);
  84. free(obj);
  85. obj=NULL;
  86. }

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号