數據結構(二)線性結構之隊列

  隊列(Queue)是具有一定操作約束的線性表。與堆棧有點類似,但是插入和刪除操作:只能在一端插入,而在另一端刪除。由於是單項鍊表,所以末端無法進行刪除操作。主要操作有兩種:

  1. 數據插入:入隊列(AddQ
  2. 數據刪除:出隊列(DeleteQ

  隊列滿足先來先服務,先進先出:FIFO

抽象數據類型描述

  隊列的抽象數據類型描述如下所示:

類型名稱:隊列(Queue)

數據對象集:一個有0個或多個元素的有窮線性表。

操作集:長度爲MaxSize的隊列QQueueQ \in \text{Queue},隊列元素itemElementType\text{item} \in \text{ElementType}
1、Queue CreatQueue( int MaxSize ):生成長度爲MaxSize的空隊列;
2、int IsFullQ( Queue Q, int MaxSize ):判斷隊列Q是否已滿;
3、void AddQ( Queue Q, ElementType item ):將數據元素item插入隊列Q中;
4、int IsEmptyQ( Queue Q):判斷隊列Q是否爲空;
5、ElementType DeleteQ( Queue Q):將隊頭數據元素從隊列中刪除並返回。

  隊列的順序存儲結構通常由一個一維數組和一個記錄隊列頭元素位置的變量front以及一個記錄隊列尾元素位置的變量rear組成。

#define MaxSize <儲存數據元素的最大個數>
typedef struct {
		ElementType Data[MaxSize];
		int rear; ;
		int front;
} Queue;

  一個工作隊列入一個列表,如下圖所示:

工作隊列

  添加的時候從右邊往裏面添加,出隊的時候從左邊取出。但是這種方式容易造成內存的浪費,比如Job 1取出來之後,還有Job想加入就無法從右邊加入,會發生衝突。因此有了順環隊列:

順環隊列

  那這種方案,堆棧空和滿的判別條件是什麼?

  其實就是Tail指針和Head指針指向同一處。而這種指向同一處的情況當空和滿是一樣的。對於這種情況可以設置Size記錄數據大小加以區分;或者判斷tag是0還是1來判斷最後一次是否是刪除操作來判斷空、滿;或者直接就設置n1n-1個數組,使得整個隊列不會被放滿。

程序描述

入出隊

void AddQ( Queue *PtrQ, ElementType item)
{
if ( (PtrQ->rear+1) % MaxSize == PtrQ->front ) {
	printf(“滿");
	return
PtrQ->rear = (PtrQ->rear+1 )% MaxSize;
PtrQ->Data[PtrQ->rear] = item;
}

  上述的Frontrearl指針的移動採用“加1取餘”法,體現了順序存儲的“循環使用”。

ElementType DeleteQ ( Queue *PtrQ )
{
	if ( PtrQ->front == PtrQ->rear) {
		printf(“隊列空"); 
		return ERROR;
	} else {
		PtrQ->front = (PtrQ->front+1)% MaxSize;
		return PtrQ->Data[PtrQ->front];
	}
}

鏈式存儲

  隊列的鏈式存儲結構也可以用一個單鏈表實現。插入和刪除操作分別在鏈表的兩頭進行;隊列指針frontrear應該分別指向鏈表的哪一頭?

typedef struct Node{
	ElementType Data; 
	struct Node *Next;
}QNode;
typedef struct { /*鏈隊列結構*/
	QNode *rear; /*指向隊尾結點*/
	QNode *front; /* 指向隊頭結點*/
} LinkQueue;
LinkQueue *PtrQ ;

隊列的鏈式存儲

ElementType DeleteQ ( LinkQueue *PtrQ )
{ Qnode *FrontCell;
	ElementType FrontElem;
	if ( PtrQ->front = NULL) {
		printf(“隊列空"); return ERROR;
	}
	FrontCell = PtrQ->front;
	if( PtrQ->front == PtrQ->rear) /* 若隊列只有一個元素*/
		PtrQ->front = PtrQ->rear = NULL; /* 刪除後隊列置爲空*/
	else
		PtrQ->front = PtrQ->front->Next;
	FrontElem = FrontCell->Data;
	free( FrontCell ); /* 釋放被刪除結點空間*/
	return FrontElem;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章