目录
目录
队列概念:
QUEUENode(队列的翻译)
队列:只允许在队里的一端插入和删除
FIFO:(first In first Out)
入队列的一端叫做队尾(也就是插入数据)
出队列的一端叫做队头(也就是删除数据)
由于队列的特殊插入和删除结构,即不论如何,出队列的数据总是连续的
队列可以使用数组或者是链表实现
数组实现:对头在数组初始位置开始,队尾在数组末尾
入队列比较简单,只需要对数组长度+1,加入数据即可
但是对于出队列来说,需要后面所有的数据往前挪动一个位置,效率比较低
也有人可能会这样的方式描述出队列:
即直接将头的索引向后移动给一个位置,但是这会导致一个问题,即如果队列满了,那么前面的空间要不要?这是个问题
链表实现:
就是简单的单链表,头就是对头,尾就是队尾
入队列就是尾插,出队列就是头删
我们在书写代码时,脑海种有清晰的逻辑结构,那么在书写代码时,就能很好的对照相应功能进行实现。所以,要学会画图!
以下是队列的基本操作:
//定义队列节点
typedef struct QueueNode{
QDateType date;
struct QueueNode* next;
}QNode;
//由于队列有两个指针,可以在一起定义比较方便
typedef struct Queue{
struct QNode* head;
struct QNode* tail;
}Queue;
入队列:
入队列很简单,两种情况:
1、队列为空:
pead = pq->tail = newNode;
2、队列不为空,就是尾插:
pq->tail->natx = newNode;
pq->tail = newNode;
出队列:
很简单,就是头删
QNode* newHead = pq->head->next;
free(head);//释放之后,更新对头为newHeaad
pq->head = newHead;
//但是这存在一个问题,当队列只有一个时,释放完后,head会被赋予新值NULL
但是tail没动,但是其指向的空间已经free,此时tail就是野指针。
变成野指针之后,例如入队列,访问到pq->tail->next就是非法访问
画图,一目了然
所以,需要情况判断:
if(pq->head->next ==NULL){
free(pq->head);
pq->head=pq->tail = NULL;
}
取出对头:
取出队尾:
简单的示例:
原码:
头文件
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int QDataType;
// 链式结构:表示队列
typedef struct QListNode
{
struct QListNode* next;
QDataType data;
}QNode;
// 队列的结构
typedef struct Queue
{
QNode* front;//头
QNode* rear;//尾
int size;
}Queue;
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);
实现文件
#include"queue.h"
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
// 初始化队列
void QueueInit(Queue* q)
{
q->front = q->rear = NULL;
q->size = 0;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
if ( q->front == NULL)
{
QNode* temp = (QNode*)malloc(sizeof(QNode));
if (temp == NULL)
{
perror("malloc fail!\n");
exit(-1);
}
temp->data = data;
temp->next = NULL;
q->front = q->rear = temp;
q->size++;
}
else
{
QNode* temp = (QNode*)malloc(sizeof(QNode));
if (temp == NULL)
{
perror("malloc fail!\n");
exit(-1);
}
temp->data = data;
temp->next = NULL;
q->rear->next = temp;
q->rear = temp;
q->size++;
}
}
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
if (q->front == NULL)
{
return;
}
QNode* second = q->front->next;
free(q->front);
q->front = second;
q->size--;
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
if(q->rear == NULL)
{
return;
}
return q->front->data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
if (q->rear == NULL)
{
return;
}
return q->rear->data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
assert(q);
if (q->size == 0)
{
return 1;
}
else
{
return 0;
}
}
// 销毁队列
void QueueDestroy(Queue* q)
{
assert(q);
if (q->rear == NULL)
{
return;
}
QNode* cur = q->front;
while (q->size--)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
printf("销毁成功!\n");
}
测试文件
#include"queue.h"
int main()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
QueuePop(&q);
QueuePop(&q);
QueuePop(&q);
QueuePop(&q);
//printf("尾数据%d \n",q.rear->data);
//printf("头数据%d \n",q.front->data);
//printf("队列长度%d \n",q.size);
获取头部元素
//printf("头部元素%d\n", QueueFront(&q));
获取队尾元素
//printf("队尾元素%d\n", QueueBack(&q));
有效数据
//printf("有效个数%d\n",QueueSize(&q));
//判空
printf("判空%d\n", QueueEmpty(&q));
QueueDestroy(&q);
return 0;
}