隊列

一、 隊列的定義 

 隊列簡稱隊,它也是一種運算受限的線性表,其限制僅允許在表的一端進行插入,而在表的另一端進行刪除。
把進行插入的一端稱做隊尾(rear),進行刪除的一端稱做隊首或隊頭(front)

向隊列中插入新元素稱爲進隊或入隊,新元素進隊後就成爲新的隊尾元素;從隊列中刪除元素稱爲出隊或離隊,元素出隊後,其後繼元素就成爲隊首元素。 

由於隊列的插入和刪除操作分別是在各自的一端進行的,每個元素必然按照進入的次序出隊,所以又把隊列稱爲先進先出表

隊列的基本運算如下:

InitQueue(&q):初始化隊列。構造一個空隊列q。
DestroyQueue(&q):銷燬隊列。釋放隊列q佔用的存儲空間。
QueueEmpty(q):判斷隊列是否爲空。若隊列q爲空,則返回真;否則返回假。
enQueue(&q,e):進隊列。將元素e進隊作爲隊尾元素。

deQueue(&q,&e):出隊列。從隊列q中出隊一個元素,並將其值賦給e。

二、隊列的順序存儲結構及其基本運算的實現

  假設隊列的元素個數最大不超過整數MaxSize,所有的元素都具有同一數據類型ElemType,則順序隊列類型SqQueue定義如下:
  typedef struct 
   {   ElemType data[MaxSize]; 
        int front,rear;//隊首和隊尾指針

   } SqQueue;

1)順序隊的四要素(初始時front=rear=-1)

隊空條件:front=rear
隊滿條件:rear=MaxSize-1
元素e進隊:rear++;data[rear]=e;

元素e出隊:front++;e=data[front];

2) 順序隊中實現隊列的基本運算

(1)初始化隊列InitQueue(q)

  構造一個空隊列q。將front和rear指針均設置成初始狀態即-1值。

void InitQueue(SqQueue *&q)
{ q=(SqQueue *)malloc (sizeof(SqQueue));
  q->front=q->rear=-1;

}

(2)銷燬隊列DestroyQueue(q)

釋放隊列q佔用的存儲空間。

void DestroyQueue(SqQueue *&q)
{
   free(q);

}

(3)判斷隊列是否爲空QueueEmpty(q)

       若隊列q滿足q->front==q->rear條件,則返回true;否則返回false。

bool QueueEmpty(SqQueue *q)
{
   return(q->front==q->rear);
}
(4)進隊列enQueue(q,e) 

       在隊列不滿的條件下,先將隊尾指針rear循環增1,然後將元素添加到該位置。

bool enQueue(SqQueue *&q,ElemType e)
{   if (q->rear==MaxSize-1) //隊滿上溢出
return false;
q->rear++;
q->data[q->rear]=e;
return true;

}

(5)出隊列deQueue(q,e)

      在隊列q不爲空的條件下,將隊首指針front循環增1,並將該位置的元素值賦給e。

bool deQueue(SqQueue *&q,ElemType &e)
{  if (q->front==q->rear) //隊空下溢出
return false;
   q->front++;
   e=q->data[q->front];
   return true;
}

3)環形隊中實現隊列的基本運算

 用rear==MaxSize-1作爲隊滿的條件有缺陷。可能隊列爲空,但仍滿足該條件。這時進隊時出現“上溢出”,這種溢出並不是真正的溢出,在data數組中存在可以存放元素的空位置,所以這是一種假溢出

爲了能夠充分地使用數組中的存儲空間,把數組的前端和後端連接起來,形成一個環形的順序表,即把存儲隊列元素的表從邏輯上看成一個環,稱爲環形隊列或循環隊列


環形隊列的四要素:

隊空條件:front==rear
隊滿條件:(rear+1)%MaxSize=front
進隊e操作:rear=(rear+1)%MaxSize; 將e放在rear處

出隊操作:front=(front+1)%MaxSize;取出front處元素e; 

(1)初始化隊列InitQueue(q)

       構造一個空隊列q。將front和rear指針均設置成初始狀態即0值。

void InitQueue(SqQueue *&q)
{   q=(SqQueue *)malloc (sizeof(SqQueue));
    q->front=q->rear=0;

}

(2)進隊列enQueue(q,e) 

        在隊列不滿的條件下,先將隊尾指針rear循環增1,然後將元素添加到該位置。

bool enQueue(SqQueue *&q,ElemType e)
{  if ((q->rear+1)%MaxSize==q->front)  //隊滿上溢出
return false;
   q->rear=(q->rear+1)%MaxSize;
   q->data[q->rear]=e;
   return true;
}
(3)出隊列deQueue(q,e)

  在隊列q不爲空的條件下,將隊首指針front循環增1,並將該位置的元素值賦給e。

bool deQueue(SqQueue *&q,ElemType &e)
{  if (q->front==q->rear) //隊空下溢出
return false;
   q->front=(q->front+1)%MaxSize;
   e=q->data[q->front];
   return true;
}
三、 隊列的鏈式存儲結構及其基本運算的實現

   鏈隊組成:
        (1)存儲隊列元素的單鏈表

        (2) 指向隊頭和隊尾指針的鏈隊頭節點    

單鏈表中數據節點類型QNode定義如下:
typedef struct qnode
{  ElemType data; //數據元素
   struct qnode *next;
} QNode;
鏈隊中頭節點類型LiQueue定義如下:
typedef struct
{  QNode *front; //指向單鏈表隊頭節點
   QNode *rear; //指向單鏈表隊尾節點

} LiQueue; 

鏈隊的4要素:

隊空條件:front=rear=NULL
隊滿條件:不考慮
進隊e操作:將包含e的節點插入到單鏈表表尾
出隊操作:刪除單鏈表首數據節點

在鏈隊存儲中,隊列的基本運算算法如下。
(1)初始化隊列InitQueue(q)

       構造一個空隊列,即只創建一個鏈隊頭節點,其front和rear域均置爲NULL,不創建數據元素節點。對應算法如下:

void InitQueue(LiQueue *&q)
{  q=(LiQueue *)malloc(sizeof(LiQueue));
   q->front=q->rear=NULL;

}


(2)銷燬隊列DestroyQueue(q)

      釋放隊列佔用的存儲空間,包括鏈隊頭節點和所有數據節點的存儲空間。對應算法如下:   

void DestroyQueue(LiQueue *&q)
{  QNode *p=q->front,*r;  //p指向隊頭數據節點
   if (p!=NULL)   //釋放數據節點佔用空間
   {  r=p->next;
while (r!=NULL)
{   free(p);
    p=r;r=p->next;
}
   }
   free(p);
   free(q);    //釋放鏈隊節點佔用空間
}

(3)判斷隊列是否爲空QueueEmpty(q)

      若鏈隊節點的rear域值爲NULL,表示隊列爲空,返回true;否則返回false。對應算法如下:     

bool QueueEmpty(LiQueue *q)
{
  return(q->rear==NULL);
}

(4) 入隊enQueue(q,e)
       創建data域爲e的數據節點*s。

   若原隊列爲空,則將鏈隊節點的兩個域均指向*s節點,否則將*s鏈到單鏈表的末尾,並讓鏈隊節點的rear域指向它。

void enQueue(LiQueue *&q,ElemType e)
{  QNode *p;
   p=(QNode *)malloc(sizeof(QNode));
   p->data=e;
   p->next=NULL;
   if (q->rear==NULL) //若鏈隊爲空,新節點是隊首節點又是隊尾節點
q->front=q->rear=p;
   else
   {  q->rear->next=p;//將*p節點鏈到隊尾,並將rear指向它
q->rear=p;
   }

}

(5)出隊deQueue(q,e)
      若原隊列不爲空,則將第一個數據節點的data域值賦給e,並刪除之。

   若出隊之前隊列中只有一個節點,則需將鏈隊節點的兩個域均置爲NULL,表示隊列已爲空。對應的算法如下:

bool deQueue(LiQueue *&q,ElemType &e)
{  QNode *t;
   if (q->rear==NULL) return false; //隊列爲空
   t=q->front;    //t指向第一個數據節點
   if (q->front==q->rear)  //隊列中只有一個節點時
q->front=q->rear=NULL;
   else    //隊列中有多個節點時
q->front=q->front->next;
   e=t->data;
   free(t);
   return true;
}


發佈了48 篇原創文章 · 獲贊 47 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章