日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/2 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言队列原理的实现,c印记(十二):队列queue原理与实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、簡(jiǎn)而言之

在百度百科里面摘取了一段關(guān)于隊(duì)列(queue)的介紹:

隊(duì)列是一種特殊的線性表,特殊之處在于它只允許在表的前端(front)進(jìn)行刪除操作,而在表的后端(rear)進(jìn)行插入操作,和棧一樣,隊(duì)列是一種操作受限制的線性表。

二、一般而言

這里是對(duì)就一般而言, 隊(duì)列的結(jié)構(gòu),操作方法等的表述。

2.1 結(jié)構(gòu)

以下為隊(duì)列的結(jié)構(gòu)示意圖

2.2 實(shí)現(xiàn)分類

一般來(lái)說(shuō),隊(duì)列有兩類實(shí)現(xiàn)方式:

數(shù)組實(shí)現(xiàn):暫時(shí)將其稱為有限隊(duì)列,根據(jù)創(chuàng)建隊(duì)列是傳入的size,創(chuàng)建相應(yīng)size的數(shù)組來(lái)作為隊(duì)列的載體,一般都會(huì)以循環(huán)的方式利用數(shù)組,也可看作循環(huán)隊(duì)列。

優(yōu)點(diǎn):預(yù)先分配好內(nèi)存,在入隊(duì)和出隊(duì)過(guò)程中不會(huì)重新分配內(nèi)存,有一定時(shí)間上的優(yōu)勢(shì)。

缺點(diǎn):因必須預(yù)先分配好內(nèi)存,所以存在內(nèi)存空間浪費(fèi)的問(wèn)題(比如分配了10個(gè)元素,但很多時(shí)候卻只有5個(gè)有效元素),元素?cái)?shù)目固定,不夠靈活。

鏈表實(shí)現(xiàn):可稱其為鏈?zhǔn)疥?duì)列,使用鏈表來(lái)實(shí)現(xiàn)隊(duì)列,理論上這樣的隊(duì)列可以無(wú)限延伸,當(dāng)然根據(jù)實(shí)際需要,可以人為的限制隊(duì)列長(zhǎng)度,讓其表現(xiàn)的和數(shù)組實(shí)現(xiàn)方式差不多。

優(yōu)點(diǎn): 無(wú)需預(yù)先分配內(nèi)存,所以不存在空間浪費(fèi)的問(wèn)題(雖然會(huì)多一個(gè)指針域,但也基本可以接受),隊(duì)列長(zhǎng)度可限制也可不限制,較為靈活。

缺點(diǎn): 入隊(duì)出隊(duì)分別需要分配和釋放元素節(jié)點(diǎn),在時(shí)間上會(huì)略微慢于數(shù)組實(shí)現(xiàn)。

總的來(lái)說(shuō),在可以確定隊(duì)列長(zhǎng)度最大值的情況下,建議用循環(huán)隊(duì)列,如果你無(wú)法預(yù)估隊(duì)列的長(zhǎng)度時(shí),則用鏈隊(duì)列。

2.3 基本操作

這里主要指的是隊(duì)列的入隊(duì)(enqueue)與出隊(duì)(dequeue),對(duì)于鏈?zhǔn)疥?duì)列來(lái)說(shuō),其入隊(duì)和出隊(duì)也就是鏈表的尾部插入與移除頭部節(jié)點(diǎn),這里就不多說(shuō),主要說(shuō)一下以數(shù)組實(shí)現(xiàn)的循環(huán)鏈表的具體實(shí)現(xiàn)(其中head和tail都是表示數(shù)組的下標(biāo))。

入隊(duì): 如上面的循環(huán)隊(duì)列示意圖,入隊(duì)操作,需要先判斷tail節(jié)點(diǎn)的下一個(gè)位置是否是head,如果是就表示隊(duì)列已滿,無(wú)法入隊(duì),如果不是,那就可以入隊(duì),也即是將元素放入tail的下一個(gè)位置,最后將tail加一(也就是指向最終的尾元素),其偽代碼如下:

/** 取余保證,當(dāng)tail = size - 1 時(shí),轉(zhuǎn)回到0 */

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

if (tail != queue->head)

{ /** 此處這樣寫,是因?yàn)檎G闆r下,非滿的情況多于滿了的情況,這樣寫可以稍微的加快點(diǎn)執(zhí)行速度 */

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

queue->tail = tail;

}

else /** 此時(shí)隊(duì)列已滿 */

{

printf("the queue is full!");

}

出隊(duì): 先判斷 tail 和head是否相等,如果相等,就比較隊(duì)列已空,無(wú)元素可出,不等則表示非空。此時(shí)需要取出head對(duì)于位置的元素,然后將head加1(當(dāng)然,為了能夠在head 增加到數(shù)組尾部時(shí)能夠轉(zhuǎn)回到首部,那么這里其實(shí)需要 將head加1與隊(duì)列的size取余再賦值給head),其偽代碼如下:

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

if(queue->tail != queue->head) /** 判斷隊(duì)列不為空 */

{/**這樣寫的作用與上一段偽代碼的作用是一樣的 */

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

/** 取余保證,當(dāng)head= size - 1 時(shí),轉(zhuǎn)回到0 */

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

}

else /** 此時(shí)隊(duì)列已空 */

{

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

}

return elem;

三、和盤托出

這里就是我的具體實(shí)現(xiàn)。目前我實(shí)現(xiàn)的是無(wú)限隊(duì)列(鏈?zhǔn)疥?duì)列 ),鏈表就是前一章實(shí)現(xiàn)的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是我封裝的虛擬系統(tǒng)接口中關(guān)于memory操作的部分,以作跨平臺(tái)使用,以上源文件中使用到的memAlloc,memFree可以簡(jiǎn)單的理解為標(biāo)準(zhǔn)的malloc和free。general_macro.h可以去看第九章。

四、捫心自問(wèn)

這里只是實(shí)現(xiàn)了無(wú)限隊(duì)列的情況,如果后續(xù)在開發(fā)的過(guò)程中還需要有限隊(duì)列的話,再添加相關(guān)接口與實(shí)現(xiàn)代碼。

總結(jié)

以上是生活随笔為你收集整理的c语言队列原理的实现,c印记(十二):队列queue原理与实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。