队列也是一种运算受限的线性表。
一、队列的定义与基本运算
1、队列的定义
(1)队列的定义
假设有一个队列Q=(a1…an),队列中元素按(a1…an)的次序入队后,入队的第一个元素a1为队头元素,最后一个元素an为队尾元素,队列的操作是按先进先出的原则进行的,这种先进先出的规则应用在数据结构中称为队列,队列又称为先进先出的线性表。
(2)队列的特性
- 队列的主要特性就是“先进先出”。
- 队列也是一种特殊的线性表。插入操作限定在线性表的一端进行,删除操作限定在线性表的另一端进行。
(3)几个术语 - 入队和出队。队列插入操作又称为入队,删除操作又称为出队
- 队头和队尾。允许进行插入的一端为队尾,允许进行删除的一端称为队头
- 队头元素和队尾元素。处于队头位置的数据元素称为队头元素,处于队尾的位置的数据元素称为队尾元素。
- 空队,不含任何数据元素的队列称为空队
2、队列的基本操作
(1)初始化队列
初始化条件:队列不存在。
操作结果:构造一个空队列
(2)判断队列是否为空
初始化条件:队列存在。
操作结果:队列为空返回0,不为空返回1。
(3)入队
初始化条件:队列存在。
操作结果:将数据元素插入到队尾
(4)出队
初始化条件:队列存在且不为空。
操作结果:将队头数据赋值给“X”,然后删除
(5)取队头元素
初始化条件:队列存在。
操作结果:将队头数据赋值给“X”,然后输出
(6)显示队列元素
初始化条件:队列存在且不为空。
操作结果:将队列元素按先进先出原则输出
二、队列的存储实现及运算实现
1、顺序队列
(1)顺序队列的定义
队列的顺序存储结构称为顺序队列。类似于顺序表的定义,顺序队列用了一个一位数组和两个分别指向队头和队尾元素的变量。
(2)顺序队列的定义
typedef int Datatype;
typedef struct Circularqueue{
Datatype Data[100];//队列的大小
int front;//记录头元素位置的变量
int rear; //记录尾元素位置的变量
}Circularqueue;
- 顺序队列有一个致命的缺点,就是当rear=100-1时,再加入新的元素,数组越界导致程序发生BUG错误。如果队列为空或有剩余存储单元的“假溢出”,就无法解决了。为了解决以上问题必须使用循环顺序队
2、循环队列
(1)循环队列就是将顺序队列的首尾相连接。形成一个“环形”,事实上循环队列依然是顺序队列,只是逻辑上不同。循环队列最大空间为100,数组下标为0~99之间,队头与队尾指针指向同一个位置为空队,非空时队中队头指针front指向队列中队头元素的前一个位置,队尾rear指向队列的队尾元素位置。
假设队列开辟的数组单元数为100,它们的数组下标在0~99之间,若使队头或队尾增加1,可以利用取摸运算及取余。
入队时尾指针增加1:
rear=(rear+1)%100;
出队时队头指针加1:
front=(front+1)%100;
-循环队列解决了假溢出的问题,但是有出现了一个新问题,队满不在是rear=100-1而是front==rear和队空条件相同。解决这一问题有三种解决方案,但是我觉得最方便的还是损失一个单元不用,当循环队列中元素的个数为100-1时就认为队满。及判断队满的条件为:
(rear+1)%100==front;
(2)循环队列的基本操作实现
- 初始化:
void InitCircularqueue(Circularqueue *queue){//初始化队列
queue->front=queue->rear=0; //头元素与尾元素等于0
if(queue->front==queue->rear){
printf("Circular queue created successfully。");
}else{
printf("Circular queue creation failed!");
exit(1);
}
}
- 判断是否为空:
int Judge(Circularqueue *queue){//判断队空
if(queue->front==queue->rear){
return 1;
}else{
return 0;
}
}
- 判断队满
int Theteamisfull(Circularqueue *queue){//判断队满
if((queue->rear+1)%100==queue->front){//利用取余运算判断是否相等
return 0;
}else{
return 1;
}
}
- 输出队中元素
void Displayelements(Circularqueue *queue){//输出队中元素
int i=queue->front;
if(Judge(queue)==1){
printf("Circular queue is empty, no element\n");
}else{
printf("\nThe elements in the circular queue are:");
while(i!=queue->rear){
printf("%5d",queue->Data[i+1]);
i++;
}
}
}
- 入队操作
void Jointheteam(Circularqueue *queue){//入队操作
char p[50];
int k,i;
k=i=0;
static char Start[]="Start";
static char End[]="End";
if(Theteamisfull(queue)==0){
printf("Circular queue is full, cannot operate!");
k++;
}else{
printf("Enter “Start” to start, enter “End”to end the team:");
gets(p);
while(strcmp(p,Start)!=0){
if(strcmp(p,End)==0){
printf("You didn't join the team!");
i++;
break;
}
printf("\nInput error, please re-enter:");
memset(p,0,sizeof p);
gets(p);
}
if(strcmp(p,Start)==0){
printf("\nPlease enter the entry element:");
memset(p,0,sizeof p);
gets(p);
}
while(strcmp(p,End)!=0){
queue->rear=(queue->rear+1)%100;
queue->Data[queue->rear]=atoi(p);
printf("\nPlease enter the entry element:");
memset(p,0,sizeof p);
gets(p);
i++;
continue;
}
}
if(k+i==i&&i==1){
printf("Failed to join the team!");
if(k==1){
printf("The team is full!");
}
}else{
Displayelements(queue);
}
}
- 出队操作
void Getoutoftheteam(Circularqueue *queue){//出队操作
char p[50];
int k,i,x,l;
k=i=0;
static char Start[]="Start";
static char End[]="End";
if(Judge(queue)==1){
printf("Circular queue is empty, no element\n");
k++;
}else{
printf("Enter “Start” to start the team, enter “End” to end:");
gets(p);
while(strcmp(p,Start)!=0){
if(strcmp(p,End)==0){
printf("You are not out of the team!");
exit(1);
}
printf("\nInput error, please re-enter:");
memset(p,0,sizeof p);
gets(p);
}
if(strcmp(p,Start)==0){
printf("\nPlease input the element of out of team:");
memset(p,0,sizeof p);
gets(p);
}
l=queue->front;
while(strcmp(p,End)!=0){
x=(l+1)%100;
if(queue->Data[x]==atoi(p)){
queue->front=(queue->front+1)%100;
x=queue->Data[queue->front];
printf("\nPlease input the element of out of team:");
memset(p,0,sizeof p);
gets(p);
l++;
i++;
}else{
printf("It doesn't meet the rules! Please re-enter:");
memset(p,0,sizeof p);
gets(p);
}
continue;
}
}
if(k+i==i&&i==0){
printf("Failed to get out of the team!");
}else{
Displayelements(queue);
}
}
- 显示队头元素
void Lineheadelement(Circularqueue *queue){//显示队头元素
int x;
if(Judge(queue)==1){
printf("The team is empty! Unable to take the top operation!");
}else{
printf("The line head elements are:");
x=queue->Data[(queue->front+1)%100];
printf("%5d",x);
}
}
3、链队
(1)用链式存储结构实现的队列称为链队,一个链队列需要一哥队头指针和一个队尾指针才能唯一确定,队列中元素的结构和前面单链表的结点的结构一样。
(2)链队的类型定义
typedef int Data;
typedef struct Chainteam{
Data data;//数据域
struct Chainteam *next;//指针域
}Chainteam;
typedef struct{
Chainteam *front ,*rear;//头,尾指针
}LinkQueue;
(3)链队的基本操作与实现
- 初始化队列操作
LinkQueue *Initializethechain(){
LinkQueue *Team;
Chainteam *P;
Team=(LinkQueue *)malloc(sizeof(LinkQueue));
P=(Chainteam *)malloc(sizeof(Chainteam));
Team->front=P;
Team->rear=P;
if(Team->front==Team->rear){
printf("Initialize the chain team successfully.");
}else{
printf("Initialization chain failed! Please check and try again.");
}
return Team;
}
- 判断是否为空
int JudgmentChain(LinkQueue *Team){
if(Team->front==Team->rear){
return 0;
}else{
return 1;
}
}
- 入队
void Jointhechainteam(LinkQueue *Team){
int j;
j=0;
Chainteam *p;
char q[50];
static char Start[]="Start";
static char End[]="End";
printf("Enter “Start” out of the chain, enter “End”to end:");
gets(q);
while(strcmp(q,Start)!=0){
if(strcmp(q,End)==0){
printf("\nYou didn't get out of the team!");
break;
}
printf("\nInput error, please enter “Start”to start joining the queue:");
memset(q,0,sizeof q);
gets(q);
}
if(strcmp(q,Start)==0){
printf("\nEnter the queue element:");
memset(q,0,sizeof q);
gets(q);
}
while(strcmp(q,End)!=0){
p=(Chainteam *)malloc(sizeof(Chainteam));
p->data=atoi(q);
p->next=NULL;
Team->rear->next=p;
Team->rear=p;
printf("\nEnter the queue element:");
memset(q,0,sizeof q);
gets(q);
j++;
}
if(j!=0){
Output(Team);
}
else{
printf("Failed to join the team!");
}
}
- 出队
void Outofthechainteam(LinkQueue *Team){
int j,x;
j=0;
Chainteam *p;
char q[50];
static char Start[]="Start";
static char End[]="End";
printf("Enter “Start” out of the chain, enter “End”to end:");
gets(q);
while(strcmp(q,Start)!=0){
if(strcmp(q,End)==0){
printf("You didn't go out of the team.");
break;
}
printf("Input error, enter “Start”to start queuing:");
memset(q,0,sizeof q);
gets(q);
}
if(strcmp(q,Start)==0){
printf("Open input and outbound elements:");
memset(q,0,sizeof q);
gets(q);
}
while(strcmp(q,End)!=0){
if(Team->front->next->data==atoi(q)){
p=Team->front->next;
x=p->data;
Team->front->next=p->next;
if(p->next=NULL){
Team->rear=Team->front;
}
free(p);
printf("Open input and outbound elements:");
memset(q,0,sizeof q);
gets(q);
j++;
continue;
}
printf("Do not meet the queuing rules, please re-enter:");
memset(q,0,sizeof q);
gets(q);
}
if(j!=0){
Output(Team);
}else
{
printf("Failed to get out of the team!");
}
}
- 输出队中元素
void Output(LinkQueue *Team){
Chainteam *q=Team->front->next;
if(JudgmentChain(Team)==0){
printf("Air team! ");
}else{
printf("\nElements in the team:");
while(q!=NULL){
printf("%5d",q->data);
q=q->next;
}
}
}
- 取队头元素
void Teamleader(LinkQueue *Team){
int x;
if(JudgmentChain(Team)==0){
printf("The team is empty! No team leader!");
}else{
x=Team->front->next->data;
printf("The line head elements are:%5d",x);
}
}
- 销毁队列
void Destruction(LinkQueue *Team){
while(Team->front){
Team->rear=Team->front->next;
free(Team->front);
Team->front=Team->rear;
}
if(Team->front==NULL){
printf("Queue destroyed successfully.");
}else
{
printf("Queue destroy failed!");
}
}