日复一日,我们知识慢慢增长,如今我们学过很多循环,有单向循环链表,双向循环链表等,似乎“循环”以及在外面心中不在陌生,今天我要分享的是循环队列;
复习:
1,单向链表之头文件“lbiao.h”(注意写好头文件接口的可以私信找我,关注我,也给我点赞哦)
typedef int sztype;
typedef struct node
{
sztype date;
struct node* next;
}sl;
void lbiaoprint(node*phead);//打印链表
void lbiaopopback(node** pphead,sztype x);//删除后驱节点
void lbiaocrback(node** pphead,sztype x);//插入后驱节点
void lbiaocrfornt(node** pphead,sztype x);//插入前驱节点
void lbiaopopfornt(node** pphead);//删除前驱节点
node* lbiaofind(node** pphead, sztype x);//查找x数据
void lbiaoryweicrfornt(node** pphead, node* pos, sztype x);//插入指定位置的后驱节点
void lbiaoryweicrafter(node* pos, sztype x);//插入指定位置的后驱节点
void lbiaopop_pos(node**pphead,node*pos);//删除指定位置的节点
void lbiaorywei_popafter(node*pos);//删除指定位置的后驱节点
void lbiaoxh(node**pphead);//销毁链表,一个一个删除
2,双向链表之头文件“slbiao.h”注意写好头文件接口的可以私信找我,关注我,也给我点赞哦)
typedef int sztype;
typedef struct Listnode
{
sztype date;
struct Listnode* next;
struct Listnode* prev;
}slbiao;
void slbiao_cshi1(slbiao**pphead);//双向链表初始化一
slbiao* slbiao_cshi2();//双向链表初始化二
void slbiao_xh(slbiao** pphead);//双向链表销毁
void slbiao_crback(slbiao* phead, sztype x);//双向链表的尾插
void slbiao_crfornt(slbiao* phead, sztype x);//双向链表的前插
void slbiaoprint(slbiao* phead);//双向链表的打印
void slbiao_popback(slbiao* phead);//双向链表的后删
void slbiao_popfornt(slbiao* phead);//双向链表的前插
slbiao* slbiao_find(slbiao* phead, sztype pos);//双向链表的查找
void slbiao_zdingcrback(slbiao* pos, sztype x);//链表指定插入
void slbiao_pop(slbiao* pos);//双向链表的指定删除
题目呈现:
一,基本思路
1,我们曾经学过单向循环链表,双向循环链表,那是否可以用这来做呢?
关于这题我们总不会用双向循环链表吧,这不是杀鸡焉用牛刀吗,用飞机抓小偷吗?
我们做题离不开画图:
我们略微思考一下,我们push四个数字,为push(1),push(2),push(3),push(4),看一下效果!
那此时画红的是不是与为空时一样,那我们判断不出来二者的状态!
或许有人提出用size来表示它的状态!,
这种方法有一定可能性,但是我不推荐!
此处我建议用数组来做
为什么选择数组呢?
我总结了3点:1,数组是一段连续的空间,int*指针好维护!2,数组比较简单,代码量小 3,用front,rear 比链表更有实现性!可读性更高,缓冲命中率更高!
值得注意的是:
1,我们要多开辟一个空间,即方便做题,判断它的full()条件!又可以防止栈溢出情况!
2,通过取模来实现循环效果!
3,为满的条件为:(rear+1)%(k+1)==front
代码展示:
1,开辟并进行维护
typedef struct
{
int *pa;//数组指针
int front;//前
int rear;//后
int k;//空间为k个int型
} MyCircularQueue;
//注意取模的妙处!
此处相当于初始化!
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->front=0;
obj->pa=malloc(sizeof(int)*(k+1));
obj->k=k;
obj->rear=0;
return obj;
}
他是否为满呢,以下是几种情况!
我们不难写出以下代码!
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
return ((obj->rear+1)%(obj->k+1))==obj->front;
}
接下来,我们画图写出代码!,相信不难,有问题的铁汁们可以私信我!
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->pa[obj->rear]=value;
obj->rear++;
obj->rear%=(obj->k+1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return false;
}
obj->front++;
obj->front%=obj->k+1;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
else
{
return obj->pa[(obj->front)];
}
}
int myCircularQueueRear(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
else{
return obj->pa[(obj->rear + obj->k)%(obj->k+1)];
}
}
void myCircularQueueFree(MyCircularQueue* obj)
{
obj->pa=NULL;
obj->front=obj->rear=0;
obj->k=0;
free(obj);
}
今天到此结束,希望大家多多支持!
我们相遇在下一题!