队列
先进先出,后进后出的思想
允许在一端插入数据,允许在另外一端删除数据
队尾rear:允许插入数据的一端
对头front:允许删除数据的一端
实现这个队列的时候有两种方式
顺序队列:
使用的就是数组实现的
我们实现这个顺序队列的时候有一点点小问题
我们不管是入队还是出队,rear 和 front实际上是不会减小的
他们是一直在增大,而我们的内存又是有限的
这个时候就会出现一种可能,你的队列里面的元素个数没有到上限
但是rear这一端可能会到达极限,达到它的最大的下标位置
这个时候我们叫队列的假溢出
元素个数到达最大值之后你还要往里面加入元素,这个东西我们叫真溢出
为了防止假溢出,我们一般做的顺序队列都是循环队列
当我们的rear front达到最大值之后,发现你的元素
个数还没有到上限,我们让这两个玩意儿回去,继续入队
这样才能防止假溢出
栈是没有假溢出的
链式队列:
使用的就是单链表
队列也需要实现如下操作
1 初始化一个队列 QueueInit
2 销毁队列 QueueDestory
3 清空队列 QueueClear
4 判断这个队列是否为空 QueueIsEmpty
5 返回队列里面多少个元素 QueueGetLength
6 返回对头元素,不出队 QueueGetFront
7 入队 InQueue
8 出队 OutQueue
typedef int ElemType;
#define QueueErro INT32_MIN
#define QueueMax 1024
typedef struct QueueNode
{
ElemType data;
struct QueueNode* next;
}Node;
typedef struct QueueHead
{
struct QueueNode* front; //队头
struct QueueNode* rear; //队尾
int num;
int MaxNum;
}Head;
实现队列出队入队
//初始化队列
Head* QueueInit(int MaxNum)
{
if (MaxNum > 1024 || MaxNum <= 0)
{
MaxNum == 1024;
}
Head* q = malloc(sizeof(Head));
q->front = q->rear = NULL;
q->num = 0;
q->MaxNum = MaxNum;
return q;
}
//建立一个队列节点
//初始化节点
static Node* QueueCreateNode(const ElemType data)
{
Node* pnew = malloc(sizeof(Node));
pnew->data = data;
pnew->next = NULL;
return pnew;
}
//判断为空
bool QueueIsEmpty(Head* q)
{
if (!q || QueueGetLength(q) == 0)
{
return true;
}
else
{
return false;
}
}
//队内多少个元素
int QueueGetLength(Head* q)
{
if (!q)
{
return -1;
}
return q->num;
}
//返回队头元素,不出队
ElemType QueueReturn(Head* q)
{
if (!q || !q->front)
{
return QueueErro;
}
else
{
return q->front->data;
}
}
//入队
void InQueue(Head * q,ElemType data)
{
if (!q)
{
printf("队列不存在,不能入队\n");
return;
}
if (QueueGetLength(q) >= q->MaxNum)
{
printf("队列满了,不能入队\n");
return;
}
Node* pnew = QueueCreateNode(data);
//队列中没有元素
if (QueueIsEmpty(q))
{
q->front = q->rear = pnew;
}
else
{
q->rear->next = pnew;
q->rear = pnew;
}
q->num++;
}
//出队
ElemType OutQueue(Head* q)
{
if (!q)
{
printf("队列不存在,无法出队\n");
return QueueErro;
}
if (QueueGetLength(q) == 0)
{
printf("队列没有元素,无法出队\n");
return QueueErro;
}
Node* p = q->front;
ElemType data = q->front->data;
if (QueueGetLength(q) == 1)
{
q->front = q->rear = NULL;
}
else
{
q->front = q->front->next;
p->next = NULL;
}
free(p);
q->num--;
return data;
}
队列的销毁和清空
//销毁
void QueueDestory(Head** q)
{
if (!q || !(*q))
{
return;
}
QueueClear(*q);
free(*q);
*q = NULL;
}
//清空
void QueueClear(Head* q)
{
if (!q)
{
return;
}
while (!QueueIsEmpty(q))
{
OutQueue(q);
}
}