概述
队列是一种只允许在表的一端(称为队尾)进行插入,而在另一端(称为队头)进行删除的线性表,是线性表的一种特例。
顺序队列是用数组结构来表示的。为了描述队列的这种结构,我们需要两个表明队头和队尾的指针,规定队头指针指向队列头结点的前一个位置,而队尾指针指向队列的尾结点。而为什么又会用到循环队列呢,因为为了防止“假上溢”对空间造成的浪费。“假上溢”是这么来的,先说“上溢”和“下溢”。下溢就是当空对时,如果再做出队操作,则会产生“下溢”。
当队满时,再做入对操作会产生“上溢”。但是,如果当前尾指针等于数组的上界,即使队列不满,再做入队操作也会引起溢出。这种现象就是“假上溢”。然而有了循环队列,我们就可以避免假上溢的问题了。但是循环队列还是有一个问题,就是判断队列与队满的情况。如果按照前面的规定,队头指针指向队列头结点的前一个位置,而队尾指针指向队列的尾结点。那么是分辨不出来队满与队空的关系的。我看书中列出了3种解决此问题的方法。不过第三种最适合,它是采用少用一个节点空间,即头指针指向的空间不使用。这样的话。当front等于rear时,队空;入队后,当尾指针加1后等于头指针,即:(rear+1)%maxsize = front.则说明这时队列已满。
下面是对循环顺序队列操作的一个整体代码:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
typedef struct node
{
int data[MAXSIZE];
int front; //存放队列头地址
int rear; //存放队列尾地址
}sequeue;
void Sequeue_SetNull(sequeue *q); //队列置空
int Sequeue_Empty(sequeue *q); //判断队列是否为空
int Sequeue_GetFront(sequeue *q); //得到队列头结点
int Sequeue_In(sequeue *q, int dat); //入对操作
int Sequeue_Out(sequeue *q); //出队操作
void ShowSequeue(sequeue *q); //输出显示队列
int main(void)
{
int num, i, dat, choice, ans;
sequeue *q;
q = (sequeue*)malloc(sizeof(sequeue));
printf("循环顺序队列的操作练习:n");
printf("输入你想创建队列的数据个数:n");
scanf("%d", &num);
if(num>MAXSIZE-1)
{
printf("队列结点数大于最大允许空间!n");
return 0;
}
Sequeue_SetNull(q);
printf("请依次输入队列数据:n");
for(i=1; i<num+1; i++) //循环输入队列结点数据
{
scanf("%d", &dat);
q->data[i] = dat;
q->rear = i;
}
while(1)
{
printf("队列操作:n");
printf("1.取队列结点n");
printf("2.入队操作n");
printf("3.出队操作n");
printf("4.输出队列n");
printf("5.退出程序n");
printf("做出选择:n");
scanf("%d", &choice);
switch(choice)
{
//取队列头结点
case 1:
dat = Sequeue_GetFront(q);
printf("头结点为:%dn", dat);
break;
//入队
case 2:
printf("输入你想入队的数据:n");
scanf("%d", &dat);
ans = Sequeue_In(q, dat);
if(ans)
printf("入队成功!n");
else
printf("入队失败!n");
break;
//出队
case 3:
ans = Sequeue_Out(q);
if(ans)
printf("出队成功!n");
else
printf("出队失败!n");
break;
//输出显示队列
case 4:
ShowSequeue(q);
break;
//退出程序
case 5:
return 0;
break;
default:
printf("选择无效!n");
break;
}
}
}
//队列置空
void Sequeue_SetNull(sequeue *q)
{
q->rear = 0; //其中数组第一个节点空间不使用(即下标为0数组元素),用作队列满与空的区别
q->front = 0;
}
//判断队列是否为空
int Sequeue_Empty(sequeue *q)
{
if(q->front == q->rear) //头结点等于尾结点即表示队列为空
return 1;
else
return 0;
}
//取得队列头结点
int Sequeue_GetFront(sequeue *q)
{
if(Sequeue_Empty(q)) //取头结点先要判断队列是否为空
{
printf("队列空!n");
return 0;
}
else
return q->data[(q->front+1) % MAXSIZE];
}
//入队
int Sequeue_In(sequeue *q, int dat)
{
if((q->rear+1)%MAXSIZE == q->front) //入队先要判断队列是否已经满了
return 0;
else
{
q->rear = (q->rear+1) % MAXSIZE; //使用求模运算
q->data[q->rear]= dat;
return 1;
}
}
//出队
int Sequeue_Out(sequeue *q)
{
if(Sequeue_Empty(q)) //出队先要判断队列是否为空
return 0;
else
{
q->front = (q->front+1) % MAXSIZE; //求模运算
return q->data[q->front];
}
}
//输出显示队列
void ShowSequeue(sequeue *q)
{
int i;
i = q->front+1;
while(i != q->rear+1)
{
printf("%d ", q->data[i]);
i++;
}
printf("n");
}
最后
以上就是典雅嚓茶为你收集整理的数据结构学习(六)——循环顺序队列的操作的全部内容,希望文章能够帮你解决数据结构学习(六)——循环顺序队列的操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复