標籤:隊列
隊列(queue)
隊列是一種先進先出(first in first out,FIFO)的線性表。它只允許在表的一端(隊尾/rear)插入元素,而在另一端(隊頭/front)刪除元素。插入操作稱為入隊或進隊,刪除操作稱為出隊或離隊。隊列如下:
1、 順序隊
隊列的順序儲存結構需要使用一個數組和兩個整型變數來實現,數組用於儲存隊列中的所有元素,兩個整型變數分別用於儲存隊頭元素和隊尾元素的下標位置,分別稱為隊頭指標和隊尾指標。
假定隊列的元素個數不超過MaxSize,所有的元素的資料類型都是ElemType,則順序隊列類型SqQueue定義如下:
typedefstruct
{
ElemType data[MaxSize];
Int front,rear;
}SqQueue;
在順序隊列*q中,隊空的條件是q->front==q->rear;隊滿的條件是q->rear==MaxSize-1;元素e入隊的操作是先將隊尾指標加1,然後將元素e放入隊尾;出隊操作是先將隊頭指標加1,然後取出隊頭處的元素;隊尾指標總是指向當前隊列中的隊尾元素,而隊頭指標總是指向當前隊列中隊頭元素的前一個位置。
順序隊的基本運算實現如下:
#include<stdio.h>#include<stdlib.h>#define MaxSize 20//隊列元素最大個數typedef char ElemType;//隊列元素類型typedef struct//順序隊{ElemType data[MaxSize];//資料元素int front;//對頭指標int rear;//隊尾指標}SqQueue;void InitQueue(SqQueue *&q)//初始化隊列{q=(SqQueue *)malloc(sizeof(SqQueue));q->front=q->rear=-1;}void DestoryQueue(SqQueue *&q)//銷毀隊列{free(q);}bool QueueEmpty(SqQueue *q)//判斷隊列是否為空白{return (q->front==q->rear);}bool QueueFull(SqQueue *q)//判斷隊列是否已滿{return (q->rear==MaxSize-1);}bool EnQueue(SqQueue *&q, ElemType e)//入隊(插入元素){if(q->rear==MaxSize-1)//隊列已滿,不能再插入return false;q->rear++;q->data[q->rear]=e;return true;}bool DeQueue(SqQueue *&q, ElemType &e)//出隊(刪除元素){if(q->front==q->rear)//隊列為空白,無法刪除return false;q->front++;e=q->data[q->front];return true;}int main(){...;return 0;}
2、 環形隊列
將數組的前端和後端串連起來,形成環形的順序表——環形隊列。
環形隊列的基本運算實現如下:
#include<stdio.h>#include<stdlib.h>#define MaxSize 10//隊列元素最大個數typedef char ElemType;//隊列元素類型typedef struct//環形隊列{ElemType data[MaxSize];//資料元素int front;//對頭指標int rear;//隊尾指標}QuType;void InitQueue(QuType *&qu)//初始化隊列{qu=(QuType *)malloc(sizeof(QuType));qu->front=qu->rear=0;}void DestoryQueue(QuType *&qu)//銷毀隊列{free(qu);}bool QueueEmpty(QuType *&qu)//判斷隊列是否為空白{return (qu->front==qu->rear);}bool QueueFull(QuType *&qu)//判斷隊列是否已滿{return (qu->front==(qu->rear+1)%MaxSize);}bool EnQueue(QuType *&qu, ElemType e)//入隊{if(qu->front==(qu->rear+1)%MaxSize)//注意!return false;qu->rear=(qu->rear+1)%MaxSize;qu->data[qu->rear]=e;return true;}bool DeQueue(QuType *&qu, ElemType &e)//出隊{if(qu->front==qu->rear)return false;qu->front=(qu->front+1)%MaxSize;e=qu->data[qu->front];return true;}int main(){...;return 0;}
3、 鏈隊
隊列的鏈式儲存結構通過由結點構成的單鏈表實現,此時只允許在單鏈表的表頭進行刪除操作和在單鏈表的表尾進行插入操作,因此需要兩個指標:隊首指標front和隊尾指標rear。用front指向隊首結點,用rear指向隊尾結點。用於儲存隊列的單鏈表成為鏈隊。
鏈隊(帶頭結點)中資料結點的類型QNode定義如下:
typedefstruct qnode
{
ElemType data;
struct qnode *next;
}QNode; //鏈隊資料結點類型定義
鏈隊結點的類型LinkQueue定義如下:
typedefstruct
{
QNode *front;
QNode *rear;
}LinkQueue; //鏈隊類型定義
鏈隊的基本運算實現如下:
#include<stdio.h>#include<stdlib.h>typedef char ElemType;typedef struct qNode{ElemType data;struct qNode *next;}QNode;//資料結點typedef struct {QNode *front;//隊頭指標QNode *rear;//隊尾指標}LinkQueue;//鏈隊結點void InitQueue(LinkQueue *&q)//初始化鏈隊{QNode *p=(QNode *)malloc(sizeof(QNode));//建立頭結點if(!p){printf("記憶體配置失敗\n");exit(1);}p->next=NULL;q=(LinkQueue *)malloc(sizeof(LinkQueue));//分配鏈隊結點空間if(!q){printf("記憶體配置失敗\n");exit(1);}q->front=q->rear=p;}void DestoryQueue(LinkQueue *&q)//銷毀鏈隊{QNode *p;while(q->front!=NULL){p=q->front;q->front=p->next;}free(p);}bool QueueEmpty(LinkQueue *q)//判斷隊列是否為空白{return (q->front->next==NULL);}void EnQueue(LinkQueue *&q, ElemType e)//入隊{QNode *p;p=(QNode *)malloc(sizeof(QNode));//建立新結點if(!p){printf("記憶體配置失敗!\n");exit(1);}p->data=e;p->next=NULL;q->rear->next=p;q->rear=p;}bool DeQueue(LinkQueue *&q, ElemType &e)//出隊{QNode *p;if(q->front->next==NULL)//隊列為空白,操作無效return false;p=q->front->next;e=p->data;q->front->next=p->next;if(p->next==NULL)//刪除最後一個結點後,將尾指標指向頭結點q->rear=q->front;free(p);return true;}int main(){...;return 0;}
幾個注意點:
1、順序隊和環形隊列的隊空條件均是q->front==q->rear;順序隊的隊滿條件是p->rear==MaxSize-1,而環形隊列的隊滿條件是q->front==(q->rear+1)%MaxSize;
2、順序隊和環形隊列初始化的不同,導致最後儲存空間上的元素不一樣。順序隊的初始化:q->front=q->rear=-1,所以元素從q->data[0]開始儲存;而環形隊列的初始化:q->front=q->rear=0,所以元素從q->data[1]開始儲存,q->data[0]空閑;
3、順序隊列滿足隊滿條件時可能是假溢出(如p->rear==MaxSize-1,此時即使出隊幾個資料仍然滿足了隊滿條件,但已經騰出了若干個空間,此時就是假溢出),而環形隊列滿足隊滿條件就是沒有多餘的儲存空間了;
4、順序隊中的元素個數是rear-front,環形隊列中的元素個數是(rear-front+MaxSize)%MaxSize;
5、鏈隊的初始化,建立頭結點的同時,為鏈隊結點分配記憶體空間;
6、出隊時,當刪除最後一個結點後,尾指標也隨之釋放,所以應該將尾指標重新賦值,指向頭結點。
2014年7月29日星期二