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

参考书籍:数据结构(C语言版)严蔚敏吴伟民编著清华大学出版社

本文中的代码可从这里下载:https://github.com/qingyujean/data-structure

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)中的现象:队尾指针已经移到了最后,再有元素入队就会出现溢出,而事实上此时队中并未真的“满员”,这种现象为“假溢出”,这是由于“队尾入队头出”这种受限制的操作所造成。

数据机构(10)--顺序循环队列的实现及相关操作_第1张图片

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

2.顺序循环队列

顺序循环队列的定义

#define MAXSIZE 30
typedef char QElemType;
typedef struct{
QElemType data[MAXSIZE];
int f;//头指针
int r;//尾指针
}SqQueue;

数据机构(10)--顺序循环队列的实现及相关操作_第2张图片

因为是头尾相接的循环结构,入队时的队尾指针加1操作修改为:Q.rear=(Q.rear+1) % (n0+1);
出队时的队头指针加1操作修改为:Q.front=(Q.front+1) % (n0+1);
设n0=9,图是循环队列操作示意图。 

数据机构(10)--顺序循环队列的实现及相关操作_第3张图片

     从图的循环队可以看出,在队空情况下有: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
#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);

}


数据机构(10)--顺序循环队列的实现及相关操作_第4张图片

 

 

 

你可能感兴趣的:(数据结构,算法+code)