c语言队列原理的实现,c印记(十二):队列queue原理与实现

一、简而言之

在百度百科里面摘取了一段关于队列(queue)的介绍:

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。

二、一般而言

这里是对就一般而言, 队列的结构,操作方法等的表述。

2.1 结构

以下为队列的结构示意图

ed41ad8659e054b28edcd5febad64a9f.png

2.2 实现分类

一般来说,队列有两类实现方式:

数组实现:暂时将其称为有限队列,根据创建队列是传入的size,创建相应size的数组来作为队列的载体,一般都会以循环的方式利用数组,也可看作循环队列。

优点:预先分配好内存,在入队和出队过程中不会重新分配内存,有一定时间上的优势。

缺点:因必须预先分配好内存,所以存在内存空间浪费的问题(比如分配了10个元素,但很多时候却只有5个有效元素),元素数目固定,不够灵活。

049c2983c4b8bd43162d5eb3e55dc988.png

链表实现:可称其为链式队列,使用链表来实现队列,理论上这样的队列可以无限延伸,当然根据实际需要,可以人为的限制队列长度,让其表现的和数组实现方式差不多。

优点: 无需预先分配内存,所以不存在空间浪费的问题(虽然会多一个指针域,但也基本可以接受),队列长度可限制也可不限制,较为灵活。

缺点: 入队出队分别需要分配和释放元素节点,在时间上会略微慢于数组实现。

总的来说,在可以确定队列长度最大值的情况下,建议用循环队列,如果你无法预估队列的长度时,则用链队列。

2.3 基本操作

这里主要指的是队列的入队(enqueue)与出队(dequeue),对于链式队列来说,其入队和出队也就是链表的尾部插入与移除头部节点,这里就不多说,主要说一下以数组实现的循环链表的具体实现(其中head和tail都是表示数组的下标)。

入队: 如上面的循环队列示意图,入队操作,需要先判断tail节点的下一个位置是否是head,如果是就表示队列已满,无法入队,如果不是,那就可以入队,也即是将元素放入tail的下一个位置,最后将tail加一(也就是指向最终的尾元素),其伪代码如下:

/** 取余保证,当tail = size - 1 时,转回到0 */

int tail = (queue->tail + 1) % queue->size;

if (tail != queue->head)

{ /** 此处这样写,是因为正常情况下,非满的情况多于满了的情况,这样写可以稍微的加快点执行速度 */

queue->elems[queue->tail] = elem;

queue->tail = tail;

}

else /** 此时队列已满 */

{

printf("the queue is full!");

}

出队: 先判断 tail 和head是否相等,如果相等,就比较队列已空,无元素可出,不等则表示非空。此时需要取出head对于位置的元素,然后将head加1(当然,为了能够在head 增加到数组尾部时能够转回到首部,那么这里其实需要 将head加1与队列的size取余再赋值给head),其伪代码如下:

elem_type elem = elem_null; /** 初始化元素 */

if(queue->tail != queue->head) /** 判断队列不为空 */

{/**这样写的作用与上一段伪代码的作用是一样的 */

elem = queue->elems[queue->head];

/** 取余保证,当head= size - 1 时,转回到0 */

queue->head = (queue->head+1) % queue->size;

}

else /** 此时队列已空 */

{

printf("the queue is empty \n");

}

return elem;

三、和盘托出

这里就是我的具体实现。目前我实现的是无限队列(链式队列 ),链表就是前一章实现的list。

其头文件如下:

#ifndef __TINY_QUEUE_H__

#define __TINY_QUEUE_H__

#include "general_type.h"

#ifdef __cplusplus

extern "C" {

#endif

/***************************************************************************

*

* macro declaration

*

***************************************************************************/

/***************************************************************************

*

* data structure declaration

*

***************************************************************************/

/** the callback function for free item */

typedef void (*tfQueueItemFreeFunc_t)(void* item);

/***************************************************************************

*

* API declaration

*

***************************************************************************/

/**

*@brief create a queue instance

*

*@param none

*

*@return success: queue instance handle, fail: NULL.

*@see

*

*/

G_API GPHD tfQueueCreate(void);

/**

*@brief destroy a queue instance

*

*@param queue [in] pointer to queue instance

*

*@return none.

*@see

*

*/

G_API void tfQueueDestroy(GPHD queue);

/**

*@brief clear(remove and free) all item in queue

*

*@param queue [in] pointer to queue instance

*@param item_free [in] callbck function for free item.

*

*@return none.

*@see

*

*/

G_API void tfQueueClear(GPHD queue, tfQueueItemFreeFunc_t item_free);

/**

*@brief append a item to current queue.

*

*@param queue [in] pointer to queue instance

*@param item [in] pointer new item.

*

*@return success: GTRUE, fail: GFALSE

*@see

*

*/

G_API GBOL tfQueueEnQueue(GPHD queue, void* item);

/**

*@brief pop a item from current queue

*

*@param queue [in] pointer to queue instance

*

*@return success: item handle, fail: NULL.

*@see

*

*/

G_API void *tfQueueDeQueue(GPHD queue);

/**

*@brief get the count of item in current queue.

*

*@param queue [in] pointer to queue instance

*

*@return how many item in current queue.

*@see

*

*/

G_API GU32 tfQueueLength(GPHD queue);

#ifdef __cplusplus

}

#endif

#endif //end of __TINY_QUEUE_H__

其源文件如下:

#include

#include "general_macro.h"

#include "tiny_queue.h"

#include "tiny_list.h"

#include "vos_mem.h"

/***************************************************************************

*

* macro declaration

*

***************************************************************************/

#define LOGE printf

#define LOGD printf

#define LOGW printf

/***************************************************************************

*

* data structure declaration

*

***************************************************************************/

/** data structure for item */

typedef struct my_queue_item_s

{

tiny_list_node_t node;

void* data;

}my_queue_item_t;

/** data structure for queue */

typedef struct my_queue_s

{

tiny_list_t items;

}my_queue_t;

/***************************************************************************

*

* inner API define

*

***************************************************************************/

static my_queue_item_t* tqItemNew(void* data)

{

my_queue_item_t* item = (my_queue_item_t*)memAlloc(sizeof(my_queue_item_t));

if (item)

{

item->data = data;

}

return item;

}

/***************************************************************************

*

* API define

*

***************************************************************************/

GPHD tfQueueCreate(void)

{

my_queue_t* mq = (my_queue_t*)memAlloc(sizeof(my_queue_t));

if (mq)

{

memset(mq, 0, sizeof(*mq));

tfListInitialize(&(mq->items), memFree);

}

else

{

LOGE("alloc queue instance failed\n");

}

return mq;

}

void tfQueueDestroy(GPHD queue)

{

if (queue)

{

my_queue_t* mq = (my_queue_t*)queue;

tiny_list_t* tl = &(mq->items);

GU32 left_count = tfListCount(tl);

if (left_count > 0)

{

LOGW("here have: %d items in queue, it's maybe lead to memory leak\n", left_count);

}

tfListClear(tl);

memFree(queue);

}

}

void tfQueueClear(GPHD queue, tfQueueItemFreeFunc_t item_free)

{

if (queue)

{

my_queue_t* mq = (my_queue_t*)queue;

tiny_list_t* tl = &(mq->items);

if (item_free)

{

tiny_list_node_t* node = tfListFront(tl);

while (node)

{

my_queue_item_t* mqi = (my_queue_item_t*)node;

item_free(mqi->data);

node = node->next;

}

}

else

{

LOGW("item_free is NULL, so here wouldn't free item, it maybe lead to memory leak\n");

}

tfListClear(tl);

}

}

GBOL tfQueueEnQueue(GPHD queue, void* item)

{

GBOL ret = GFALSE;

if (queue)

{

my_queue_t* mq = (my_queue_t*)queue;

tiny_list_t* tl = &(mq->items);

my_queue_item_t* mqi = tqItemNew(item);

GCHECK(mqi);

tfListPushBack(tl, (tiny_list_node_t*)mqi);

/** todo, is need check push to list is successed ?? */

ret = GTRUE;

}

return GFALSE;

}

void *tfQueueDeQueue(GPHD queue)

{

void* item = NULL;

if (queue)

{

my_queue_t* mq = (my_queue_t*)queue;

tiny_list_t* tl = &(mq->items);

my_queue_item_t* node = (my_queue_item_t*)tfListFront(tl);

if (node)

{

item = node->data;

tfListPopFront(tl); /** remove head node from list */

}

}

return item;

}

GU32 tfQueueLength(GPHD queue)

{

GU32 ret = 0;

if (queue)

{

my_queue_t* mq = (my_queue_t*)queue;

ret = tfListCount(&(mq->items));

}

return ret;

}

其中的 vos_mem.h是我封装的虚拟系统接口中关于memory操作的部分,以作跨平台使用,以上源文件中使用到的memAlloc,memFree可以简单的理解为标准的malloc和free。general_macro.h可以去看第九章。

四、扪心自问

这里只是实现了无限队列的情况,如果后续在开发的过程中还需要有限队列的话,再添加相关接口与实现代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/347546.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

w ndows7与XP哪个好,Win7系统与Win XP系统哪个更好?Windows7与WindowsXP区别介绍-系统城·电脑系统下载之家...

虽然微软已经停止对xp系统的维护,但是仍有不少用户有这样一个疑惑:Win7系统与WinXP系统哪个更好?接下来,小编就向大家具体介绍Windows7与WindowsXP的区别,让你知道到底哪个系统会更好一些。首先跟系统城小编一起来看微…

一文完整MySQL连接查询,笛卡尔乘积,内连接外连接交叉连接

文章目录笛卡尔乘积连接查询分类等值连接非等值连接自连接外连接交叉连接连接查询又称为多表查询,当查询的字段来自于多个表时,使用连接查询。 笛卡尔乘积 笛卡尔乘积现象:表1有m行,表2有n行,结果有m*n行 发生原因&a…

【PostmanJMeter】使用Postman和JMeter进行signature签名

一、前言 ​ 有些接口的请求会带上sign(签名)进行请求,各接口对sign的签名内容、方式可能不一样,但一般都是从接口的入参中选择部分内容组成一个字符串,然后再进行签名操作, 将结果赋值给sign; 完整规范的接口文档都会…

詹金斯搭建_詹金斯的Maven报告

詹金斯搭建代码质量是一个敏感的话题。 它会影响您的维护成本以及客户满意度。 更不用说您的开发人员使用代码的动力了。 谁想要修复难看的代码,对吗? 讨论代码质量总是需要事实和数字! 因此,这是一个简短的教程,介绍…

Oracle应用容器云的自由

在这篇博客文章中,我将介绍如何部署CloudEE封装在杜克大学应用自由尤伯杯罐子Oracle应用集装箱云端 。 在Oracle Application Container Cloud中进行部署所需的部署工件是一个ZIP归档文件,其中包含应用程序ber-jar和清单文件(manifest.json&…

简洁明了!Java实现单向环形链表以解决约瑟夫环Josepfu问题

文章目录简单介绍代码实现简单介绍 如果把单链表的最后一个节点的指针指向链表头部,而不是指向NULL,那么就构成了一个单向循环链表,通俗讲就是让尾节点指向头结点。 单向环形链表应用场景:Josephu(约瑟夫、约瑟夫环)问题&#xf…

荣耀v10Android9新功能,荣耀10、荣耀V10开启安卓9.0内测 日常领跑行业

【PConline 资讯】今天(8月9日)早上10点,荣耀总裁赵明发微博宣布荣耀已经有四款机型面向少部分用户推送安卓9.0内部测试版本。实际上,在8月8日晚上,花粉论坛就已经公布华为4款机型内测安卓 9.0 版本,荣耀手机两款旗舰进入升级名单…

状态模式 设计模式_设计模式:状态

状态模式 设计模式本文将介绍状态设计模式 。 它是行为设计模式之一 。 您无需了解许多理论即可了解模式的主要概念。 该文章将分为几个部分,在其中我将提供有关需要应用该模式的情况,它所具有的利弊以及用法示例的信息。 有时,当对象的内部…

Java中的AES加密和解密(CBC模式)

通过有线方式传输诸如纯文本密码之类的机密数据总是容易受到安全性的影响,始终建议对此类信息进行加密并使用SSL传输这些机密数据.Java为此提供了多种加密算法。在本文中,我们将讨论Java中具有CBC模式的AES(高级加密标准)对称加密…

hiti打印机android驱动,HiTi 打印机 驱动程序下载——更新 HiTi 软件

HiTi 打印机驱动程序下载如何手动下载和更新:你可以通过 %%os%% 或通过执行 Windows 更新获取基本的 HiTi Printer 驱动程序。 内置驱动程序将支持Printer的基本功能,但通常不支持更高级的功能。以下是手动更新这些 HiTi 设备驱动程序的完整指南。程序员: HiTi 类别…

Java实现最小二乘法线性拟合,传感与检测,单臂半桥全桥实验,江南大学自动化

因为作为资源上传不方便我们获取且我想免费分享给有需要的小伙伴,以后所有实验报告都通过文章形式记录输出了,仅供参考,欢迎交流。(最小二乘法代码在文末) 电桥特性曲线: Java实现最小二乘法线性拟合及计算…

android task详解,Android AsyncTask的使用详解

当然,我们在进行耗时操作或者更新UI时,是可以使用匿名线程的,但是此种方式是存在缺陷的:第一,线程的开销较大,如果每个任务都要创建一个线程,那么应用 程序的效率要低很多;第二&…

【Error】IDEA报错:org.jetbrains.jps.builders.java.dependencyView.TypeRepr$PrimitiveType cannot be cast t

错误日志: org.jetbrains.jps.builders.java.dependencyView.TypeRepr$PrimitiveType cannot be cast to org.jetbrains.jps.builders.java.dependencyView.TypeRepr$ClassType 解决方法:

ReSQL的?

大约在2009年创造出来的NoSQL名字标志着从“传统”关系模型的转变。 在2009年之前,有相当多的非关系数据库,但是在最近几年中,我们看到了许多新产品(例如, 我在上一篇文章中可以看到“ NoSQL格局” )。 一般…

数据结构,Java实现递归回溯,寻找出迷宫路线,解决迷宫问题

/*** Author: Yeman* Date: 2021-10-28-22:52* Description:*/ public class Labyrinth {public static void main(String[] args) {//七行八列的迷宫地图int[][] map new int[8][7];//设置墙for (int i 0; i < 7; i) {map[0][i] 1;map[7][i] 1;}for (int i 0; i < …

android动画优缺点,Android动画总结

动画分为三种&#xff1a;View动画、帧动画和属性动画View动画View动画共有四种动画&#xff1a;TranslateAnimation、RotateAnimation、ScaleAnimation和AlphaAnimation。四个动画类都继承于抽象类Animation。名称标签子类效果平移动画TranslateAnimation移动View缩放动画Scal…

Java实现递归回溯,解决八皇后问题,数据结构与算法

文章目录八皇后问题解决思路代码实现运行结果八皇后问题 八皇后问题&#xff0c;是一个古老而著名的问题&#xff0c;是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯贝瑟尔于1848年提出&#xff1a;在8X8格的国际象棋上摆放八个皇后&#xff0c;使其不能互相攻击&#x…

HTML JS正方形轮播,js,html一个页面里面多个页面轮播

这种轮播都是div或者图片的&#xff0c;div能换成iframe显示嵌套网页吗&#xff1f;或者请问有没有其他方法能实现多个页面轮播&#xff1f;我写了三个iframeframeborder"no" border"0" marginwidth"0" marginheight"0" scrolling&quo…

html制作任务计划列表网页,添加计划任务的脚本

在windows中怎样用bat或者vbs添加计划任务..例如.我想在每次开机10分钟后运行windows目录中的XX.exe文件。应该怎么弄写了一个bat的备份脚本&#xff0c;在添加计划任务的时候&#xff0c;出你可以把 运行的帐号制定成管理员&#xff0c;不要任意用户。200分。用批处理或DOS添加…