思路:如下图,我们可以定义两个栈,其中一个input用于实现队列的入队列的操作(就是input栈的入栈),另外一个output用于实现出队列和取队首元素的操作(就是output栈的出栈和取栈顶元素)。

当我们要出队列或者去队首元素时时,因为出队列和取队首元素要从output栈出,所以要先将input中的元素移到output中(而且谁最后入栈,就先把谁移到output中,这样一来,后入栈(后入队列)的元素,到了output栈中就是在栈底(相当于队尾)了

同理,我们需要入队列时,因为入队列操作只能从input栈顶要进行操作,所以需要将output中的元素全部都移动到input栈中。

注意:对于元素的移动,其实由于栈后进先出的特点,我们要将一个栈中的元素移到另外一个栈中,移动完成的结果总是逆序的(入一个栈中的元素为:a b c d 移动到另外一个栈后必然是:d c b a),正式由于这样的特性我们就可以通过两个栈来实现一个队列的情况。
QueueBy2Stack.h文件

#pragma once typedef char DataType;typedef struct Stack
{DataType *data;//有效元素个数int size;//表示data段内存中能容纳的元素个数int capacity;
}Stack;typedef struct Queue
{Stack input;Stack output;//队列的有效元素个数int size;
}Queue;//初始化函数
void QueueInit(Queue *queue);
//销毁函数
void QueueDestroy(Queue *queue);
//入栈函数
void QueuePush(Queue *queue,DataType value);
//出栈函数
void QueuePop(Queue *queue);
//取栈顶元素函数
int QueueFront(Queue *queue,DataType *front);

QueueBy2Stack.c文件

#include<stdio.h>
#include<stdlib.h>
#include"QueueBy2Stack.h"#define Test_Header printf("\n==========%s==========\n",__FUNCTION__);//栈初始化
void StackInit(Stack *stack)
{if(stack == NULL){//非法输入return;}stack->size = 0;stack->capacity = 1000;stack->data = (DataType*)malloc(stack->capacity * sizeof(DataType));
}
//栈销毁函数
void StackDestroy(Stack *stack)
{if(stack == NULL){//非法输入return;}free(stack->data);stack->data = NULL;stack->size = 0;stack->capacity = 0;
}
//入栈操作
void StackPush(Stack *stack,DataType value)
{if(stack == NULL){//非法输入return;}if(stack->size >= stack->capacity){//栈满了return;}//栈没满stack->data[stack->size++] = value;
}
//出栈操作
void StackPop(Stack *stack)
{if(stack == NULL){//非法输入return;}if(stack->size == 0){//空栈return;}stack->size--;
}
//取栈顶元素函数
int StackGetTop(Stack *stack,DataType *value)
{if(stack == NULL){//非法输入return 0;}if(stack->size == 0){//空栈return 0;}*value = stack->data[stack->size-1];return 1;
}//队列初始化函数
void QueueInit(Queue *queue)
{if(queue == NULL){//非法输入return;}StackInit(&queue->input);StackInit(&queue->output);queue->size = 0;
}//队列销毁函数
void QueueDestroy(Queue *queue)
{if(queue == NULL){//非法输入return;}StackDestroy(&queue->input);StackDestroy(&queue->output);queue->size = 0;
}//入队列函数
void QueuePush(Queue *queue,DataType value)
{if(queue == NULL){//非法输入return;}//将output(用于出队列的栈)中的元素倒腾到input(用于入队列的栈)中while(1){DataType front;int ret = StackGetTop(&queue->output,&front);//如果取栈顶元素返回了0,则说明output(用于出队列的栈)中已经没有元素了if(ret == 0){break;}//将output中的元素出栈StackPop(&queue->output);//将output的栈首元素插入到input中StackPush(&queue->input,front);}//倒腾完成以后再将要插入的新元素插入到input栈中StackPush(&queue->input,value);//将队列元素个数+1queue->size++;
}//出队列函数
void QueuePop(Queue *queue)
{if(queue == NULL){//非法输入return;}//将input(用于入队列的栈)中的元素倒腾到output(用于出队列的栈)中while(1){DataType front;int ret = StackGetTop(&queue->input,&front);//如果取栈顶元素返回了0,则说明该栈中已经没有元素了if (ret == 0){break;}//将input中的元素出栈StackPop(&queue->input);//将input(用于入队列的栈)中的栈顶元素插入到output(用于出队列的栈)中 StackPush(&queue->output,front);}//倒腾完成以后将output(用于出队列的栈)中的栈顶元素出栈(即出队列操作)StackPop(&queue->output);//队列元素个数-1queue->size--;
}//取队首元素函数
int QueueFront(Queue *queue,DataType *front)
{if(queue == NULL){//非法输入return 0;}//将input(用于入队列的栈)中的元素倒腾到output(用于出队列的栈)中while(1){DataType front;int ret = StackGetTop(&queue->input,&front);//如果取栈顶元素返回了0,则说明该栈中已经没有元素了if(ret == 0){break;     }//将input中的元素出栈StackPop(&queue->input);//将input(用于入队列的栈)中的栈顶元素插入到output(用于出队列的栈)中 StackPush(&queue->output,front);}//取用于出队列的栈的栈首元素(即取出队首元素)int ret = StackGetTop(&queue->output,front);return ret;
}//打印队列元素以便观察函数测试结果(其中思路不再详述,与之前函数思路一致)
void PrintQueueElem(Queue *queue,const char *msg)
{printf("[%s]\n",msg);if(queue == NULL){//非法输入return;}if(queue->size == 0){//空队列return;}while(1){DataType front;int ret = StackGetTop(&queue->output,&front);if(ret == 0){break;}StackPop(&queue->output);StackPush(&queue->input,front);}int i = 0;for(;i < queue->input.size;i++){printf("%c ",stack->data[i]);}printf("\n\n");
}
//以下为测试函数
void TestQueueBy2Stack()
{Test_Header;Queue queue;//队列初始化QueueInit(&queue);//入队列函数测试QueuePush(&queue,'a');QueuePush(&queue,'b');QueuePush(&queue,'c');QueuePush(&queue,'d');PrintQueueElem(&queue,"入队列4个元素:a b c d");//以下为取队首元素函数测试1DataType front;int ret = QueueFront(&queue,&front);printf("expected ret = 1,actual ret = %d\n",ret);printf("expected front = a,actual front = %c\n",front);//出队列函数测试QueuePop(&queue);QueuePop(&queue);PrintQueueElem(&queue,"出队列两个元素");//取队首元素测试2ret = QueueFront(&queue,&front);printf("expected ret = 1,actual ret = %d\n",ret);printf("expected front = c,actual front = %c\n",front);QueuePop(&queue);QueuePop(&queue);PrintQueueElem(&queue,"将最后两个元素也出队列");//取队首元素函数测试3(空队列)ret = QueueFront(&queue,&front);printf("expected ret = 0,actual ret = %d\n",ret);//销毁队列QueueDestroy(&queue);
}
//主函数调用测试函数
int main()
{TestQueueBy2Stack();return 0;
}

测试结果如下图:

通过两个栈实现一个队列(C语言)相关推荐

  1. 多态指针访问虚函数不能被继承的类快速排序N皇后问题插入排序堆排序merge归并排序栈上生成对象两个栈实现一个队列...

    多态 /*1. 要想实现覆盖(重写)父类必须声明为virtual,子类可以不声明为virtual.-->FunB()2. 派生类重写基类的虚函数实现多态,要求函数名.参数列表.返回值完全相同.( ...

  2. 【剑指offer】用两个栈实现一个队列

    题目:两个栈实现一个队列. 栈的特点:先进后出,队列的特点是先进先出 思路:stack1放入数据:pop时,先判断stack2是否为空,如果不为空,直接pop,如果空,则push(stack1.pop ...

  3. 剑指offer五:两个栈实现一个队列

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. package com.jianzhioffer;import java.util.Stack;publ ...

  4. 两个栈实现一个队列,两个队列实现一个栈

    题目:用两个栈实现一个队列,用两个队列实现一个栈. 首先要了解栈和队列这两种数据结构各自的特点,栈是一种后入先出(Last In First Out,LIFO)的数据结构,队列是一种先进先出(Firs ...

  5. python 用两个栈实现一个队列

    | 两个栈实现队列 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能.(若队列中没有元素 ...

  6. java实现-两个栈实现一个队列和两个队列实现一个栈

    1.两个栈实现一个队列 思路:压入元素直接入stack1,删除元素先判断stack2中是否为空,如果不为空直接弹出:为空则将stack1中的元素取出压入 stack2中再弹出. 代码: import ...

  7. python ——两个队列实现一个栈两个栈实现一个队列

    1.两个队列实现一个栈 进栈:元素入队列A 出栈:判断如果队列A只有一个元素,则直接出队.否则,把队A中的元素出队并入队B,直到队A中只有一个元素,再直接出队.为了下一次继续操作,互换队A和队B. p ...

  8. 两个栈实现一个队列与两个队列实现一个栈

    http://blog.csdn.net/z84616995z/article/details/19204529 两个栈实现一个队列: 原理方法:用一个栈为主栈,一个栈为辅助栈存放临时元素. 入队:将 ...

  9. 【数据结构】(面试题)使用两个栈实现一个队列(详细介绍)

    http://blog.csdn.net/hanjing_1995/article/details/51539578 使用两个栈实现一个队列 思路一: 我们设定s1是入栈的,s2是出栈的. 入队列,直 ...

  10. 两个栈实现一个队列/两个队列实现一个栈

    http://blog.csdn.net/sinat_30472685/article/details/70157227 1两个栈实现一个队列 1.原理分析: 队列的主要操作有两个:入队操作和出队操作 ...

最新文章

  1. axtoolbarcontrol加载图层后还是灰的_OpenLayers教程九:多源数据加载之瓦片地图原理一...
  2. 国家脑库:神经科学研究的基础设施
  3. kafka Detailed Replication Design V3
  4. php如何定义的数位置,php如何实现不借助IDE快速定位行数或者方法定义的文件和位置...
  5. 单片机蓝牙烧录_蓝牙模块与单片机如何连接?
  6. C代码中如何调用C++ C++中如何调用C
  7. 寄存器分配图着色_【02】从零开始的卡通渲染-着色篇1
  8. [Perl系列—] 2. Perl 中的引用使用方法
  9. Apache部署多个WordPress网站
  10. 线性代数学习之行列式
  11. 代码大全 服装尺寸图html,最全服装尺码对照表
  12. 【Pygame小游戏】确实会玩—教你如何在”吃豆豆“上完美躺赢……(收藏起来偷偷学)
  13. 如何选一款软件助力企业腾飞
  14. iOS从相册选择视频和保存视频到相册
  15. 英语广播原声听力100篇MP3及听力原文
  16. 抖音最新风控体系研究
  17. 需求跟踪系列 III - 建立需求关联最佳的方式和时间点
  18. 负载均衡进阶:SLB常见问题解决方法
  19. Linux_第1章 Linux入门
  20. 2017年7月14日 星期五 --出埃及记 Exodus 28:5

热门文章

  1. 创建CrossApp工程
  2. CrossAPP第一课
  3. 路由器linux校园网,还在为无法突破校园网的限制而烦恼?动动手,借助路由器完成锐捷认证...
  4. 服务器ipsan虚拟化,挂载IPSAN存储+链接克隆模板(修正版)
  5. 北京林业大学计算机复试难度,2015年北京林业大学考研复试经验
  6. BLP读书笔记(一)——通过shell访问终端模式
  7. cesium雷达图_Cesium专栏-气象雷达动图(附源码下载)
  8. 无人车系统(三):用python写一个简单的无人车仿真环境
  9. (转)量化投资发展史:野蛮、乱象、科学
  10. SRIO学习笔记之SRIO简介与Xilinx SRIO ip核例程详解