• 用栈实现队列、用队列实现栈(C语言_leetcode_232+225)


    前两天实现了栈和队列,现在做两道经典的例题来巩固所学的知识。

    题目链接:

    232. 用栈实现队列 - 力扣(LeetCode)

    225. 用队列实现栈 - 力扣(LeetCode)

    目录

    一、用栈实现队列

    二、用队列实现栈

     三、源码

    3.1 栈-->队列  源码

    3.2 队列-->栈  源码


    一、用栈实现队列

    思路:

    ①构建两个栈实现队列。一个栈为input栈,只存入数据;一个栈为output栈,只负责出数据

    ②当出数据时,先判断output栈是否为空(StackEmpty(&output)),如果为空,要把input栈中的数据全部导入到output栈中,然后再出output栈顶元素,再删除一个output栈中的数据。

    这时我们来分析为什么要让output为空时才倒数据。

    注意了!栈是先进后出哦!只有当output为空的时候才能倒数据,要不然后插入的数据会将出栈的顺序打乱。

    因为我们是使用C语言做这道题,我们要自己创建栈,这点是比较麻烦的,好在是前两天我们实现了一个栈,直接拿来使用即可。

    源码较长,我放在最后,可以通过目录跳转。


    二、用队列实现栈

    思路:

    ①一个队列存放输入的数据,一个队列专门为空,在出数据时用于保存数据。这两个队列每出一次数据时会进行功能的倒换。

    ②出数据时,要将存数据的队列中数据导入到空队列中,直到只留下一个数据。然后将此数据输出,如果是Pop型,输出后则将数据删除,如果是Top型,则将数据输出后再插入到倒数据队列。

    步骤:

    一、插入数据

    如果q1为空,则q1是用于倒数据的队列,所以放入q2,反之亦然,q2为空放数据插入q1。

    二、取数据

    1.将除了最后一个数据之外的剩下数据全部导入到倒数据队列,然后将剩下这最后一个数据输出。

    2.如果要求是Pop型,输出后则将该数据删除;如果是Top型,则将数据输出后再插入到倒数据队列。

     


    三、源码

    因为C语言没有这些结构的库,我们只能手搓出栈和队列,好在前两天我们实现过栈和队列,这时我们直接将其拷贝过来然后套用既可,所以代码有点多。

    3.1 栈-->队列  源码

    1. #include <stdio.h>
    2. #include <assert.h>
    3. #include <stdbool.h>
    4. #include <stdlib.h>
    5. typedef int STDateType;
    6. typedef struct Stack
    7. {
    8. STDateType* a;
    9. int top; //标识栈顶的数据
    10. int capacity; //动态性的 可以扩容
    11. }ST;
    12. void StackInit(ST* ps);
    13. void StackDestory(ST* ps);
    14. void StackPush(ST* ps, STDateType x);
    15. void StackPop(ST* ps);
    16. STDateType StackTop(ST* ps); //取栈顶的元素
    17. bool StackEmpty(ST* ps); //判断栈是否为空
    18. int StackSize(ST* ps); //得知栈的大小
    19. void StackInit(ST* ps)
    20. {
    21. assert(ps);
    22. ps->a = NULL;
    23. ps->top = 0;
    24. ps->capacity = 0;
    25. }
    26. void StackDestory(ST* ps)
    27. {
    28. assert(ps);
    29. free(ps->a);
    30. ps->a = NULL;
    31. ps->top = ps->capacity = 0;
    32. }
    33. void StackPush(ST* ps, STDateType x)
    34. {
    35. assert(ps);
    36. if (ps->capacity == ps->top)
    37. {
    38. int NewCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
    39. STDateType* temp = (STDateType * )realloc(ps->a, sizeof(STDateType) * NewCapacity);
    40. if (temp == NULL)
    41. {
    42. printf("realloc fail");
    43. exit(-1);
    44. }
    45. ps->a = temp;
    46. ps->capacity = NewCapacity;
    47. }
    48. ps->a[ps->top] = x;
    49. ps->top++;
    50. }
    51. void StackPop(ST* ps)
    52. {
    53. assert(ps);
    54. assert(!StackEmpty(ps));
    55. ps->top--;
    56. }
    57. STDateType StackTop(ST* ps)
    58. {
    59. assert(ps);
    60. assert(!StackEmpty(ps));
    61. return ps->a[ps->top - 1];
    62. }
    63. bool StackEmpty(ST* ps)
    64. {
    65. assert(ps);
    66. return ps->top == 0;
    67. }
    68. int StackSize(ST* ps)
    69. {
    70. assert(ps);
    71. return ps->top;
    72. }
    73. typedef struct {
    74. ST input; //input栈
    75. ST output; //output栈
    76. } MyQueue;
    77. //将队列创建好 并返回
    78. MyQueue* myQueueCreate() {
    79. //开辟一个结构体变量的空间
    80. //表示我们自己创建的结构体 MyQueue
    81. MyQueue* obj =(MyQueue*)malloc(sizeof(MyQueue));
    82. //注意,在创建一个MyQueue中,我们是创建了一个栈,如果我们调用了栈的函数,是需要将该栈的地址传入函数才能符合其类型
    83. StackInit(&obj->input);
    84. StackInit(&obj->output);
    85. return obj;
    86. }
    87. void myQueuePush(MyQueue* obj, int x) {
    88. //将数据放入input栈
    89. StackPush(&obj->input,x);
    90. }
    91. int myQueuePop(MyQueue* obj) {
    92. //将数据弹出
    93. //如果output空,则表示出数据栈为空,则要导数据
    94. if(StackEmpty(&obj->output))
    95. {
    96. //直到input为空
    97. while(!StackEmpty(&obj->input))
    98. {
    99. //将input的数据放入output
    100. //插入一个 Pop一个
    101. StackPush(&obj->output,StackTop(&obj->input));
    102. StackPop(&obj->input);
    103. }
    104. }
    105. int ret=StackTop(&obj->output);
    106. StackPop(&obj->output);
    107. return ret;
    108. }
    109. bool myQueueEmpty(MyQueue* obj) {
    110. //两个栈为空,即队列为空
    111. return (StackEmpty(&obj->input)&& StackEmpty(&obj->output));
    112. }
    113. int myQueuePeek(MyQueue* obj) {
    114. //如果队列为空
    115. if (myQueueEmpty(obj))
    116. {
    117. return -1;
    118. }
    119. if(StackEmpty(&obj->output))
    120. {
    121. while(!StackEmpty(&obj->input))
    122. {
    123. //将input的数据放入output
    124. StackPush(&obj->output,StackTop(&obj->input));
    125. StackPop(&obj->input);
    126. }
    127. }
    128. return StackTop(&obj->output);
    129. }
    130. void myQueueFree(MyQueue* obj) {
    131. StackDestory(&obj->input);
    132. StackDestory(&obj->output);
    133. free(obj);
    134. }

    3.2 队列-->栈  源码

    1. #include <stdio.h>
    2. #include <stdbool.h>
    3. #include <stdlib.h>
    4. #include <assert.h>
    5. typedef int QDataType;
    6. typedef struct QueueNode
    7. {
    8. struct QueueNode* next;
    9. QDataType data;
    10. }QNode;
    11. typedef struct Queue
    12. {
    13. QNode* head;
    14. QNode* tail;
    15. }Queue;
    16. void QueueInit(Queue* pq)
    17. {
    18. assert(pq);
    19. pq->head = pq->tail = NULL;
    20. }
    21. void QueueDestroy(Queue* pq)
    22. {
    23. assert(pq);
    24. QNode* Dest = pq->head;
    25. while (Dest)
    26. {
    27. QNode* temp = Dest->next;
    28. free(Dest);
    29. Dest = temp;
    30. }
    31. pq->head = pq->tail = NULL;
    32. }
    33. void QueuePush(Queue* pq, QDataType x)
    34. {
    35. assert(pq);
    36. //创建一个节点
    37. QNode* newnode = (QNode*)malloc(sizeof(QNode));
    38. if (newnode == NULL)
    39. {
    40. printf("malloc fail\n");
    41. exit(-1);
    42. }
    43. newnode->data = x;
    44. newnode->next = NULL;
    45. //判断pq是不是一个空结点
    46. //如果是 则将newnode置为当前队列的第一个结点
    47. //如果不是 则将newnode链接到pq的下一个位置
    48. if (pq->tail == NULL)
    49. { //两个节点都指向newnode 表示此时队列中就一个元素
    50. pq->head = pq->tail = newnode;
    51. }
    52. else
    53. {
    54. //1.将newnode链接到tail的后面
    55. pq->tail->next = newnode;
    56. //2.将newnode置换为新的tail
    57. pq->tail = newnode;
    58. }
    59. }
    60. bool QueueEmpty(Queue* pq)
    61. {
    62. assert(pq);
    63. return pq->head == NULL;
    64. }
    65. void QueuePop(Queue* pq)
    66. {
    67. assert(pq);
    68. assert(!QueueEmpty(pq));
    69. //额外判断一下,解决如果仅剩一个结点了,pop的话导致tail为野指针
    70. if (pq->head->next == NULL)
    71. {
    72. free(pq->head);
    73. pq->head = pq->tail = NULL;
    74. }
    75. else
    76. {
    77. QNode* next = pq->head->next;
    78. free(pq->head);
    79. pq->head = next;
    80. }
    81. }
    82. QDataType QueueFront(Queue* pq)
    83. {
    84. assert(pq);
    85. assert(!QueueEmpty(pq));
    86. return pq->head->data;
    87. }
    88. QDataType QueueBck(Queue* pq)
    89. {
    90. assert(pq);
    91. assert(!QueueEmpty(pq));
    92. return pq->tail ->data;
    93. }
    94. int QueueSize(Queue *pq)
    95. {
    96. assert(pq);
    97. int count = 0;
    98. QNode* cur = pq->head;
    99. while (cur)
    100. {
    101. cur = cur->next;
    102. count++;
    103. }
    104. return count;
    105. }
    106. typedef struct {
    107. Queue q1; //队列1
    108. Queue q2; //队列2
    109. } MyStack;
    110. MyStack* myStackCreate() {
    111. MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
    112. if (obj == NULL)
    113. {
    114. return 0;
    115. }
    116. //初始化这两个队列
    117. QueueInit(&obj->q1);
    118. QueueInit(&obj->q2);
    119. return obj;
    120. }
    121. bool myStackEmpty(MyStack* obj) {
    122. return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
    123. }
    124. void myStackPush(MyStack* obj, int x) {
    125. //如果q1为空,则往q2里放数据
    126. if (QueueEmpty(&obj->q1))
    127. {
    128. QueuePush(&obj->q2, x);
    129. }
    130. else
    131. {
    132. QueuePush(&obj->q1, x);
    133. }
    134. }
    135. int myStackPop(MyStack* obj) {
    136. //如果q1为空,就要从q2往q1里导数据
    137. if (QueueEmpty(&obj->q1))
    138. {
    139. while (!((&obj->q2)->head->next == NULL))
    140. {
    141. QueuePush(&obj->q1, QueueFront(&obj->q2));
    142. QueuePop(&obj->q2);
    143. }
    144. int ret = QueueFront(&obj->q2);
    145. QueuePop(&obj->q2);
    146. return ret;
    147. }
    148. else
    149. {
    150. while (!((&obj->q1)->head->next == NULL))
    151. {
    152. QueuePush(&obj->q2, QueueFront(&obj->q1));
    153. QueuePop(&obj->q1);
    154. }
    155. int ret = QueueFront(&obj->q1);
    156. QueuePop(&obj->q1);
    157. return ret;
    158. }
    159. }
    160. int myStackTop(MyStack* obj) {
    161. //如果q1为空,则是存放除栈顶数据的位置
    162. if (QueueEmpty(&obj->q1))
    163. {
    164. while (!((&obj->q2)->head->next == NULL))
    165. {
    166. QueuePush(&obj->q1, QueueFront(&obj->q2));
    167. QueuePop(&obj->q2);
    168. }
    169. int ret = QueueFront(&obj->q2);
    170. QueuePush(&obj->q1,ret);
    171. QueuePop(&obj->q2);
    172. return ret;
    173. }
    174. else
    175. {
    176. while (!((&obj->q1)->head->next == NULL))
    177. {
    178. QueuePush(&obj->q2, QueueFront(&obj->q1));
    179. QueuePop(&obj->q1);
    180. }
    181. int ret = QueueFront(&obj->q1);
    182. QueuePush(&obj->q2,ret);
    183. QueuePop(&obj->q1);
    184. return ret;
    185. }
    186. }
    187. void myStackFree(MyStack* obj) {
    188. QueueDestroy(&obj->q1);
    189. QueueDestroy(&obj->q2);
    190. free(obj);
    191. }

  • 相关阅读:
    【译】Visual Studio 2013 退役 :旧版本 Visual Studio 的支持提醒
    2022中国人工智能芯片行业研究报告【免费下载】
    前端开发:JS中的Window对象详解
    Alibaba(获得店铺的所有商品) API 接口
    32.2.3 配置Atlas读写分离
    SpringSecurity---Remember Me
    QT+OSG/osgEarth编译之四十:osg+Qt编译(一套代码、一套框架,跨平台编译,版本:OSG-3.6.5核心库osg)
    【SRE】MySQL8的安装方式
    html表格账号密码备忘录:表格内容将通过JavaScript动态生成。点击查看密码10秒关闭
    ISP-Gamma
  • 原文地址:https://blog.csdn.net/Brant_zero/article/details/125495631