顺序队列的基本算法及循环队列

队列的顺序存储结构类型描述如下:

#define M 1000
QElemType queue[ M ];
int front, rear;

队头指针front指出实际队头元素所在位置的 前一个位置,而队尾指针rear指出实际队尾元素所在的位置,初始时,队列为空有front = rear = -1, 测试一个队列是否为空的条件是front = rear.

顺序队列的基本算法如下:

/* 顺序队列的基本算法 */

#include
#include
/* 队列的顺序存储结构类型 */
#define M 1000

/* 初始化一个队列 */
void initialQ( int *front, int *rear ){
	*front = -1;
	*rear = -1;
}

/* 测试队列是否为空 */
int isEmpty( int front, int rear ){
	return front == rear;
}

/* 取当前队头元素 */
int getQ( int queue[  ], int front, int rear, int *item ){
	if( isEmpty( front, rear ) )   /* 如队列为空,操作失败,返回0 */
		return 0;
	else{                         /* 取出对头元素,操作成功,返回1 */
		*item = queue[ front+1 ];
		return 1;
	}
}

/* 队列的插入,入队 */
int addQ( int queue[  ], int *rear, int item ){
	if( *rear == M-1 )
		return 0;       /* 队列已满,插入失败,返回0 */
	else{
		queue[ ++( *rear ) ] = item;
		return 1;         /* 队列未满,插入成功,返回1 */
	}
}

/* 队列的删除,出队 */
int deleteQ( int queue[  ], int *front, int rear, int *item ){
	if( isEmpty( *front, rear ) )   /* 队列为空,删除失败,返回0 */
		return 0;
	else{
		*item = queue[ ++( *front ) ];  /* 保存队头元素,队列头指针后移1 */
		return 1;
	}
}

void printQ( int queue[  ], int front, int rear ){
	int p;
	printf( "the elem in queue is:" );
	for( p = front + 1; p <= rear; p++ ){
		printf( "%3d", queue[ p ] );
	}
}

int main(){
	int queue[ M ];
	int front, rear;
	initialQ( &front, &rear );
	printf( "the queue is empty %d\n", isEmpty( front, rear ) );
	addQ( queue, &rear, 8 );
	addQ( queue, &rear, 14 );
	addQ( queue, &rear, 84 );
	printQ( queue, front, rear );

	int elem;
	deleteQ( queue, &front, rear, &elem );
	printf( "the deleted elem is%d\n", elem );

	getQ( queue, front, rear, &elem );
	printf( "the front elem is %d\n", elem );

	return 0;
}

为了节省存储空间,可使用循环队列,初始化循环队列时令front = rear = 0, 并且把队列设想成头尾相连的循环表,使得空间得以重复使用,在进行插入操作时,当队列的第M个位置(数组下标是M-1)被占用后,只要队列前面还有可用空间,新的元素加入队列时就可以从第1个元素(数组下标为0)开始,按照这种思路,插入算法中修改队尾指针的语句可以写成:
if(rear == M-1)
    rear = 0;
else
    rear ++;

若修改后的队尾指针满足rear = front,那么真的要产生溢出了,上述语句可用求模运算改写成:

rear = (rear + 1) % M;

在删除算法中也可以有:

front = (front + 1) % M;

循环队列的插入和删除算法如下:

/* 循环队列的插入 */
int addCQ( int queue[  ], int front, int *rear, int item ){
	if( (*rear + 1)%M == front )  /* 循环队列已满,插入失败,返回0 */
		return 0;
	else{
		queue[ ++(*rear)%M ] = item;  /* 循环队列未满,插入成功,返回1 */
		return 1;
	}
}

/* 循环队列的删除 */
int deleteCQ( int queue[  ], int *front, int rear, int *item ){
	if( *front == rear )        /* 循环队列为空,删除失败,返回0 */
		return 0;
	else{
		*front = (*front + 1)%M;   /* 删除并保存头结点元素 */
		*item = queue[ *front ];
		return 1;
	}
}

只有当rear 加1 以后从“后面”赶上来并等于front是才是循环队列“满”的情况,其余情况下的front等于rear均表示循环队列为空,应说明一点的是,此时循环队列的“满”,实际上还有一个空位置(仅一个), 用来区分“上溢” 和 “下溢”,头指针所指位置为空位置,不存元素。



你可能感兴趣的:(数据结构)