队列的特别实现

上两节讲的队列实现方式确实提高了顺序队列和链式队列的效率,可是实现过程还是比较复杂。这样就有可能导致错误,其实有即能复用之前的代码,又比较高效的队列实现算法的。

那就是用栈来实现,可能有人要说了,栈不是后入先出的吗?怎么可能实现栈呢?大家考虑一下,如果使用两个栈呢?如下图:

大家是不是明白一点了呢?

下面做个小结:

1.组合使用两个栈的“后进先出”可以实现队列的“先进先出”;
2.两个栈实现队列的方法复用栈数据结构,实现过程简单且高效;
3.两个栈实现的队列其操作的时间复杂度能够达到O(1)。

栈实现队列方案
实现思路:
1.准备两个栈用于实现队列:inStack和outStack;

2.当有新元素入队时:将其压入inStack中;

3.当需要出队时:

3.1.当outStack为空时:

3.1.1.将inStack中的元素逐一弹出并压入outStack中;

3.1.2.将outStack的栈顶元素弹出;

3.2.当outStack不为空时:

3.2.1.直接将outStack的栈顶元素弹出。

下面看一下具体的实现代码,栈部分参考:栈的定义与实现

创建队列

// 定义队列结构体
typedef struct _tag_SQueue
{LinkStack* inStack;LinkStack* outStack;
} TSQueue;
// 创建队列
SQueue* SQueue_Create() // O(1)
{// 定义队列结构体变量,并申请内存TSQueue* ret = (TSQueue*)malloc(sizeof(TSQueue));// 内存申请成功if( ret != NULL ){// 创建入栈或出栈ret->inStack = LinkStack_Create();ret->outStack = LinkStack_Create();// 创建栈失败,销毁栈,释放内存if( (ret->inStack == NULL) || (ret->outStack == NULL) ){LinkStack_Destroy(ret->inStack);LinkStack_Destroy(ret->outStack);free(ret);ret = NULL;}}// 返回队列地址return ret;
}

销毁队列、清空队列

// 销毁队列
void SQueue_Destroy(SQueue* queue) // O(n)
{   // 清空队列,释放内存SQueue_Clear(queue);free(queue);
}
// 清空队列
void SQueue_Clear(SQueue* queue) // O(n)
{// 定义队列结构体变量,并强制转换入口参数TSQueue* sQueue = (TSQueue*)queue;// 参数合法,清空两个入栈和出栈if( sQueue != NULL ){LinkStack_Clear(sQueue->inStack);LinkStack_Clear(sQueue->outStack);}
}

入队代码

// 入队
int SQueue_Append(SQueue* queue, void* item) // O(1)
{// 定义队列结构体变量,并强制转换入口参数TSQueue* sQueue = (TSQueue*)queue;// 参数合法,将掺入元素压入栈内if( sQueue != NULL ){LinkStack_Push(sQueue->inStack, item);}
}

出队

// 出队
void* SQueue_Retrieve(SQueue* queue) // O(1)
{// 定义队列结构体变量,并强制转换入口参数TSQueue* sQueue = (TSQueue*)queue;void* ret = NULL;// 参数合法,将掺入元素压入栈内if( sQueue != NULL ){// 出栈元素为空if( LinkStack_Size(sQueue->outStack) == 0 ){// 将入栈所有元素压入出栈中while( LinkStack_Size(sQueue->inStack) > 0 ){LinkStack_Push(sQueue->outStack, LinkStack_Pop(sQueue->inStack));}}// 返回弹出的出栈栈顶元素ret = LinkStack_Pop(sQueue->outStack);}return ret;
}

获取队首元素

// 获取队头元素
void* SQueue_Header(SQueue* queue) // O(1)
{// 定义队列结构体变量,并强制转换入口参数TSQueue* sQueue = (TSQueue*)queue;void* ret = NULL;// 参数合法if( sQueue != NULL ){// 出栈元素为空if( LinkStack_Size(sQueue->outStack) == 0 ){// 将入栈所有元素压入出栈中while( LinkStack_Size(sQueue->inStack) > 0 ){LinkStack_Push(sQueue->outStack, LinkStack_Pop(sQueue->inStack));}}// 返回出栈栈顶元素ret = LinkStack_Top(sQueue->outStack);}return ret;
}

获取队长度

// 获取队长度
int SQueue_Length(SQueue* queue) // O(1)
{// 定义队列结构体变量,并强制转换入口参数TSQueue* sQueue = (TSQueue*)queue;int ret = -1;// 参数合法,返回入栈和出栈的长度和if( sQueue != NULL ){ret = LinkStack_Size(sQueue->inStack) + LinkStack_Size(sQueue->outStack);}return ret;
}

头文件

#ifndef _SQUEUE_H_
#define _SQUEUE_H_typedef void SQueue;
// 创建队列
SQueue* SQueue_Create();
// 销毁队列
void SQueue_Destroy(SQueue* queue);
// 清空队列
void SQueue_Clear(SQueue* queue);
// 入队
int SQueue_Append(SQueue* queue, void* item);
// 出队
void* SQueue_Retrieve(SQueue* queue);
// 获取队头元素
void* SQueue_Header(SQueue* queue);
// 获取队长度
int SQueue_Length(SQueue* queue);#endif

测试代码

#include <stdio.h>
#include <stdlib.h>
#include "SQueue.h"/* run this program using the console pauser or add your own getch, system("pause") or input loop */int main(int argc, char *argv[])
{SQueue* queue = SQueue_Create();int a[10] = {0};int i = 0;for(i=0; i<10; i++){a[i] = i + 1;SQueue_Append(queue, a + i);}printf("Header: %d\n", *(int*)SQueue_Header(queue));printf("Length: %d\n", SQueue_Length(queue));for(i=0; i<5; i++){printf("Retrieve: %d\n", *(int*)SQueue_Retrieve(queue));}printf("Header: %d\n", *(int*)SQueue_Header(queue));printf("Length: %d\n", SQueue_Length(queue));for(i=0; i<10; i++){a[i] = i + 1;SQueue_Append(queue, a + i);}while( SQueue_Length(queue) > 0 ){printf("Retrieve: %d\n", *(int*)SQueue_Retrieve(queue));}SQueue_Destroy(queue);return 0;
}

至此,队列也就介绍完了。最后上传一下整体代码链接: 双栈实现队列C实现代码

数据结构之队列的特别实现相关推荐

  1. python环形队列_Python 实现数据结构-循环队列的操作方法

    今天我们来到了循环队列这一节,之前的文章中,我介绍过了用python自带的列表来实现队列,这是最简单的实现方法. 但是,我们都知道,在列表中删除第一个元素和删除最后一个元素花费的时间代价是不一样的,删 ...

  2. 数据结构之队列、双端队列

    数据结构之队列.双端队列 队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表. 队列是一种先进先出的(First in First Out)的线性表,简称FIFO.允许插入的 ...

  3. (四)数据结构之“队列”

    数据结构之"队列" 队列是什么? 队列的应用场景 场景一:食堂排队打饭 场景二:JS异步中的任务队列 场景三:计算最近请求次数 LeetCode:933.最近的请求次数 前端与队列 ...

  4. c++ 优先队列_C/C++数据结构:队列结构最全解析!带你零基础入门队列结构

    前言 上一章节针对于C语言栈结构做了解析,不清楚的可以回顾一下. 本章节主要针对于C语言的基础数据结构队列做以解析. 数据结构之队列 队列是一种特殊的 线性表 ,特殊之处在于它只允许在表的前端(fro ...

  5. java 头尾 队列_Java数据结构之队列(动力节点Java学院整理)

    队列的定义: 队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表. (1)允许删除的一端称为队头(Front). (2)允许插入的一端称为队尾(Rear). (3)当队列中 ...

  6. 数据结构之队列的应用(实现斐波那契数列)

    数据结构之队列的应用(实现斐波那契数列) 导入 基本的队列结构 的构造函数 const Queue = require('./Queue.js')/*** @description 获取第n项斐波那契 ...

  7. 银行业务队列简单模拟Java程序设计_PTA 数据结构 银行业务队列简单模拟

    仅供参考,请勿粘贴 设某银行有A.B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 -- 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客.给定到达银行的顾客序列,请按业务完 ...

  8. 大一新生必看,自学必看,里昂详解数据结构之队列

    数据结构之队列 有幸掌握浅薄知识,不吝分享,保持独立思考,自主学习,共同进步.另求关注,点赞,评论,感谢!(tips:主页有数据结构全部知识点,以及知识点讲解,建立完善的数据结构知识体) 核心算法思想 ...

  9. 数据结构——环形队列的原理(模拟环形队列)

    数据结构--环形队列的原理(模拟环形队列) 知识点简要介绍: 队列:一种特殊的线性表,包含队列头.队列尾,只允许在队列头进行删除操作,在队列为进行删除操作 分类:     顺序队列.循环队列(环形队列 ...

最新文章

  1. BZOJ 1047 理想的正方形(单调队列)
  2. 计算机与社会关系的案例,计算机网络与社会关系论文.pdf
  3. 切换日期_2.4.14-切换时区分析
  4. 在eclipse及myEclipse下安装插件之方法
  5. android开源系统brvah,Android Jetpack之通用Adapter(Databinding+BRVAH)
  6. chackbox的值 php获取_PHP操作Redis数据库常用方法
  7. ubuntu14.10 LTS安装完成后鼠标闪烁问题
  8. 小型超市管理系统(JAVA,JSP,SSH,MYSQL)
  9. 修改VNR源码接入新版有道中文翻译API
  10. echarts 柱形图数据位置显示
  11. Python修改图片分辨率(附代码) | Python工具
  12. c#物联网_毕业季我与你招聘信息中移物联网
  13. 计算机图形学实验二交互式绘制多边形
  14. 三星M8 智能显示器 评测
  15. VTK和numpy的整合
  16. 今年最受欢迎的14款黑客工具
  17. 戈壁日记——一个来了又来的地方
  18. 软件工程第三次作业——关于软件质量保障初探
  19. 默孚龙导电滑环在比亚迪垂直循环式充电站中的应用
  20. Matlab:Voronoi 图

热门文章

  1. 制作漫画风图片(无需下载APP无需PS无需电脑)
  2. 解决gmpy2安装报错:# include “mpfr.h“ compilation terminated.error: command ‘gcc‘ failed with exit status 1
  3. aes key长度_AES加密(1): 基本AES算法
  4. JDK1.8版本,java并发框架支持锁包括
  5. 【CF913G】Power Substring 数论+原根
  6. leetcode 61. Rotate List
  7. android.mk简单介绍
  8. HandleExternalEventActivity
  9. 1002-487-3279*北京大学acm-oj-java语言题解
  10. Telnet三步完成连接(简短版)