当前位置:   article > 正文

【C语言】栈和队列的相互实现_用栈实现队列c语言

用栈实现队列c语言

目录

用队列实现栈

代码实现

完整代码

用栈实现队列

 代码实现

完整代码


用队列实现栈

力扣链接用队列实现栈

这个题目,使用队列模拟实现栈,我们是使用C语言来实现,由于C语言没有相应的库所以我们要先手写一个队列出来,在此之前我们还要对队列和栈的性质有所了解 ,可以参考我之前写的文章——队列的模拟实现)和(栈的模拟实现

方法两个队列

为了满足栈的特性,即最后入栈的元素最先出栈,在使用队列实现栈时,应满足队列前端的元素是最后入栈的元素。所以我们可以使用两个队列实现栈的操作,其中一个队列用来存储栈内的元素,另一个队列用来倒数据。

入栈操作把数据入队到其中一个队列中,另一个队列保持为空队列。

出栈操作:将存储了栈内元素的队列倒到另一个空的队列中,当倒了只剩下一个数据时停止,将这个数据出队就达到了出栈的效果。

  

代码实现

 创建两个队列

  1. typedef struct
  2. {
  3. Queue q1;
  4. Queue q2;
  5. } MyStack;

初始化 

  1. MyStack* myStackCreate() {
  2. MyStack* obj=(MyStack*)malloc(sizeof(MyStack));
  3. QueueInit(&obj->q1);
  4. QueueInit(&obj->q2);
  5. return obj;
  6. }

 首先看一下这样写行不行?

这样写当然是不行的,因为它是带返回值的,所以我们要返回我们创建的地址,但是st是局部变量,出了这个函数就销毁了,那你接受到的只能是野指针。

所以这里只能用静态的或者malloc动态的,出了这个函数也不会被销毁,但是malloc更好,那我们就用malloc的,然后初始化这两个队列 就行了。

入栈

  1. void myStackPush(MyStack* obj, int x) {
  2. if(!QueueEmpty(&obj->q1))
  3. {
  4. QueuePush(&obj->q1,x);
  5. }
  6. else
  7. {
  8. QueuePush(&obj->q2,x);
  9. }
  10. }

 入栈就很简单了,我们就向队列不为空的入数据,如果两个队列都为空,向哪个队列入数据都行。

出栈

  1. int myStackPop(MyStack* obj) {
  2. Queue* emptyQ=&obj->q1;
  3. Queue* nonEmptyQ=&obj->q2;
  4. if(!QueueEmpty(&obj->q1))
  5. {
  6. emptyQ=&obj->q2;
  7. nonEmptyQ=&obj->q1;
  8. }
  9. while(QueueSize(nonEmptyQ)>1)
  10. {
  11. QueuePush(emptyQ,QueueFront(nonEmptyQ));
  12. QueuePop(nonEmptyQ);
  13. }
  14. int top=QueueFront(nonEmptyQ);
  15. QueuePop(nonEmptyQ);
  16. return top;
  17. }

 这里就需要倒数据了,但是我们不知道哪个为空,哪个不为空,我们可以用假设法。先假设一个为空 ,一个不为空,再来一个if语句判断一下,确定哪个为空,哪个不为空。然后将非空队列的数据倒入空的队列中去,当非空对列倒的只剩下一个数据时就停止,最后pop掉这个数据。

 获取栈顶元素

  1. int myStackTop(MyStack* obj) {
  2. if(!QueueEmpty(&obj->q1))
  3. {
  4. return QueueBack(&obj->q1);
  5. }
  6. else
  7. {
  8. return QueueBack(&obj->q2);
  9. }
  10. }

因为我们是用队列来模拟实现栈的,那我们既可以取到对头的数据,也可以取到队尾的数据,这里我们只用取队尾的数据就行了,只需判断哪个不为空,取那个就行。 

判空 

  1. bool myStackEmpty(MyStack* obj) {
  2. return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
  3. }

注意这里是&&而不是|| ,我们是用两个队列来模拟栈,只有当两个队列都为空时,栈才是空。

销毁栈

  1. void myStackFree(MyStack* obj) {
  2. QueueDestroy(&obj->q1);
  3. QueueDestroy(&obj->q2);
  4. free(obj);
  5. }

 我们不仅要销毁这两个队列,还要free掉队列中指针指向的链表。

完整代码

  1. typedef int QDataType;
  2. typedef struct QueueNode
  3. {
  4. struct QueueNode* next;
  5. QDataType data;
  6. }QNode;
  7. typedef struct Queue
  8. {
  9. int size;
  10. QNode* head;
  11. QNode* tail;
  12. }Queue;
  13. //初始化队列
  14. void QueueInit(Queue* pq);
  15. //销毁队列
  16. void QueueDestroy(Queue* pq);
  17. //对尾入队列
  18. void QueuePush(Queue* pq, QDataType x);
  19. //对头出队列
  20. void QueuePop(Queue* pq);
  21. //获取对列头部元素
  22. QDataType QueueFront(Queue* pq);
  23. //获取队列队尾元素
  24. QDataType QueueBack(Queue* pq);
  25. //判空
  26. bool QueueEmpty(Queue* pq);
  27. //获取队列中有效元素的个数
  28. int QueueSize(Queue* pq);
  29. void QueueInit(Queue* pq)
  30. {
  31. assert(pq);
  32. pq->size = 0;
  33. pq->head = pq->tail = NULL;
  34. }
  35. void QueueDestroy(Queue* pq)
  36. {
  37. assert(pq);
  38. QNode* cur = pq->head;
  39. while (cur)
  40. {
  41. QNode* next = cur->next;
  42. free(cur);
  43. cur = next;
  44. }
  45. pq->head = pq->tail = NULL;
  46. }
  47. void QueuePush(Queue* pq, QDataType x)
  48. {
  49. assert(pq);
  50. QNode* newnode = (QNode*)malloc(sizeof(QNode));
  51. if (newnode == NULL)
  52. {
  53. printf("malloc fail\n");
  54. exit(-1);
  55. }
  56. newnode->data = x;
  57. newnode->next = NULL;
  58. if (pq->tail == NULL)
  59. {
  60. pq->head = pq->tail = newnode;
  61. }
  62. else
  63. {
  64. pq->tail->next = newnode;
  65. pq->tail = newnode;
  66. }
  67. pq->size++;
  68. }
  69. void QueuePop(Queue* pq)
  70. {
  71. assert(pq);
  72. assert(!QueueEmpty(pq));
  73. //1.一个节点
  74. if (pq->head->next == NULL)
  75. {
  76. free(pq->head);
  77. pq->head = pq->tail = NULL;//避免野指针问题
  78. }
  79. //2.多个节点
  80. else
  81. {
  82. QNode* next = pq->head->next;
  83. free(pq->head);
  84. pq->head = next;
  85. }
  86. pq->size--;
  87. }
  88. QDataType QueueFront(Queue* pq)
  89. {
  90. assert(pq);
  91. assert(!QueueEmpty(pq));
  92. return pq->head->data;
  93. }
  94. QDataType QueueBack(Queue* pq)
  95. {
  96. assert(pq);
  97. assert(!QueueEmpty(pq));
  98. return pq->tail->data;
  99. }
  100. bool QueueEmpty(Queue* pq)
  101. {
  102. assert(pq);
  103. return pq->head == NULL;
  104. }
  105. int QueueSize(Queue* pq)
  106. {
  107. assert(pq);
  108. /*int size = 0;
  109. QNode* cur = pq->head;
  110. while (cur)
  111. {
  112. size++;
  113. cur = cur->next;
  114. }*/
  115. return pq->size;
  116. }
  117. typedef struct
  118. {
  119. Queue q1;
  120. Queue q2;
  121. } MyStack;
  122. MyStack* myStackCreate() {
  123. MyStack* obj=(MyStack*)malloc(sizeof(MyStack));
  124. QueueInit(&obj->q1);
  125. QueueInit(&obj->q2);
  126. return obj;
  127. }
  128. void myStackPush(MyStack* obj, int x) {
  129. if(!QueueEmpty(&obj->q1))
  130. {
  131. QueuePush(&obj->q1,x);
  132. }
  133. else
  134. {
  135. QueuePush(&obj->q2,x);
  136. }
  137. }
  138. int myStackPop(MyStack* obj) {
  139. Queue* emptyQ=&obj->q1;
  140. Queue* nonEmptyQ=&obj->q2;
  141. if(!QueueEmpty(&obj->q1))
  142. {
  143. emptyQ=&obj->q2;
  144. nonEmptyQ=&obj->q1;
  145. }
  146. while(QueueSize(nonEmptyQ)>1)
  147. {
  148. QueuePush(emptyQ,QueueFront(nonEmptyQ));
  149. QueuePop(nonEmptyQ);
  150. }
  151. int top=QueueFront(nonEmptyQ);
  152. QueuePop(nonEmptyQ);
  153. return top;
  154. }
  155. int myStackTop(MyStack* obj) {
  156. if(!QueueEmpty(&obj->q1))
  157. {
  158. return QueueBack(&obj->q1);
  159. }
  160. else
  161. {
  162. return QueueBack(&obj->q2);
  163. }
  164. }
  165. bool myStackEmpty(MyStack* obj) {
  166. return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
  167. }
  168. void myStackFree(MyStack* obj) {
  169. QueueDestroy(&obj->q1);
  170. QueueDestroy(&obj->q2);
  171. free(obj);
  172. }

用栈实现队列

力扣链接用栈实现队列

这个题目是用栈实现队列,我们依然使用C语言来写,C语言没有相应的库,所以我们还是要先手写一个栈才能实现题目中要求的函数接口。

方法两个栈

一个队列是先进先出,一个栈是先进后出,新进的数据肯定是在栈底。我们可以这样做,指定一个栈专门进数据,指定另外一个栈专门出数据。

入队操作向push栈中入数据。

 出对操作将push栈中的数据全部倒入pop栈中,pop栈中数据的顺序刚好与push栈中的数据顺序相反,正好满足队列的性质,最后在push栈的栈顶出数据就行了。

 

 代码实现

创建两个栈

  1. typedef struct {
  2. ST pushst;
  3. ST popst;
  4. } MyQueue;

 指定一个栈专门进数据,指定另外一个栈专门出数据。

初始化

  1. MyQueue* myQueueCreate() {
  2. MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));
  3. StackInit(&obj->pushst);
  4. StackInit(&obj->popst);
  5. return obj;
  6. }

销毁队列

  1. void myQueueFree(MyQueue* obj) {
  2. StackDestroy(&obj->popst);
  3. StackDestroy(&obj->pushst);
  4. free(obj);
  5. }

初始化和销毁队列的方法和上面题目的方法一致,就不多讲了。

入队

  1. void myQueuePush(MyQueue* obj, int x) {
  2. StackPush(&obj->pushst,x);
  3. }

 入对只需要push进栈就行啦。

出队

  1. int myQueuePop(MyQueue* obj) {
  2. if(StackEmpty(&obj->popst))
  3. {
  4. //如果pop栈为空,则把push栈的数据倒过来
  5. while(!StackEmpty(&obj->pushst))
  6. {
  7. StackPush(&obj->popst,StackTop(&obj->pushst));
  8. StackPop(&obj->pushst);
  9. }
  10. }
  11. int front=StackTop(&obj->popst);
  12. StackPop(&obj->popst);
  13. return front;
  14. }

 首先要判断一下popst栈为不为空,如果为空,则把push栈的数据倒过来,不为空就直接在pop栈出数据。

取对头元素

  1. int myQueuePeek(MyQueue* obj) {
  2. if(StackEmpty(&obj->popst))
  3. {
  4. //如果pop栈为空,则把push栈的数据倒过来
  5. while(!StackEmpty(&obj->pushst))
  6. {
  7. StackPush(&obj->popst,StackTop(&obj->pushst));
  8. StackPop(&obj->pushst);
  9. }
  10. }
  11. return StackTop(&obj->popst);
  12. }

 这个就简单了,只需要取pop栈的栈顶的数据返回就可以了。

判空

  1. bool myQueueEmpty(MyQueue* obj) {
  2. return StackEmpty(&obj->popst)&&StackEmpty(&obj->pushst);
  3. }

两个栈等于一个队列,所以两个栈都需要判空。 和上面的题目一样。

完整代码

  1. typedef int STDataType;
  2. typedef struct Stack
  3. {
  4. STDataType* a;
  5. int top;
  6. int capacity;
  7. }ST;
  8. //初始化栈
  9. void StackInit(ST* ps);
  10. //销毁栈
  11. void StackDestroy(ST* ps);
  12. //进栈
  13. void StackPush(ST* ps, STDataType x);
  14. //出栈
  15. void StackPop(ST* ps);
  16. //获取栈顶元素
  17. STDataType StackTop(ST* ps);
  18. //判空
  19. bool StackEmpty(ST* ps);
  20. //栈的元素个数
  21. int StackSize(ST* ps);
  22. void StackInit(ST* ps)
  23. {
  24. assert(ps);
  25. ps->a = NULL;
  26. ps->top = 0;
  27. ps->capacity = 0;
  28. }
  29. void StackDestroy(ST* ps)
  30. {
  31. assert(ps);
  32. free(ps->a);
  33. ps->a = NULL;
  34. ps->top = ps->capacity = 0;
  35. }
  36. void StackPush(ST* ps, STDataType x)
  37. {
  38. assert(ps);
  39. if (ps->top == ps->capacity)
  40. {
  41. int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
  42. STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType)* newcapacity);
  43. if (tmp == NULL)
  44. {
  45. printf("realloc fail\n");
  46. exit(-1);
  47. }
  48. ps->a = tmp;
  49. ps->capacity = newcapacity;
  50. }
  51. ps->a[ps->top] = x;
  52. ps->top++;
  53. }
  54. void StackPop(ST* ps)
  55. {
  56. assert(ps);
  57. assert(!StackEmpty(ps));
  58. ps->top--;
  59. }
  60. STDataType StackTop(ST* ps)
  61. {
  62. assert(ps);
  63. assert(!StackEmpty(ps));
  64. return ps->a[ps->top - 1];
  65. }
  66. bool StackEmpty(ST* ps)
  67. {
  68. assert(ps);
  69. return ps->top == 0;
  70. }
  71. int StackSize(ST* ps)
  72. {
  73. assert(ps);
  74. return ps->top;
  75. }
  76. typedef struct {
  77. ST pushst;
  78. ST popst;
  79. } MyQueue;
  80. MyQueue* myQueueCreate() {
  81. MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));
  82. StackInit(&obj->pushst);
  83. StackInit(&obj->popst);
  84. return obj;
  85. }
  86. void myQueuePush(MyQueue* obj, int x) {
  87. StackPush(&obj->pushst,x);
  88. }
  89. int myQueuePop(MyQueue* obj) {
  90. if(StackEmpty(&obj->popst))
  91. {
  92. //如果pop栈为空,则把push栈的数据倒过来
  93. while(!StackEmpty(&obj->pushst))
  94. {
  95. StackPush(&obj->popst,StackTop(&obj->pushst));
  96. StackPop(&obj->pushst);
  97. }
  98. }
  99. int front=StackTop(&obj->popst);
  100. StackPop(&obj->popst);
  101. return front;
  102. }
  103. int myQueuePeek(MyQueue* obj) {
  104. if(StackEmpty(&obj->popst))
  105. {
  106. //如果pop栈为空,则把push栈的数据倒过来
  107. while(!StackEmpty(&obj->pushst))
  108. {
  109. StackPush(&obj->popst,StackTop(&obj->pushst));
  110. StackPop(&obj->pushst);
  111. }
  112. }
  113. return StackTop(&obj->popst);
  114. }
  115. bool myQueueEmpty(MyQueue* obj) {
  116. return StackEmpty(&obj->popst)&&StackEmpty(&obj->pushst);
  117. }
  118. void myQueueFree(MyQueue* obj) {
  119. StackDestroy(&obj->popst);
  120. StackDestroy(&obj->pushst);
  121. free(obj);
  122. }

总结:这两个题目是很相似的,你会写其中一个,那么另一个也不是什么难事。

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

闽ICP备14008679号