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

来源:互联网 发布:网络紅人思瑞 编辑:程序博客网 时间:2024/05/21 10:56

参考书籍:数据结构(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 30typedef 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);}


0 0