顺序队列:
线性表的第一个元素作为队头;线性表的最后一个元素作为队尾;
入队的新元素是在线性表的最后时间复杂度为O(1);
出队时需要将后续的所有元素向前时间复杂度为O(n);
顺序队列的优化方案:
定义front使其始终代表队头的下标;
出队时将队头元素返回且front++;
定义rear使其始终代表队尾下一个元素的下标;
入队时将新元素插入 且rear++;
没有必要只将下标为0的位置定义为队头!!!
顺序队列的关键状态
初始状态:length == 0, front == 0, rear == 0;
空队列状态:length == 0, front == rear;
满队列状态:length == capacity, front == rear;
循环使用队列中的空间
入队:rear = (rear + 1) % capacity;
出队:front = (front + 1) % capacity;
#include <stdio.h>
#include <malloc.h>
#include "SeqQueue.h"
typedef unsigned int TSeqQueueNode;//数组结点
typedef struct _tag_SeqQueue//顺序队列的头
{
int capacity;//顺序队列的容量
int length;//队列长度
int front;//队头
int rear;//队尾
TSeqQueueNode* node;//空间
} TSeqQueue;
SeqQueue* SeqQueue_Create(int capacity) // O(1)
{
TSeqQueue* ret = NULL;
if( capacity >= 0 )//合法性判断,至少保证队列容量大于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);
}
return ret;
}
void SeqQueue_Destroy(SeqQueue* queue) // O(1)
{
free(queue);
}
void SeqQueue_Clear(SeqQueue* queue) // O(1)
{
TSeqQueue* sQueue = (TSeqQueue*)queue;
if( sQueue != NULL )//恢复至初始状态即清空
{
sQueue->length = 0;
sQueue->front = 0;
sQueue->rear = 0;
}
}
int SeqQueue_Append(SeqQueue* queue, void* item) // O(1)
{
TSeqQueue* sQueue = (TSeqQueue*)queue;
int ret = (sQueue != NULL) && (item != NULL);//队列不为空,插入元素不为空
ret = ret && (sQueue->length + 1 <= sQueue->capacity);//队列中有空间可以插入
if( ret )
{
sQueue->node[sQueue->rear] = (TSeqQueueNode)item;//合法性判断成功后,队尾插入新元素
sQueue->rear = (sQueue->rear + 1) % sQueue->capacity;//rear应到下一个位置,因为要循环使用数组中的元素,因此需要取余
sQueue->length++;
}
return ret;
}
void* SeqQueue_Retrieve(SeqQueue* queue) // O(1)
{
TSeqQueue* sQueue = (TSeqQueue*)queue;
void* ret = SeqQueue_Header(queue);//调用header,获取队头元素
if( ret != NULL )
{
sQueue->front = (sQueue->front + 1) % sQueue->capacity;//同rear
sQueue->length--;
}
return ret;
}
void* SeqQueue_Header(SeqQueue* queue) // O(1)
{
TSeqQueue* sQueue = (TSeqQueue*)queue;
void* ret = NULL;
if( (sQueue != NULL) && (sQueue->length > 0) )//队列不为空,长度大于零,
{
ret = (void*)(sQueue->node[sQueue->front]);
}
return ret;
}
int SeqQueue_Length(SeqQueue* queue) // O(1)
{
TSeqQueue* sQueue = (TSeqQueue*)queue;
int ret = -1;
if( sQueue != NULL )
{
ret = sQueue->length;
}
return ret;
}
int SeqQueue_Capacity(SeqQueue* queue) // O(1)
{
TSeqQueue* sQueue = (TSeqQueue*)queue;
int ret = -1;
if( sQueue != NULL )
{
ret = sQueue->capacity;
}
return ret;
}
链式队列的瓶颈:
链式队列:
线性表的第一个元素作为队头;
线性表的最后一个元素作为队尾;
入队的新元素是在线性表的最后 时间复杂度为O(n);
出队的元素即链表的第一个元素时间复杂度为O(1);
链式队列的优化方案:
定义rear指针始终指向链表中的最有一个元素;
入队时将新元素通过rear插入队尾且将rear指向新元素;
链式队列的关键状态
空队列状态:front == NULL, rear == NULL;
关键操作
入队:
• rear->next = node;
• rear = node;
• node->next = NULL;
出队:
• front = front->next
#include <malloc.h>
#include <stdio.h>
#include "LinkQueue.h"
typedef struct _tag_LinkQueueNode TLinkQueueNode;//链式队列中的每一个结点
struct _tag_LinkQueueNode
{
TLinkQueueNode* next;
void* item;
};
typedef struct _tag_LinkQueue//链式队列的表头结点
{
TLinkQueueNode* front;
TLinkQueueNode* rear;
int length;
} TLinkQueue;
LinkQueue* LinkQueue_Create() // O(1)
{
TLinkQueue* ret = (TLinkQueue*)malloc(sizeof(TLinkQueue));//申请表头结点空间
if( ret != NULL )//申请成功
{
ret->front = NULL;//初始化
ret->rear = NULL;
ret->length = 0;
}
return ret;
}
void LinkQueue_Destroy(LinkQueue* queue) // O(n)
{
LinkQueue_Clear(queue);//因为申请了空间,必须清空
free(queue);
}
void LinkQueue_Clear(LinkQueue* queue) // O(n)
{
while( LinkQueue_Length(queue) > 0 )
{
LinkQueue_Retrieve(queue);//释放队列里的每一个结点
}
}
int LinkQueue_Append(LinkQueue* queue, void* item) // O(1)//无循环无遍历
{
TLinkQueue* sQueue = (TLinkQueue*)queue;//强制类型转换
TLinkQueueNode* node = (TLinkQueueNode*)malloc(sizeof(TLinkQueueNode));//申请元素结点空间
int ret = (sQueue != NULL ) && (item != NULL) && (node != NULL);//合法性检测
if( ret )
{
node->item = item;
if( sQueue->length > 0 )
{
sQueue->rear->next = node;//最后一个元素的next指针指向node
sQueue->rear = node;//队尾rear指向node
node->next = NULL;
}
else//如果队列中的一个元素都没有
{
sQueue->front = node;
sQueue->rear = node;
node->next = NULL;
}
sQueue->length++;
}
if( !ret )//合法性检测未通过
{
free(node);//释放,防止内存泄漏
}
return ret;
}
void* LinkQueue_Retrieve(LinkQueue* queue) // O(1)无循环无遍历
{
TLinkQueue* sQueue = (TLinkQueue*)queue;
TLinkQueueNode* node = NULL;
void* ret = NULL;
if( (sQueue != NULL) && (sQueue->length > 0) )//队列中有元素可删
{
node = sQueue->front;//node指向第一个元素
sQueue->front = node->next;//front移动到下一个元素
ret = node->item;//node里面的给返回值
free(node);//释放内存
sQueue->length--;
if( sQueue->length == 0 )//如果元素删完,则恢复至初始状态
{
sQueue->front = NULL;
sQueue->rear = NULL;
}
}
return ret;
}
void* LinkQueue_Header(LinkQueue* queue) // O(1)
{
TLinkQueue* sQueue = (TLinkQueue*)queue;
void* ret = NULL;
if( (sQueue != NULL) && (sQueue->length > 0) )
{
ret = sQueue->front->item;
}
return ret;
}
int LinkQueue_Length(LinkQueue* queue) // O(1)
{
TLinkQueue* sQueue = (TLinkQueue*)queue;
int ret = -1;
if( sQueue != NULL )
{
ret = sQueue->length;
}
return ret;
}
优化的顺序队列循环利用顺序空间提高出队操作的效率;
优化的链式队列定义rear rear指针指向队尾元素 指针指向队尾元素提高出队操作的效率;