队列
1.顺序队列(循环)
前置知识
text
一种先进先出的结构
先简述下为什么要写循环队列 ----->主要是为了解决 "假溢出"
text
就是rear指到最后已经满了 但是同时前面又出队了 这样还有位置但是进不去
循环队列相关
c
一个问题 若我们规定空队列时是front == rear 当队列满时呢? 也是front == rear???
**这里我采用浪费一个空间的方法(浪费队列的首空间)(也就是队列首个空间不放元素)
由于rear可能比front大,也可能比front小,所以在他们相差一个位置的时候,就是满的情况
也可能是相差一整圈,也是满的情况(这种是队列中没有一个出队的)
这里我们规定队列的最大空间为MaxQueueSize
1. front == rear //队列为空
2. (rear + 1) % MaxQueueSize == front //队列为满
1.入队
text
1.判断队列是否已满
2.移动rear指针
3.放值
-
判断队列是否已满------> if ( ( queue->rear + 1 ) % MaxQueueSize == queue->front )
-
移动rear指针 ------> queue->rear = ( queue->rear + 1 ) % MaxQueueSize;
-
放值 ------> queue->dataqueue-\>rear = e;
text
1.判断队列是否已满
2.移动rear指针
3.放值
c
if ((queue->rear + 1) % MaxQueueSize == queue->front)
{
fprintf(stderr, "Queue Full!\n");
return -1;
}
queue->rear = (queue->rear + 1) % MaxQueueSize;
queue->data[queue->rear] = e;
2.出队
text
1.判断队列是否为空
2.移动front指针
-
判断队列是否为空------> if (queue->rear == queue->front)
-
移动front指针 ------> queue->front = (queue->front + 1) % MaxQueueSize;
text
1.判断队列是否为空
2.移动front指针
c
if (queue->rear == queue->front)
{
fprintf(stderr, "Queue Empty!\n");
return -1;
}
queue->front = (queue->front + 1) % MaxQueueSize;
头文件部分
c
typedef int Element;
#define MaxQueueSize 5
typedef struct
{
Element data[MaxQueueSize];
int front;
int rear;
}ArrayQueue;
//1.初始化循环队列
void initArrayQueue(ArrayQueue* queue);
//2.入队
int enArrayQueue(ArrayQueue* queue, Element e);
//3.出队
int deArrayQueue(ArrayQueue* queue, Element* e);
实现
1.初始化循环队列
c
//1.初始化循环队列
void initArrayQueue(ArrayQueue* queue)
{
//初始化
memset(stack->data, 0, sizeof(stack->data));
queue->front = queue->rear = 0;
}
2.入队
c
int enArrayQueue(ArrayQueue* queue, Element e)
{
//入队相关代码
//1.判断队列是否已满
if ((queue->rear + 1) % MaxQueueSize == queue->front) {
fprintf(stderr, "Queue Full!\n");
return -1;
}
//2.移动rear指针
queue->rear = (queue->rear + 1) % MaxQueueSize;
//3.放值
queue->data[queue->rear] = e;
return 0;
}
3.出队
c
int deArrayQueue(ArrayQueue* queue, Element* e) //用e返回队头元素
{
//出队相关代码
//1.判断队列是否为空
if (queue->rear == queue->front) {
fprintf(stderr, "Queue Empty!\n");
return -1;
}
//2.移动front指针
queue->front = (queue->front + 1) % MaxQueueSize;
//通过指针修改外部实参 带出队首元素
*e = queue->data[queue->front];
return 0;
}
测试案例
main函数
c
void test03()
{
ArrayQueue stu1;
//初始化队列
initArrayQueue(&stu1);
//循环入队5个元素
for (int i = 0;i < MaxQueueSize-1;i++) {
enArrayQueue(&stu1,i+100);
}
//队列已满 入队失败
enArrayQueue(&stu1,520);
//出队 并查看队列中元素
Element x1;
while (deArrayQueue(&stu1, &x1) != -1)
{
printf("%d\t", x1);
}
printf("\n");
}
输出结果
c
Queue Full!
619 620 621 622 Queue Empty!
2.链式队列
前置知识
text
链式队列其实就是单链表 直播不过它只能头进尾出而已
先看下队列的样子吧
1.入队
text
这个该往rear的后面插 即尾插
为了方便出队(如果头插了 出队的时候front也不能往前走啊)
1.创建新结点
2.更新新节点
3.更新队尾的next指针 连接新节点
4.更新队尾指针
-
创建新节点 ------> *QueNode new_node = malloc(sizeof(QueNode));
-
更新新节点 ------> new_node->next = NULL;
-
更新队尾的next指针 连接新节点 ------> queue->rear->next = new_node;
-
更新队尾指针 ------> queue->rear = new_node;
text
1.创建新结点
2.更新新节点
3.更新队尾的next指针 连接新节点
4.更新队尾指针
c
QueNode *new_node = malloc(sizeof(QueNode));
new_node->next = NULL;
queue->rear->next = new_node;
queue->rear = new_node;
2.出队
text
1.引入辅助指针tmp备份待删除位置
2.修改队头指针 跳过待删除节点 重新衔接队列
3.删除tmp
-
引入辅助指针tmp备份待删除位置 ------> *QueNode tmp = queue->front;
-
修改队头指针 跳过待删除节点 重新衔接队列 ------> queue->front = tmp->next;
-
删除tmp ------> free(tmp);
text
1.引入辅助指针tmp备份待删除位置
2.修改队头指针 跳过待删除节点 重新衔接队列
3.删除tmp
c
QueNode *tmp = queue->front;
queue->front = tmp->next;
free(tmp);
头文件部分
c
typedef int Element;
// 链式队列的节点
typedef struct _node
{
Element data;
struct _node *next;
} QueNode;
// 链式队列的头节点
typedef struct
{
QueNode *rear; //队列头指针
QueNode *front; //队列尾指针
int cnt; //用来计数队列中的节点数量 这个其实写不写都可以
const char *name; //链式队列名字 写不写都可以 写着玩
} LinkQueue;
//1.创建链式队列
LinkQueue *createLinkQueue(const char *name);
//2.释放链式队列
void releaseLinkQueue(LinkQueue *queue);
//3.入队
int enLinkQueue(LinkQueue *queue, Element e);
//4.出队
int deLinkQueue(LinkQueue *queue, Element *e);
实现
1.创建链式队列
c
LinkQueue* createLinkQueue(const char *name)
{
//创建链式队列
LinkQueue* queue = malloc(sizeof(LinkQueue));
if (queue == NULL) {
fprintf(stderr, "createLinkQueue malloc failed!\n");
return NULL;
}
//初始化
queue->name = name;
queue->front =queue->rear = NULL;
queue->cnt = 0;
//返回该链式队列
return queue;
}
2.释放链式队列
c
void releaseLinkQueue(LinkQueue* queue)
{
if (queue)
{
QueNode *tmp;
while (queue->front)
{
//出队相关代码
tmp = queue->front;
queue->front = tmp->next; //不断向后遍历队列中节点
free(tmp);
//减少队列中节点数量
queue->cnt--;
}
printf("queue have %d node!\n", queue->cnt);
//最后释放队列
free(queue);
}
}
3.入队
c
// 先有新节点,新节点应该rear的next方向插入,便于front的删除
int enLinkQueue(LinkQueue* queue, Element e)
{
QueNode *node = malloc(sizeof(QueNode));
if (node == NULL) {
fprintf(stderr, "enLinkQueue new_node malloc failed!\n");
return -1;
}
//入队相关代码
node->data = e;
node->next = NULL;
if (queue->rear) //队列中元素不为空时
{
queue->rear->next = node;
queue->rear = node;
}
else //当队列中元素为空时
{
queue->rear = queue->front = node;
}
//增加链式队列中节点数量
queue->cnt++;
return 0;
}
4.出队
c
int deLinkQueue(LinkQueue* queue, Element* e) //用e返回队头元素
{
//判断队列是否为空
if (queue->front == NULL)
{
fprintf(stderr, "\tqueue empty!\n");
return -1;
}
//通过指针修改外部实参 带出队首元素
*e = queue->front->data;
//出队相关代码
QueNode *tmp = queue->front;
queue->front = tmp->next;
free(tmp);
//减少队列中节点数量
queue->cnt--;
if (queue->front == NULL)
{ // 队列中已经没有元素
queue->rear = NULL; //尾指针置空
}
return 0;
}
测试案例
main函数
c
void test04()
{
//创建链式队列
LinkQueue* queue = creatLinkkQueue("jj");
if (queue == NULL) {
return;
}
//循环入队5个元素
for (int i = 0; i < 5; i++)
{
enLinkQueue(queue, i + 619);
}
Element x1;
printf("%s Queue %d show:", queue->name,queue->cnt);
//出队 队列中所有元素
while (deLinkQueue(queue, &x1) != -1)
{
printf("\t%d", x1);
}
printf("\n");
//释放该队列
releaseLinkQueue(queue);
}
int main()
{
test04();
return 0;
}
输出结果
c
jj Queue 5 show: 619 620 621 622 623 queue empty!
queue have 0 node!
嘻嘻嘻嘻 队列部分到此结束😆😆
(有错误欢迎指出) (疑问也是)❤️❤️😍😍💖💖
至此 队列小节结束 持续更新中... ...