一、特性
1、概念
队列是只允许在两端进行插入和删除操作的线性表,在队尾插入,在队头删除,插入的一端被称为“队尾”,删除的一端被称为“队头”。 队列包括顺序队列(循环队列)、链式队列。
结构:先进先出FIFO
操作:创建、入列、出列、判空和满、清空
注意:为了避免假溢出问题,即队列前面还有空闲,但是队尾已经出现越界,所以在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进,需要引入循环队列。
循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列。
- 循环队列
逻辑结构:线性结构
存储结构:顺序存储
操作:创建、入列、出列、判空和判满、清空
循环队列操作
队列结构体:
代码实现:
创建空队列:
入列:
循环队列判满需要浪费一个空间来实现
出列:
循环队列结构体
#include<stdio.h>
#include<stdlib.h>
#define N 6
typedef int datatype;
typedef struct sequeue
{
datatype data[N];//循环队列存放数据的数组。
int front;//队头,出数据的一端。
int rear;//队尾,存数据的一端。
}sequeue_t,* sequeue_list_t;
1)创建一个空队列
//创建一个空队列
sequeue_t CreatSequeue()
{
sequeue_list_t p=(sequeue_list_t)malloc(sizeof(sequeue_t));
if(NULL==p)
{
perror("空间开辟失败\n");
return NULL;
}
//初始化
p->front=0;//使用的时候是数组的下标,表示队头,用来出队得那一端
p->rear=0;//使用的时候是数组的下标, 表示队尾,用来入队的那一端
return p;
}
2)判空
//判空
int IsFellSequeue(sequeue_list_t p)
{
return p->front==(p->rear+1)%N;
}
3)判满
//判断队列是否为满
int isFullSequeue(sequeue_t *p)
{
//思想上,舍去数组上的一个存储位置,用于判断队列是否为满
//先判断rear的下一个位置是否等于front
return p->front == (p->rear + 1) % N;
}
4)入列
//入列
int InSequeue(sequeue_list_t p,datatype data)
{
if(IsFellSequeue(p)) //1.容错判断,入列前判断是否为满
{
printf("队列已满\n");
return -1;
}
p->data[p->rear]=data;//2.将数据如列,存到rear表示的那个空间。
p->rear=(p->rear+1)%N;//3.将rear移动到下一个位置,这里不能单纯的+1了,而是通过取于让下标循环起来。
return 0;
}
5)出列
//出列
int OutSequeue(sequeue_list_t p)
{
if(IsVoidSequeue(p))
{
printf("顺序列为空\n");
}
datatype out=p->data[p->front];
p->front=(p->front+1)%N;
printf("%d\n",out);
printf("头的位置:%d,尾的位置:%d\n",p->front,p->rear);
return out;
}
6)遍历输出
//遍历输出
void Show(sequeue_list_t p)
{
if(IsVoidSequeue(p))
{
printf("顺序列为空\n");
}
int i=p->front;
while(i!=p->rear)
{
printf("%d ",p->data[i]);
i=(i+1)%N;
}
puts(" ");
}
7)求顺序队列长度
//求顺序队列长度
int LengthSequeue(sequeue_list_t p)
{
if(IsVoidSequeue(p))
{
printf("顺序列为空\n");
}
if(p->front<=p->rear)
{
printf("%d\n",(p->rear)-(p->front));
return (p->rear)-(p->front);
}
else
{
printf("%d\n",(p->rear)-(p->front)+N);
return p->rear-p->front+N;
}
}
8)清空
//清空
int ClearSequeue(sequeue_list_t p)
{
if(IsVoidSequeue(p))
{
printf("顺序列为空\n");
}
while(p->data[p->front]!=0)
{
OutSequeue(p);
}
// p->front=p->rear;
return 0;
}
综合代码
#include<stdio.h>
#include<stdlib.h>
#define N 6
typedef int datatype;
typedef struct sequeue
{
datatype data[N];//循环队列存放数据的数组。
int front;//队头,出数据的一端。
int rear;//队尾,存数据的一端。
}sequeue_t,* sequeue_list_t;
//创建一个空队列
sequeue_list_t CreatSequeue()
{
sequeue_list_t p=(sequeue_list_t)malloc(sizeof(sequeue_t));
if(NULL==p)
{
perror("空间开辟失败\n");
return NULL;
}
//初始化
p->front=0;
p->rear=0;
return p;
}
//判满
int IsFellSequeue(sequeue_list_t p)
{
return p->front==(p->rear+1)%N;
}
//入列
int InSequeue(sequeue_list_t p,datatype data)
{
if(IsFellSequeue(p)) //1.容错判断,入列前判断是否为满
{
printf("队列已满\n");
return -1;
}
p->data[p->rear]=data;//2.将数据如列,存到rear表示的那个空间。
p->rear=(p->rear+1)%N;//3.将rear移动到下一个位置,这里不能单纯的+1了,而是通过取于让下标循环起来。
return 0;
}
//判空
int IsVoidSequeue(sequeue_list_t p)
{
return p->front==p->rear;
}
//出列
int OutSequeue(sequeue_list_t p)
{
if(IsVoidSequeue(p))
{
printf("顺序列为空\n");
}
datatype out=p->data[p->front];
p->front=(p->front+1)%N;
printf("%d\n",out);
printf("头的位置:%d,尾的位置:%d\n",p->front,p->rear);
return out;
}
//遍历输出
void Show(sequeue_list_t p)
{
if(IsVoidSequeue(p))
{
printf("顺序列为空\n");
}
int i=p->front;
while(i!=p->rear)
{
printf("%d ",p->data[i]);
i=(i+1)%N;
}
puts(" ");
}
//求顺序队列长度
int LengthSequeue(sequeue_list_t p)
{
if(IsVoidSequeue(p))
{
printf("顺序列为空\n");
}
if(p->front<=p->rear)
{
printf("%d\n",(p->rear)-(p->front));
return (p->rear)-(p->front);
}
else
{
printf("%d\n",(p->rear)-(p->front)+N);
return p->rear-p->front+N;
}
}
//清空
int ClearSequeue(sequeue_list_t p)
{
if(IsVoidSequeue(p))
{
printf("顺序列为空\n");
}
while(p->data[p->front]!=0)
{
OutSequeue(p);
}
// p->front=p->rear;
return 0;
}
int main(int argc, char const *argv[])
{
sequeue_list_t p=CreatSequeue();
int num;
int push[32];
char in;
while(1)
{
printf("请输入命令=");
scanf("%c",&in);//回收一个垃圾字符
getchar();
switch(in)
{
case 'A':
printf("请输入要插入的元素个数:");
scanf("%d",&num);
getchar();
printf("请输入要插入的元素内容:");
for(int i=0;i<num;i++)
{
scanf("%d",&push[i]);
getchar();
}
for(int i=0;i<num;i++)
{
InSequeue(p,push[i]);
}break;
case 'a':
printf("请输入要插入的元素内容:");
scanf("%d",&num);
getchar();
InSequeue(p,num);break;
case 'b':
Show(p);break;
case 'c'://清空栈
ClearSequeue(p);break;
case 'd':
LengthSequeue(p);break;
case 'e':
//出栈
OutSequeue(p);break;
// case 'f':
// ShowForlinkstack(p);break;
// case 'q':
// break;break;
}
}
return 0;
}
循环队列,如果数组的元素个数为N,那么队列中最多能够存储的数据数的多少?N-1
为什么呢?
答:rear 后面 队尾,在插入的时候,插入之前需要先判断 rear+1,也就是他的下一个为位置是否 等于 front 来判断队列是否为满,会造成浪费一个存储位置。