您的位置:首页 > 其它

数据机构(10)--顺序循环队列的实现及相关操作

2016-02-21 14:56 501 查看
参考书籍:数据结构(C语言版)严蔚敏吴伟民编著清华大学出版社

1.顺序队列

顺序队列的类型定义如下:

#define maxsize 100/*队列的最大容量*/

typedef char QElemtype;

struct Queue

{ QElemtype data[maxsize ]; //队员的存储空间

int front; //队头队尾指针

int rear; //队尾指针

};

定义一个顺序队的变量: Queue Q;

队列的数据区为:Q.data[0]---Q.data[maxsize -1]

队头指针:Q.front 队尾指针:Q.rear

约定队头指针指向队头元素,队尾指针指向队尾元素后面一个位置(这样的设置是为了某些运算的方便,并不是唯一的方法)。

从下图中可以看到,随着入队出队的进行,会使整个队列整体向后移动,这样就出现了图(d)中的现象:队尾指针已经移到了最后,再有元素入队就会出现溢出,而事实上此时队中并未真的“满员”,这种现象为“假溢出”,这是由于“队尾入队头出”这种受限制的操作所造成。



解决上面的问题一个巧妙的方法就是:将顺序队列臆造成一个环状的空间,如下图,称之为循环队列

2.顺序循环队列

顺序循环队列的定义

#define MAXSIZE 30

typedef char QElemType;

typedef struct{

QElemType data[MAXSIZE];

int f;//头指针

int r;//尾指针

}SqQueue;



因为是头尾相接的循环结构,入队时的队尾指针加1操作修改为:Q.rear=(Q.rear+1) % (n0+1);

出队时的队头指针加1操作修改为:Q.front=(Q.front+1) % (n0+1);

设n0=9,图是循环队列操作示意图。



从图的循环队可以看出,在队空情况下有:front==rear,在队满情况下也有:front==rear就是说“队满”和“队空”的条件是相同的了。这显然是必须要解决的一个问题。

方法之一是附设一个存储队中元素个数的变量如num,当num==0时队空,当num==maxsize时为队满。

另一种方法是少用一个元素空间,把图(d)所示的情况就视为队满,此时的状态是队尾指针加1就会从后面赶上队头指针,这种情况下队满的条件是:(rear+1) % maxsize ==front,也能和空队区别开。

下面的循环队列及操作按第二种方法实现。

队空:front==rear

队满: (rear+1) mod maxsize ==front

队中元素个数n=(rear-front+maxsize )mod maxsize

入队:rear=(rear+1) % maxsize ;

出队:front=(front+1) % maxsize ;

3.顺序循环队列相关操作的实现

3.1顺序循环队列的定义

/*顺序循环队列:少用一个元素空间,约定以“队列头指针在队列尾指针的下一位置(环状的下一位置)上”作为队列“满”状态的标志
即,队满:Q.f == (R.r + 1)%MAXSIZE
对空:Q.f == Q.r
队长:(Q.r - Q.f + MAXSIZE)%MAXSIZE
入队时尾指针后移:Q.r = (Q.r + 1)%MAXSIZE
出队时头指针后移:Q.f = (Q.f + 1)%MAXSIZE
*/
#include<stdio.h>
#define MAXSIZE 30
typedef char QElemType;
typedef struct{
QElemType data[MAXSIZE];
int f;//头指针
int r;//尾指针
}SqQueue;

3.2初始化一个空队列

//初始化一个空队列
void initQueue(SqQueue &Q){
Q.f = Q.r = 0;
}


3.3求队列长度

//求队列长度
int getQueueLength(SqQueue Q){
return (Q.r - Q.f + MAXSIZE)%MAXSIZE;
}

3.4入队操作

//入队操作,尾指针后移
void enQueue(SqQueue &Q, QElemType e){
//先判断队列是否已满
if(Q.f == (Q.r + 1)%MAXSIZE){
printf("队列已满,入队操作失败!\n");
return;
}
Q.data[Q.r] = e;
Q.r = (Q.r + 1)%MAXSIZE;
}


3.5出队操作

//出队操作,头指针后移,e返回出队元素值
void deQueue(SqQueue &Q, QElemType &e){
//先判断队列是否为空
if(Q.f == Q.r){
printf("队列已空,出队操作失败!\n");
return;
}
e = Q.data[Q.f];
printf("元素%c出队\n", e);
Q.f = (Q.f + 1)%MAXSIZE;
}


3.6利用入队操作创建队列

//利用入队操作创建一个队列,他含有n个元素
void createQueue(SqQueue &Q, int n){
int i = 0;
printf("请输入%d个字符队列元素:\n", n);
while(i < n){
QElemType e;
scanf("%c", &e);
enQueue(Q, e);
i++;
getchar();//吃掉回车符
}
}


3.7打印队列

void printQueue(SqQueue Q){
printf("打印队列:");
int i = Q.f;
while(i%MAXSIZE != Q.r){
printf("%c ", Q.data[i]);
i++;
}
printf("\n\n");
}


4.演示

void main(){
SqQueue Q;
initQueue(Q);
createQueue(Q, 5);
printQueue(Q);

printf("执行入队操作:");
printf("请输入您要入队的字符元素:");
QElemType e;
scanf("%c", &e);
enQueue(Q, e);
printQueue(Q);

printf("执行出队操作:");
deQueue(Q, e);
printQueue(Q);

}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: