队列有两种表示方式,我们先看顺序表示:
代码中的rear(尾指针)与front(头指针)都是int 型的,它的作用就是做数组下标,我们习惯称它为指针,这里应该注意它不是指针类型。头指针始终指向队列头元素,尾指针始终指向队尾元素的下一个位置。
由于增加元素rear加一,删除元素front也加一,没错都是加一。就像一排10个座位,一开始只有前面三个座位有人,但我们的规则是:只能前面的同学离开,后来的同学只能坐后面。这样的话过了一会儿会发现同学们都坐在后面,而前面的座位没人坐,这就尴尬了——明明前面有位子却不能坐,班长说已经满了,再坐后面就没座位了(溢出)。我们肯定会质疑这个规则有毛病,但是班长说把10个座位围起来形成一个圆圈,第10号座位后面跟着第1号。哎!这个办法不错,既没有违背规则,又没有浪费位子。这就可以用“模”运算解决循环问题,即满了10我们就让他变为0,其他是多少就是多少。当增加一个元素时rear=(rear+1)%10,(注意数组下标0开始,扭转思维)。
下面我们来思考一个问题:
【1】 当一个人都没有的时候,front==rear;当全部坐满的时候 rear==front;由此可见,循环队列不能以头尾指针是否相同来判别队列是否为空。这里我们采用空出一个位置的方法来标记是否队满:
记住下面两点(很重要):
队空的条件:front==rear;
队满的条件:(rear+1)% MAXSIZE==front;
接下来还是看代码实现来的爽快:
#include<stdio.h>
#include<malloc.h>
#define OK 1
#define ERROR 0
#define MAXSIZE 20
typedef struct
{
int data;
}MyType;
typedef struct
{
MyType *base;
//注意这两个标记不是指针类型,属于数组下标。但我们习惯叫它指针;
int front;
int rear;
}SqQueue;
//---------------初始化队列----------------
int InitQueue(SqQueue & Q)
{
//构造一个空队列
Q.base=new MyType[MAXSIZE];
if(Q.base==NULL)
return ERROR;
Q.front=Q.rear=0;
return OK;
}
//--------------求队列的长度----------------
int QueueLength(SqQueue Q)
{
//因为是循环队列,所以rear可以比front小,一减就是负数,其绝对值也就是空位置的大小
//MAXSIZE减去空位置就是长度
return (MAXSIZE+Q.rear-Q.front)%MAXSIZE;
}
//--------------入队操作---------------
int EnQueue(SqQueue &Q,MyType e)
{
//先判断满了没
if((Q.rear+1)%MAXSIZE==Q.front)
return ERROR;
Q.base[Q.rear].data=e.data;
Q.rear=(Q.rear+1)%MAXSIZE;
return OK;
}
//-------------出队操作-----------------
int DeQueue(SqQueue &Q,MyType &e)
{
//先判断是不是空队列
if(Q.front==Q.rear)
return ERROR;
e.data=Q.base[Q.front].data;
Q.front=(Q.front+1)%MAXSIZE;
return OK;
}
//--------------取循环队列对头元素----------
MyType GetHead(SqQueue Q)
{
//不是空就这样干
if(Q.front!=Q.rear)
return Q.base[Q.front];
}
//-------------打印出来看看-------------
void Print(SqQueue Q)
{
int i;
for(i=Q.front;i<Q.rear;i++)
{
printf("第%d个位置是:%d\n",i+1,Q.base[i].data);
}
}
//--------------输入数据---------------
void Scanf(SqQueue &Q,int n)
{
int i,data;
MyType datatype;
for(i=0;i<n;i++)
{
printf("请输入第%d个数:",i+1);
scanf("%d",&datatype.data);
EnQueue(Q,datatype);
}
printf("\n\n");
}
int main()
{
MyType mydata;
SqQueue Q;
InitQueue(Q);
Scanf(Q,4);
Print(Q);
printf("\n队头的元素是:%d ",GetHead(Q));
DeQueue(Q,mydata);
printf("\n出队的元素是:%d",mydata.data);
printf("\n出队后的队列是这样的:\n");
Print(Q);
printf("重新入队后的队列是:\n");
EnQueue(Q,mydata);
Print(Q);
return 0;
}
运行结果如下: