1. 程式人生 > >順序佇列的基本演算法及迴圈佇列

順序佇列的基本演算法及迴圈佇列

佇列的順序儲存結構型別描述如下:

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

隊頭指標front指出實際隊頭元素所在位置的前一個位置,而隊尾指標rear指出實際隊尾元素所在的位置,初始時,佇列為空有front = rear = -1, 測試一個佇列是否為空的條件是front = rear.

順序佇列的基本演算法如下:

/* 順序佇列的基本演算法 */

#include<stdlib.h>
#include<stdio.h>
/* 佇列的順序儲存結構型別 */
#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均表示迴圈佇列為空,應說明一點的是,此時迴圈佇列的“滿”,實際上還有一個空位置(僅一個), 用來區分“上溢” 和 “下溢”,頭指標所指位置為空位置,不存元素。