代码如下:
SeqQueue.c文件:
/************************************************************************************ 文件名:SeqQueue.c 头文件:SeqQueue.h 时间: 2014/03/31 作者: Hao 功能:可以复用的顺序循环队列 即入队列和出队列的时间复杂度都为O(1) ************************************************************************************/ #include <stdio.h> #include <malloc.h> #include "SeqQueue.h" typedef void* TSeqQueueNode; typedef struct str_SeqQueue { int capacity; int length; int front; int rear; TSeqQueueNode* node; }TSeqQueue; /************************************************************************************ 函数名: SeqQueue_Create 函数功能: 创建一个容量为capacity的循环队列 参数: int capacity 创建循环队列中成员的个数 即循环队列容量 返回值: void* ret 如果返回NULL 说明创建循环队列失败 如果返回ret 说明创建循环队列成功 且ret为描述循环队列的结构体 ************************************************************************************/ SeqQueue* SeqQueue_Create(int capacity) { TSeqQueue* ret = NULL; if( capacity >= 0 ) { ret = (TSeqQueue*)malloc(sizeof(TSeqQueue) + sizeof(TSeqQueueNode) * capacity); if( ret != NULL ) { ret->capacity = capacity; ret->length = 0; ret->front = 0; ret->rear = 0; ret->node = (TSeqQueueNode*)(ret + 1); } } else { ret = NULL; } return (SeqQueue*)ret; } /************************************************************************************ 函数名: SeqQueue_Destroy 函数功能: 销毁循环队列 free开辟的内存 参数: void* list 描述循环队列结构体指针 返回值: void ************************************************************************************/ void SeqQueue_Destroy(SeqQueue* queue) { free(queue); } /************************************************************************************ 函数名: SeqQueue_Clear 函数功能:清空循环队列 其实就是给length=0; front = 0 rear = 0; 函数参数:SeqQueue* queue 描述循环队列结构体指针 函数返回值:int ret 成功返回0 失败返回-1 ************************************************************************************/ int SeqQueue_Clear(SeqQueue* queue) { int ret; TSeqQueue *Tqueue = (TSeqQueue* )queue; /*函数参数合法性检测*/ if(NULL != Tqueue) { Tqueue->length = 0; Tqueue->front = 0; Tqueue->rear = 0; ret=0; } else ret=-1; return ret; } /************************************************************************************ 函数名: SeqQueue_Length 函数功能:获得循环队列 现在的大小 函数参数:void* list 描述循环队列结构体指针 函数返回值:int ret 成功返回length 失败返回-1 ************************************************************************************/ int SeqQueue_Length(SeqQueue* queue) { int ret; TSeqQueue *Tqueue = (SeqQueue* )queue; /*函数参数合法性检测*/ if(NULL != Tqueue) { ret = Tqueue->length; } else ret = -1; return ret; } /************************************************************************************ 函数名: SeqQueue_Capacity 函数功能:获得循环队列 的容量 函数参数:void* list 描述循环队列结构体指针 函数返回值:int ret 成功返回capacity 失败返回-1 ************************************************************************************/ int SeqQueue_Capacity(SeqQueue* queue) { int ret; TSeqQueue *Tqueue = (SeqQueue* )queue; /*函数参数合法性检测*/ if(NULL != Tqueue) { ret = Tqueue->capacity; } else ret = -1; return ret; } /************************************************************************************ 函数名: SeqQueue_Push 函数功能:入队操作 函数参数:SeqQueue* queue入队队列, void* data入队数据元素 这个队列是从尾部入队rear 从头部出队front 函数返回值:int ret 成功返回 1 失败返回 0 ************************************************************************************/ int SeqQueue_Push(SeqQueue* queue, void* data) { TSeqQueue* Tqueue = (TSeqQueue*)queue; int ret = (Tqueue != NULL) && (data != NULL); //安全性检测 ret = ret && (Tqueue->length + 1 <= Tqueue->capacity); //容量检测 if(ret) { Tqueue->node[Tqueue->rear] = data; Tqueue->rear = (Tqueue->rear + 1) % Tqueue->capacity; Tqueue->length++; } return ret; } /************************************************************************************ 函数名: SeqQueue_Pop 函数功能:出队操作 函数参数:SeqQueue* queue出队队列 这个队列是从尾部入队rear 从头部出队front 函数返回值:void* ret 成功返回 数据元素地址 失败返回 NULL ************************************************************************************/ void* SeqQueue_Pop(SeqQueue* queue) { TSeqQueue* Tqueue = (TSeqQueue*)queue; void* ret = NULL; if((Tqueue != NULL) && (Tqueue->length > 0)) { ret = (void*)(Tqueue->node[Tqueue->front]); Tqueue->front = (Tqueue->front + 1) % Tqueue->capacity; Tqueue->length--; } return ret; } /************************************************************************************ 函数名: SeqQueue_Top 函数功能:获得队尾元素地址 函数参数:SeqQueue* queue出队队列 这个队列是从尾部入队rear 从头部出队front 函数返回值:void* ret 成功返回 队尾数据元素地址 失败返回 NULL ************************************************************************************/ void* SeqQueue_Top(SeqQueue* queue) { TSeqQueue* Tqueue = (TSeqQueue*)queue; void* ret = NULL; if((Tqueue != NULL) && (Tqueue->length > 0)) { ret = (void*)(Tqueue->node[Tqueue->front]); } return ret; }
#ifndef _SeqQueue_H_ #define _SeqQueue_H_ typedef void SeqQueue; SeqQueue* SeqQueue_Create(int capacity); void SeqQueue_Destroy(SeqQueue* queue); int SeqQueue_Clear(SeqQueue* queue); int SeqQueue_Push(SeqQueue* queue, void* data); void* SeqQueue_Pop(SeqQueue* queue); void* SeqQueue_Top(SeqQueue* queue); int SeqQueue_Length(SeqQueue* queue); int SeqQueue_Capacity(SeqQueue* queue); #endif
#include <stdio.h> #include <stdlib.h> #include "SeqQueue.h" int main(int argc, char *argv[]) { SeqQueue* queue = SeqQueue_Create(6); int a[10] = {0}; int i = 0; for(i=0; i<10; i++) { a[i] = i + 1; SeqQueue_Push(queue, a + i); } printf("Top: %d\n", *(int*)SeqQueue_Top(queue)); printf("Length: %d\n", SeqQueue_Length(queue)); printf("Capacity: %d\n", SeqQueue_Capacity(queue)); while( SeqQueue_Length(queue) > 0 ) { printf("Pop: %d\n", *(int*)SeqQueue_Pop(queue)); } printf("\n"); for(i=0; i<10; i++) { a[i] = i + 1; SeqQueue_Push(queue, a + i); printf("Pop: %d\n", *(int*)SeqQueue_Pop(queue)); } SeqQueue_Destroy(queue); return 0; }注意:其实循环队列就是在一段内存空间中,使用front和rear变量夹住一端空间,使其成为顺序队列,并且入队列和出队列的时间复杂度都是O(1)
示例代码:
LinkQueue.c文件:
/******************************************************************************************************* 文件名:LinkQueue.c 头文件:LinkQueue.h 时间: 2013/03/31 作者: Hao 功能: 可以复用 链式队列 *******************************************************************************************************/ #include <stdio.h> #include <malloc.h> #include "LinkQueue.h" typedef struct str_linkqueue { LinkQueueNode* front; LinkQueueNode* rear; int length; }link_queue; /******************************************************************************************************* 函数名: Creat_LinkQueueHead 函数功能:创建一个链式队列头 并给队列头分配空间 参数: void 返回值:ret 成功返回链表头地址 失败返回NULL *******************************************************************************************************/ LinkQueue* Creat_LinkQueueHead(void) { link_queue* ret = NULL; ret = (link_queue* )malloc( sizeof(link_queue)*1 ); if(NULL != ret) //malloc分配成功 { ret -> length = 0; ret -> front = NULL; ret -> rear = NULL; } return (LinkQueue* )ret; } /******************************************************************************************************* 函数名: Get_Length 函数功能:获得链式队列的长度 参数: LinkQueue* queue 描述队列的结构体 返回值:ret 成功返回队列长度 失败返回0 *******************************************************************************************************/ int Get_Length(LinkQueue* queue) { int ret = 0; link_queue* lqueue = (link_queue* )queue; if( NULL != lqueue ) { ret = lqueue -> length; } return ret; } /******************************************************************************************************* 函数名: LinkQueue_Push 函数功能:把数据data从队尾加入队列中 参数: LinkQueue* queue 描述队列的结构体 void* data 要加入队列数据的地址 返回值:ret 成功返回1 失败返回0 *******************************************************************************************************/ int LinkQueue_Push(LinkQueue* queue, void* data) { link_queue* lqueue = (link_queue* )queue; int ret = ((NULL != lqueue)&&(NULL != data)); if(ret) { LinkQueueNode* node = (LinkQueueNode*)malloc(sizeof(LinkQueueNode)); if(NULL != node) { node -> Queuedata = data; if(lqueue -> length == 0) { lqueue -> front = node; lqueue -> rear = node; node -> next = NULL; } else { lqueue -> rear -> next = node; lqueue -> rear = node; node -> next = NULL; } lqueue -> length++; } } return ret; } /******************************************************************************************************* 函数名: LinkQueue_Pop 函数功能:把数据从队头取出 参数: LinkQueue* queue 描述队列的结构体 返回值:ret 成功返回取出数据地址 失败返回NULL *******************************************************************************************************/ void* LinkQueue_Pop(LinkQueue* queue) { void* ret = NULL; LinkQueueNode* node = NULL; link_queue* lqueue = (link_queue* )queue; if((NULL != lqueue)&&(lqueue->length > 0)) { node = lqueue->front; lqueue->front = lqueue->front->next; lqueue->length--; ret = node->Queuedata; free(node); if(lqueue->length == 0) { lqueue->front = NULL; //其实理论上可以不给front赋值NULL的 lqueue->rear = NULL; } } return ret; } /******************************************************************************************************* 函数名: LinkQueue_Top 函数功能:获得队头数据地址 参数: LinkQueue* queue 描述队列的结构体 返回值:ret 成功返回取出数据地址 失败返回NULL *******************************************************************************************************/ void* LinkQueue_Top(LinkQueue* queue) { void* ret = NULL; link_queue* lqueue = (link_queue* )queue; if((NULL != lqueue)&&(lqueue->length > 0)) { ret = lqueue->front->Queuedata; } return ret; } /******************************************************************************************************* 函数名: Clean_LinkQueue 函数功能:清空队列 参数: LinkQueue* queue 描述队列的结构体 返回值:ret 成功返回1 失败返回0 *******************************************************************************************************/ int Clean_LinkQueue(LinkQueue* queue) { int ret = 0; void* temp = NULL; if(NULL != queue) { ret = 1; while(Get_Length(queue)) { temp = LinkQueue_Pop(queue); if(NULL == temp) { ret = 0; break; } } } return ret; } /******************************************************************************************************* 函数名: Destroy_LinkQueue 函数功能:清空队列并且销毁队列头 参数: LinkQueue* queue 描述队列的结构体 返回值:ret 成功返回1 失败返回0 *******************************************************************************************************/ void Destroy_LinkQueue(LinkQueue* queue) { Clean_LinkQueue(queue); free(queue); }
#ifndef __LinkQueue_H__ #define __LinkQueue_H__ typedef void LinkQueue; //这个是为了 封装方便 typedef struct Str_LinkQueue LinkQueueNode; //这个结构体是链表的真身 struct Str_LinkQueue { LinkQueueNode* next; void* Queuedata; }; LinkQueue* Creat_LinkQueueHead(void); void Destroy_LinkQueue(LinkQueue* queue); int Get_Length(LinkQueue* queue); int Clean_LinkQueue(LinkQueue* queue); int LinkQueue_Push(LinkQueue* queue, void* data); void* LinkQueue_Pop(LinkQueue* queue); void* LinkQueue_Top(LinkQueue* queue); #endif
#include <stdio.h> #include "LinkQueue.h" int main() { LinkQueue* queue = Creat_LinkQueueHead(); int a[10] = {0}; int i = 0; for(i=0; i<10; i++) { a[i] = i + 1; LinkQueue_Push(queue, a + i); } printf("Pop: %d\n", *(int*)LinkQueue_Pop(queue)); printf("Top: %d\n", *(int*)LinkQueue_Top(queue)); printf("Length: %d\n", Get_Length(queue)); //Clean_LinkQueue(queue); while( Get_Length(queue) > 0 ) { printf("Pop: %d\n", *(int*)LinkQueue_Pop(queue)); } Destroy_LinkQueue(queue); return 0; }注意:链队列,无非就是定义了两个指针,分别指向队列头和队列尾,这样找到队头和队尾的时间复杂度就是O(1)