用循环数组来,描述一个队列。
要搞清楚两件事:
- 何时为空
- 何时为满
头文件
#ifndef _HEAD_H
#define _HEAD_H
#define MINSIZE 5
typedef int ElementType;
typedef struct node* Queue;
typedef struct node{
ElementType* arrayQueue;
int front; //队头
int rear; //队尾
int length; //队列长度
}Node;
Queue CreateQueue(void);
void Display(Queue q);
void MakeEmpty(Queue q);
int IsEmpty(Queue q);
int IsFull(Queue q);
void Free(Queue q);
int LengthQueue(Queue q);
void AddElementType(Queue q, ElementType x);
ElementType DeleteElementType(Queue q);
void clean(void);
#endif
front表示队头的第一个元素,rear表示队尾的第一个空位置。
当队为空时,front和rear相等。(为什么不是同时等于0,因为front在一个元素出队后就会后移,不一定就永远在0位置。)
因为队列在删除时,会删除数组下标最小的那个元素,那个位置会空出来。当队尾超过最大下标时,再加入元素就可以用再用前面空出来的位置,这样就成了一个循环数组。
那什么时候是队满呢?。
有两种判断方式,
- 当这个数组满了,队就满了。这时用一个flag来标志。当front = rear且flag = 1时是满,当front = rear且flag = 0时是空。
- 当整个数组只有一个空位时就满,这样避免与队空相同。也就是rear后面就是front。
讨论第二种判断方式
这个图可以用rear + 1 = front来表示。那是否就可以用rear + 1 = front来表示队满呢?
看下面这个图:
显然这种情况也是队满,但是却不能用rear + 1 = front来表示了。
怎么办?有没有一种通用的表达式?
有,只要超过后对数组长度取余即可。
判断队满:
(rear + 1) % arraylength = front
队长也是用这种方法。
队长=
((rear - front) + arraylength)% arraylength
这种队列在此还有很多种细节来考,比如rear表示的是最后一个元素,而不是后一个空位。空两位时队满等等。
重点是搞清楚,判断队空的条件与判断队满的条件。
操作集
#include"head.h"
#include <stdlib.h>
#include <stdio.h>
Queue CreateQueue(void)
{
printf("输入队列最大容量:");
int size;
while(scanf("%d", &size))
{
if (size >= MINSIZE)
break;
else
printf("请输入一个不小于%d的数:", MINSIZE);
}
Queue q = (Queue)malloc(sizeof(Node));
if (q == NULL)
{
printf("out of space!\n");
exit(EXIT_FAILURE);
}
q->arrayQueue = (ElementType*)malloc(size * sizeof(ElementType));
if (q->arrayQueue == NULL)
{
printf("out of space!\n");
exit(EXIT_FAILURE);
}
q->front = 0;
q->rear = 0;
q->length = size;
return q;
}
void MakeEmpty(Queue q)
{
q->front == q->rear == 0;
}
int IsEmpty(Queue q)
{
return q->front == q->rear;//队空
}
int IsFull(Queue q)
{
return (q->rear + 1) % (q->length) == q->front;//队满
}
int LengthQueue(Queue q)
{
return ((q->rear - q->front) + q->length) % (q->length); //队长
}
void Display(Queue q)
{
if (q == NULL)
{
printf("the point is NULL\n");
return ;
}
printf("队列长度为%d:", LengthQueue(q));
if (IsEmpty(q))
{
printf("空队列\n");
return ;
}
else
{
for (int i = q->front; i < q->rear; i++)
{
printf("%d", q->arrayQueue[i]);
if (i != q->rear - 1)
printf("<-");
}
printf("\n");
}
}
void Free(Queue q)
{
free(q->arrayQueue);
q->arrayQueue = NULL;
free(q);
}
void AddElementType(Queue q, ElementType x)
{
if (q == NULL)
{
printf("the point is NULL\n");
exit(EXIT_FAILURE);
}
if (IsFull(q))
{
printf("不能加入刚才这个元素,因为队列已满\n");
return ;
}
q->arrayQueue[q->rear] = x;
q->rear = (q->rear + 1) % (q->length);
}
ElementType DeleteElementType(Queue q)
{
if (q == NULL)
{
printf("the point is NULL\n");
exit(EXIT_FAILURE);
}
if (IsEmpty(q))
{
printf("队列为空\n");
return -1;
}
ElementType data = q->arrayQueue[q->front];
q->front = (q->front + 1) % (q->length);
return data;
}
void clean(void)
{
while(getchar() != '\n')
continue;
}
主函数
#include <stdio.h>
#include "head.h"
int main(void)
{
printf("创建\n");
printf("*********************************************\n");
Queue q = CreateQueue();
Display(q);
printf("入队\n");
printf("*********************************************\n");
ElementType data;
printf("请输入要入队的元素(非数字结束):");
while(scanf("%d", &data))
{
printf("请输入要入队的元素(非数字结束):");
AddElementType(q, data);
}
Display(q);
printf("出队\n");
printf("*********************************************\n");
data = DeleteElementType(q);
if (data != -1)
printf("删除的元素:%d\n", data);
Display(q);
printf("释放,指针置空\n");
printf("*********************************************\n");
Free(q);
q = NULL;
Display(q);
return 0;
}