1.队列
队列是只允许在两端进行插入和删除操作的线性表,在队尾插入,在队头插入,插入的一端被称为“队尾”,删除的一端称为“队头”,队列包括循环队列(顺序队列)、链式队列。
结构:先进先出 FIFO
操作:创建、入队、出队、判空和判满
2.顺序队列
注意:为了避免假溢出问题,即队列前面还有空闲,但是队尾已经出现越界,所以在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进,需要引入循环队列。
循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列。
1)逻辑结构:线性结构
2)存储结构:顺序存储
3)操作:创建、入列、出列、判空和判满
3.结构体
#define N 6
typedef int datatype;
typedef struct seqqueue
{
datatype data[N]; // 循环队列的数组
int last; // 存数据端 rear 后面,数组下标
int head; // 取数据端 front 前面,数组下标
} sequeue_t, *sequeue_q;
4.创建空队列
// 1.创建一个空的队列
sequeue_t *CreateEmptySequeue()
{
// 开辟结构体大小的空间
sequeue_t *p = (sequeue_t *)malloc(sizeof(sequeue_t));
if (p == NULL)
{
perror("p malloc error");
return NULL;
}
// 初始化空间
p->head = 0;
p->last = 0;
return p;
}
5.入队
步骤
(1)存入数据
(2)移动尾栈针
尾在头前一个单位就是满,因为要区分判空和判满。尾所表示元素空间无数据,所以牺牲了一个元素空间用于判满。
// 2.入列 data代表入列的数据
int InSequeue(sequeue_t *p, datatype data)
{
// 判满
if (IsFullSequeue(p))
{
perror("队列已满");
return -1;
}
// 存放数据
p->data[p->last] = data;
// 移动队尾
p->last = (p->last + 1) % N;
return 0;
}
6.出队
出队:思想是先将数据取出,然后将头往后移动一个单位
步骤:
(1)判断队列是否为空
(2)用临时变量保存要出队的数据
(3)将头栈针往后移动一位
(4)返回要出队的数据
// 5.出列
datatype OutSequeue(sequeue_t *p)
{
// 判空
if (IsEmptySequeue(p))
{
perror("队列为空");
return -1;
}
// 取数
datatype temp = p->data[p->head];
// 移动队头
p->head = (p->head + 1) % N;
printf("%d\n", temp);
return temp;
}
7.判满判空
// 3.判断队列是否为满
int IsFullSequeue(sequeue_t *p)
{
return (p->last + 1) % N == p->head;
}
// 4.判断队列是否为空
int IsEmptySequeue(sequeue_t *p)
{
return p->last == p->head;
}
8.队列长度
// 6.求队列的长度
int LengthSequeue(sequeue_t *p)
{
int length = 0;
length = ((p->last + N) - p->head) % N;
printf("队列长度为:%d\n", length);
return length;
}