c语言队列原理的实现,c印记(十二):队列queue原理与实现
一、簡而言之
在百度百科里面摘取了一段關(guān)于隊列(queue)的介紹:
隊列是一種特殊的線性表,特殊之處在于它只允許在表的前端(front)進(jìn)行刪除操作,而在表的后端(rear)進(jìn)行插入操作,和棧一樣,隊列是一種操作受限制的線性表。
二、一般而言
這里是對就一般而言, 隊列的結(jié)構(gòu),操作方法等的表述。
2.1 結(jié)構(gòu)
以下為隊列的結(jié)構(gòu)示意圖
2.2 實現(xiàn)分類
一般來說,隊列有兩類實現(xiàn)方式:
數(shù)組實現(xiàn):暫時將其稱為有限隊列,根據(jù)創(chuàng)建隊列是傳入的size,創(chuàng)建相應(yīng)size的數(shù)組來作為隊列的載體,一般都會以循環(huán)的方式利用數(shù)組,也可看作循環(huán)隊列。
優(yōu)點:預(yù)先分配好內(nèi)存,在入隊和出隊過程中不會重新分配內(nèi)存,有一定時間上的優(yōu)勢。
缺點:因必須預(yù)先分配好內(nèi)存,所以存在內(nèi)存空間浪費的問題(比如分配了10個元素,但很多時候卻只有5個有效元素),元素數(shù)目固定,不夠靈活。
鏈表實現(xiàn):可稱其為鏈?zhǔn)疥犃?#xff0c;使用鏈表來實現(xiàn)隊列,理論上這樣的隊列可以無限延伸,當(dāng)然根據(jù)實際需要,可以人為的限制隊列長度,讓其表現(xiàn)的和數(shù)組實現(xiàn)方式差不多。
優(yōu)點: 無需預(yù)先分配內(nèi)存,所以不存在空間浪費的問題(雖然會多一個指針域,但也基本可以接受),隊列長度可限制也可不限制,較為靈活。
缺點: 入隊出隊分別需要分配和釋放元素節(jié)點,在時間上會略微慢于數(shù)組實現(xiàn)。
總的來說,在可以確定隊列長度最大值的情況下,建議用循環(huán)隊列,如果你無法預(yù)估隊列的長度時,則用鏈隊列。
2.3 基本操作
這里主要指的是隊列的入隊(enqueue)與出隊(dequeue),對于鏈?zhǔn)疥犃衼碚f,其入隊和出隊也就是鏈表的尾部插入與移除頭部節(jié)點,這里就不多說,主要說一下以數(shù)組實現(xiàn)的循環(huán)鏈表的具體實現(xiàn)(其中head和tail都是表示數(shù)組的下標(biāo))。
入隊: 如上面的循環(huán)隊列示意圖,入隊操作,需要先判斷tail節(jié)點的下一個位置是否是head,如果是就表示隊列已滿,無法入隊,如果不是,那就可以入隊,也即是將元素放入tail的下一個位置,最后將tail加一(也就是指向最終的尾元素),其偽代碼如下:
/** 取余保證,當(dāng)tail = size - 1 時,轉(zhuǎn)回到0 */
int tail = (queue->tail + 1) % queue->size;
if (tail != queue->head)
{ /** 此處這樣寫,是因為正常情況下,非滿的情況多于滿了的情況,這樣寫可以稍微的加快點執(zhí)行速度 */
queue->elems[queue->tail] = elem;
queue->tail = tail;
}
else /** 此時隊列已滿 */
{
printf("the queue is full!");
}
出隊: 先判斷 tail 和head是否相等,如果相等,就比較隊列已空,無元素可出,不等則表示非空。此時需要取出head對于位置的元素,然后將head加1(當(dāng)然,為了能夠在head 增加到數(shù)組尾部時能夠轉(zhuǎn)回到首部,那么這里其實需要 將head加1與隊列的size取余再賦值給head),其偽代碼如下:
elem_type elem = elem_null; /** 初始化元素 */
if(queue->tail != queue->head) /** 判斷隊列不為空 */
{/**這樣寫的作用與上一段偽代碼的作用是一樣的 */
elem = queue->elems[queue->head];
/** 取余保證,當(dāng)head= size - 1 時,轉(zhuǎn)回到0 */
queue->head = (queue->head+1) % queue->size;
}
else /** 此時隊列已空 */
{
printf("the queue is empty \n");
}
return elem;
三、和盤托出
這里就是我的具體實現(xiàn)。目前我實現(xiàn)的是無限隊列(鏈?zhǔn)疥犃?),鏈表就是前一章實現(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操作的部分,以作跨平臺使用,以上源文件中使用到的memAlloc,memFree可以簡單的理解為標(biāo)準(zhǔn)的malloc和free。general_macro.h可以去看第九章。
四、捫心自問
這里只是實現(xiàn)了無限隊列的情況,如果后續(xù)在開發(fā)的過程中還需要有限隊列的話,再添加相關(guān)接口與實現(xiàn)代碼。
總結(jié)
以上是生活随笔為你收集整理的c语言队列原理的实现,c印记(十二):队列queue原理与实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DDOS流量峰值测试IP(DDOS流量峰
- 下一篇: android已经点击,【已解决】and