两种方式实现循环队列 -- 数组形式 和 链表形式
目录
题目:
需要注意的是这里的队列的长度是限定好的 因此无论我们在使用链表还是使用数组时 均需要考虑K的影响。因为这是个循环队列 为了区别该队列为空还是满 我们要增加一个额外的空间 作为缓冲
数组形式:
创建基本结构
typedef struct {
int *a ;
int head ;
int tail ;
int k ;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* cq = ( MyCircularQueue*)malloc(sizeof(MyCircularQueue));
cq->a =(int*)malloc(sizeof(int)*(k+1));//a也需要动态开辟出来
cq->head = cq->tail = 0;
cq->k=k;
return cq;
}
判断数组是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->head == obj->tail;
}
判断数组是否满了
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->tail+1)%(obj->k+1)==(obj->head);
}
插入数据
这个需要注意的是 队列的长度是固定的 如果数组下标会超出限定值之外时 要对下标进行一个处理
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
//插入 要确定是否满了
if(myCircularQueueIsFull(obj))
{
return false;
}
//开始插入
obj->a[obj->tail]=value;
obj->tail++;
obj->tail %= (obj->k+1);//这里采用的这种方式 也可以使用if进行判断 从而修改超出的下标
return true;
}
删除数据
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
//删除
//判断是否为空
if(myCircularQueueIsEmpty(obj))
{
return false;
}
obj->head++;
obj->head %= (obj->k+1);//head 也有可能会超出范围
return true;
}
返回队首元素
int myCircularQueueFront(MyCircularQueue* obj) {
//判断是否为空
if(myCircularQueueIsEmpty(obj))
return -1;
//不为空 返回队首的元素
return obj->a[obj->head];
}
返回队尾元素
这里的返回队尾要比队首麻烦一点 其实一般情况比较简单 只需要返回tail的坐标-1就好
但是存在特殊情况 有可能tail处于0的位置 这时候就不成立了 可以如下方代码处理或者采用if
int myCircularQueueRear(MyCircularQueue* obj) {
//判断是否为空
if(myCircularQueueIsEmpty(obj))
return -1;
//不为空 返回队尾的元素 //
int end = (obj->tail + obj->k) %(obj->k+1);
return obj->a[end];
}
销毁队列
删除全面。
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}
链表形式:
链表形式相较于数组形式 在除创建之外的各功能都要简单
创建基本结构
创建链表 和 创建包含着队列长度 前后指针的结构体
typedef struct list
{
int val;
struct list* next;
}list;//创建结点基本结构
typedef struct {
list* head;
list* tail;//记录尾结点
int k;//保存k的值
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
cq->k = k;
int count = k + 1;
while (count)
{
list* newnode = (list*)malloc(sizeof(list));
if (count == k + 1)
{
cq->tail = cq->head = newnode;
cq->tail->next = cq->head;
}
newnode->next = cq->tail->next;
cq->tail->next = newnode;
cq->tail = newnode;
count--;
}
cq->tail = cq->head;
return cq;
}
判断链表是否满了
此接口和判断是否为空接口要提前设计 方面其他函数复用
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return obj->tail->next == obj->head;
}
判断链表是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->head == obj->tail;
}
插入数据
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
//判断是否满了
if (myCircularQueueIsFull(obj))
{
return false;
}
//录入数据
obj->tail->val = value;
obj->tail = obj->tail->next;
return true;
}
删除数据
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
//判断是否为空
if (myCircularQueueIsEmpty(obj))
{
return false;
}
//删除数据
obj->head = obj->head->next;
return true;
}
返回队头值
int myCircularQueueFront(MyCircularQueue* obj) {
//判断是否为空
if (myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->head->val;
}
返回队尾元素
这个较返回队头元素稍微麻烦一点 但也只是麻烦一点 比数组形式要简单的多
int myCircularQueueRear(MyCircularQueue* obj) {
if (myCircularQueueIsEmpty(obj))
{
return -1;
}
list* tmp = obj->head;
while (tmp->next != obj->tail)
{
tmp = tmp->next;
}
return tmp->val;
}
销毁队列
全面就好了
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->head);
free(obj);
}