顺序队列与循环队列
一、隊列的概念
???????只能在表的一端進行插入操作,只能在表的另一端進行刪除操作,這種數據結構稱為隊列。把允許插入的一端叫隊尾(rear),允許刪除的一端叫對頭(front)。
二、隊列的分類 ???????隊列本身也是一種線性表,因而和線性表一樣也有順序和鏈式存儲結構兩種存儲方式。 ???????采用順序存儲結構實現的隊列稱為順序隊列; ???????采用鏈式存儲結構實現的隊列稱為鏈隊列。
三、順序隊列 1、順序隊列的表示 ???????①順序隊列用一個向量空間(一般使用一維數組)來存放當前隊列中的元素。
②由于隊列的隊頭和隊尾的位置是變化的,設置兩個指針front和rear分別指示隊頭元素和隊尾元素在向量空間中的位置,它們的初值在隊列初始化時均應置為0。
2、 ?順序隊列的基本操作
①入隊時:將新元素插入rear所指的位置,然后將rear加1。
②出隊時:刪去front所指的元素,然后將front加1并返回被刪元素。
注意:
????①當頭尾指針相等時,隊列為空。
????????②在非空隊列里,隊頭指針始終指向隊頭元素,尾指針始終指向隊尾元素的下一位置。 3、順序隊列中的溢出現象 ① "下溢"現象
???? 當隊列為空時,做出隊運算產生的溢出現象。“下溢”是正常現象,常用作程序控制轉移的條件。
② "真上溢"現象
???? 當隊列滿時,做進棧運算產生空間溢出的現象。“真上溢”是一種出錯狀態,應設法避免。
③ "假上溢"現象
由于入隊和出隊操作中,頭尾指針只增加不減小,致使被刪元素的空間永遠無法重新利用。當隊列中實際的元素個數遠遠小于向量空間的規模時,也可能由于尾指針已超越向量空間的上界而不能做入隊操作。該現象稱為"假上溢"現象。
四、循環隊列 ???????為充分利用向量空間,克服"假上溢"現象的方法是:將向量空間想象為一個首尾相接的圓環,并稱這種向量為循環向量。存儲在其中的隊列稱為循環隊列(Circular Queue)。
1、 循環隊列的基本操作
???? 循環隊列中進行出隊、入隊操作時,頭尾指針仍要加1,朝前移動。只不過當頭尾指針指向向量上界(QueueSize-1)時,其加1操作的結果是指向向量的下界0。這種循環意義下的加1操作可以描述為:
① 方法一:
????if(i+1==QueueSize) //i表示front或rear
????????i=0;
????else
????????i++;
② 方法二--利用"模運算"
????i=(i+1)%QueueSize;
2、 循環隊列邊界條件處理
??? 循環隊列中,由于入隊時尾指針向前追趕頭指針;出隊時頭指針向前追趕尾指針,造成隊空和隊滿時頭尾指針均相等。因此,無法通過條件front==rear來判別隊列是"空"還是"滿"。?
??? 解決這個問題的方法至少有三種:
① 另設一布爾變量以區別隊列的空和滿;
② 少用一個元素的空間。約定入隊前,測試尾指針在循環意義下加1后是否等于頭指針,若相等則認為隊滿(注意:rear所指的單元始終為空);
③使用一個計數器記錄隊列中元素的總數(即隊列長度)。
3、程序 #define ?DataType ??int ? #define ?MAXSIZE ???100
using namespace std;
typedef ?struct ?_CirQueue? { DataType ??data[MAXSIZE]; int ?front; //頭指針,隊非空時指向隊頭元素 int ?rear; //尾指針,隊非空時指向隊尾元素的下一位置 }CirQueue, *pCirQueue;
void ??InitQueue(pCirQueue ??pQueue); bool ???Empty(pCirQueue ?pQueue); bool InsertQueue(pCirQueue pQueue, DataType x); DataType OutQueue(pCirQueue pQueue); DataType ???GetHead(pCirQueue ?pQueue); int ?GetLength(pCirQueue ??pQueue);
int _tmain(int argc, _TCHAR* argv[]) { int ?len = 0, data; CirQueue ?myQueue; InitQueue(&myQueue); if (!Empty(&myQueue)) { printf("Queue is Empty"); } InsertQueue(&myQueue, 1); InsertQueue(&myQueue, 2); InsertQueue(&myQueue, 3); InsertQueue(&myQueue, 4); len = GetLength(&myQueue); data = GetHead(&myQueue); while (Empty(&myQueue)) { data = OutQueue(&myQueue); cout<<endl<<data; } return 0; }
//初始化:初始化一個新的隊列 void ??InitQueue(pCirQueue ??pQueue) { memset(pQueue, 0, sizeof(CirQueue)); }
//隊列非空判斷:若隊列不為空,則返回true;否則返回false。 bool ???Empty(pCirQueue ?pQueue) { if (pQueue->front != pQueue->rear) { return true; } else return false; }
//入隊列:在隊列的尾部插入元素x,使元素x成為新的隊尾。若 隊列滿,則返回false;否則,返回true。 bool InsertQueue(pCirQueue pQueue, DataType x) { if ((pQueue->rear+1)%MAXSIZE != pQueue->front) ?//判斷隊列是否已滿 { pQueue->data[pQueue->rear] = x; pQueue->rear = (pQueue->rear + 1)%MAXSIZE; return true; } else return ?false; }
//出隊列:若隊列不為空,則返回對頭元素,并從對頭刪除該元素,對頭指針指向原對頭的后記元素;否則,返回元素NULL DataType OutQueue(pCirQueue pQueue) { DataType ??data; if (pQueue->front == pQueue->rear) { return NULL; } else { data = pQueue->data[pQueue->front]; pQueue->front = (pQueue->front + 1)%MAXSIZE; return data; } }
//取對頭元素:若隊列不空,則返回對頭元素;否則,返回空元素NULL DataType ???GetHead(pCirQueue ?pQueue) { if (pQueue->front == pQueue->rear) { return ?NULL; } else { return ?pQueue->data[pQueue->front]; } }
//求隊列長度 int ?GetLength(pCirQueue ??pQueue) { int ?length = 0, number = 0; for (number = pQueue->front; number%MAXSIZE < pQueue->rear; number = (number+1)%MAXSIZE) { length++; } return length; }
運行結果:
二、隊列的分類 ???????隊列本身也是一種線性表,因而和線性表一樣也有順序和鏈式存儲結構兩種存儲方式。 ???????采用順序存儲結構實現的隊列稱為順序隊列; ???????采用鏈式存儲結構實現的隊列稱為鏈隊列。
三、順序隊列 1、順序隊列的表示 ???????①順序隊列用一個向量空間(一般使用一維數組)來存放當前隊列中的元素。
②由于隊列的隊頭和隊尾的位置是變化的,設置兩個指針front和rear分別指示隊頭元素和隊尾元素在向量空間中的位置,它們的初值在隊列初始化時均應置為0。
2、 ?順序隊列的基本操作
①入隊時:將新元素插入rear所指的位置,然后將rear加1。
②出隊時:刪去front所指的元素,然后將front加1并返回被刪元素。
注意:
????①當頭尾指針相等時,隊列為空。
????????②在非空隊列里,隊頭指針始終指向隊頭元素,尾指針始終指向隊尾元素的下一位置。 3、順序隊列中的溢出現象 ① "下溢"現象
???? 當隊列為空時,做出隊運算產生的溢出現象。“下溢”是正常現象,常用作程序控制轉移的條件。
② "真上溢"現象
???? 當隊列滿時,做進棧運算產生空間溢出的現象。“真上溢”是一種出錯狀態,應設法避免。
③ "假上溢"現象
由于入隊和出隊操作中,頭尾指針只增加不減小,致使被刪元素的空間永遠無法重新利用。當隊列中實際的元素個數遠遠小于向量空間的規模時,也可能由于尾指針已超越向量空間的上界而不能做入隊操作。該現象稱為"假上溢"現象。
四、循環隊列 ???????為充分利用向量空間,克服"假上溢"現象的方法是:將向量空間想象為一個首尾相接的圓環,并稱這種向量為循環向量。存儲在其中的隊列稱為循環隊列(Circular Queue)。
1、 循環隊列的基本操作
???? 循環隊列中進行出隊、入隊操作時,頭尾指針仍要加1,朝前移動。只不過當頭尾指針指向向量上界(QueueSize-1)時,其加1操作的結果是指向向量的下界0。這種循環意義下的加1操作可以描述為:
① 方法一:
????if(i+1==QueueSize) //i表示front或rear
????????i=0;
????else
????????i++;
② 方法二--利用"模運算"
????i=(i+1)%QueueSize;
2、 循環隊列邊界條件處理
??? 循環隊列中,由于入隊時尾指針向前追趕頭指針;出隊時頭指針向前追趕尾指針,造成隊空和隊滿時頭尾指針均相等。因此,無法通過條件front==rear來判別隊列是"空"還是"滿"。?
??? 解決這個問題的方法至少有三種:
① 另設一布爾變量以區別隊列的空和滿;
② 少用一個元素的空間。約定入隊前,測試尾指針在循環意義下加1后是否等于頭指針,若相等則認為隊滿(注意:rear所指的單元始終為空);
③使用一個計數器記錄隊列中元素的總數(即隊列長度)。
3、程序 #define ?DataType ??int ? #define ?MAXSIZE ???100
using namespace std;
typedef ?struct ?_CirQueue? { DataType ??data[MAXSIZE]; int ?front; //頭指針,隊非空時指向隊頭元素 int ?rear; //尾指針,隊非空時指向隊尾元素的下一位置 }CirQueue, *pCirQueue;
void ??InitQueue(pCirQueue ??pQueue); bool ???Empty(pCirQueue ?pQueue); bool InsertQueue(pCirQueue pQueue, DataType x); DataType OutQueue(pCirQueue pQueue); DataType ???GetHead(pCirQueue ?pQueue); int ?GetLength(pCirQueue ??pQueue);
int _tmain(int argc, _TCHAR* argv[]) { int ?len = 0, data; CirQueue ?myQueue; InitQueue(&myQueue); if (!Empty(&myQueue)) { printf("Queue is Empty"); } InsertQueue(&myQueue, 1); InsertQueue(&myQueue, 2); InsertQueue(&myQueue, 3); InsertQueue(&myQueue, 4); len = GetLength(&myQueue); data = GetHead(&myQueue); while (Empty(&myQueue)) { data = OutQueue(&myQueue); cout<<endl<<data; } return 0; }
//初始化:初始化一個新的隊列 void ??InitQueue(pCirQueue ??pQueue) { memset(pQueue, 0, sizeof(CirQueue)); }
//隊列非空判斷:若隊列不為空,則返回true;否則返回false。 bool ???Empty(pCirQueue ?pQueue) { if (pQueue->front != pQueue->rear) { return true; } else return false; }
//入隊列:在隊列的尾部插入元素x,使元素x成為新的隊尾。若 隊列滿,則返回false;否則,返回true。 bool InsertQueue(pCirQueue pQueue, DataType x) { if ((pQueue->rear+1)%MAXSIZE != pQueue->front) ?//判斷隊列是否已滿 { pQueue->data[pQueue->rear] = x; pQueue->rear = (pQueue->rear + 1)%MAXSIZE; return true; } else return ?false; }
//出隊列:若隊列不為空,則返回對頭元素,并從對頭刪除該元素,對頭指針指向原對頭的后記元素;否則,返回元素NULL DataType OutQueue(pCirQueue pQueue) { DataType ??data; if (pQueue->front == pQueue->rear) { return NULL; } else { data = pQueue->data[pQueue->front]; pQueue->front = (pQueue->front + 1)%MAXSIZE; return data; } }
//取對頭元素:若隊列不空,則返回對頭元素;否則,返回空元素NULL DataType ???GetHead(pCirQueue ?pQueue) { if (pQueue->front == pQueue->rear) { return ?NULL; } else { return ?pQueue->data[pQueue->front]; } }
//求隊列長度 int ?GetLength(pCirQueue ??pQueue) { int ?length = 0, number = 0; for (number = pQueue->front; number%MAXSIZE < pQueue->rear; number = (number+1)%MAXSIZE) { length++; } return length; }
運行結果:
總結
- 上一篇: 潮人专属好物!HCK哈士奇x可口可乐联名
- 下一篇: 成长反思