隊列是什么???
今天我們來談一談隊列。
隊列同樣是一種線性表,但其運算受到一定的限制。其限制在於僅允許在隊的一段(這里我們把它叫做隊尾)進行插入操作,另一端(把它叫做隊首)則進行刪除操作。
這和現實生活中的排隊類似,由於有秩序,整個隊列遵循先進先出原則。故又把隊列稱為先進先出表。
我們首先用數組對其進行模擬。
隊列之數組實現:
//數組模擬隊列 #include<iostream> #include<cstdlib> # define maxn 10001 using namespace std; int queue[maxn]; int front = -1;//指向隊首 int rear = -1;//指向隊尾 void add(int temp)//入隊操作 { if(rear>=maxn) cout<<"The queue is full!"<<endl; else queue[++rear]=temp; return; } int del()//出隊操作 { if(rear==front) return -1; int temp; temp=queue[++front]; queue[front]=-1; return temp; } void display()//顯示隊中元素(從隊首到隊尾) { if(rear==front) { cout<<"The queue is empty!"<<endl; return; } int i=front; cout<<"The front is : "<<front<<endl; cout<<"The rear is : "<<rear<<endl; cout<<"The queue is : "; while(i<rear) { cout<<queue[++i]<<" "; } cout<<endl; return; } int main() { int ins; int i,temp; while(1) { cout<<"1.Input a data."<<endl; cout<<"2.Output a data."<<endl; cout<<"3.Exit."<<endl; cin>>ins; switch(ins) { case 1: cout<<"Please input a value: "; cin>>temp; add(temp); cout<<endl; break; case 2: temp=del(); if(temp==-1) cout<<"The queue is empty!"<<endl; else cout<<"The out value is: "<<temp<<endl; break; case 3: return 0; } display(); system("pause"); system("cls"); } return 0; }
在以上代碼實現的過程中,我們可以發現,每次出隊操作后都會有數組的空間浪費,這會導致隊滿后仍有大量空間浪費,我們稱之為“假溢出”。
解決假溢出的方法是將線型數組擬成環形,將線性隊列擬為循環隊列,這樣便可以避免大量空間浪費。
不過,口頭上說有些抽象,讓我們看圖。

每當隊尾達到數組的最大長度時,我們便將下一個待插入的元素的插入位置(即隊尾)轉移至數組首端,若該位置可插入,則插入成功,否則判斷隊滿。
可以看出:
隊空時,rear==front;
隊滿時,((rear+1)%maxn==front);
隊空時的條件應該很好理解,這里我們只說說隊滿時的條件討論。
這里的maxn代表隊列的最大長度,但為什么要做((rear+1)%maxn==front)的條件判斷呢?
首先,取模操作無疑是為了使我們的隊列“循環”起來。但是(rear+1)%maxn的目的是為了什么呢?
假設為(rear%maxn==front)為判斷條件,可知有rear始終位於0~maxn之間,則存在將(rear%maxn==front)轉化為(rear==front)的情況。因此,我們可能會將隊滿的情況判斷為隊空的情況(反之亦可)。
所以,在判斷條件中給rear加上一個1是為了在對尾與隊首之間隔出一個空位,以區分隊滿與隊空兩種情況。
OK,優化過程分析到這就結束了,下面見代碼。
數組循環隊列:
//循環隊列 #include<iostream> #include<cstdlib> #include<cstring> # define maxn 10 using namespace std; int queue[maxn]; int front = 0;//隊首指針 int rear = 0;//隊尾指針 void add(int temp) { if((rear+1)%maxn==front) cout<<"The queue is full!"<<endl; else { queue[rear]=temp; rear=(rear+1)%maxn; } return; } int del() { if(front==rear) return -1; int temp=queue[front]; queue[front]=-1; front=(front+1)%maxn; return temp; } void display() { if(front==rear) cout<<"The queue is empty!"<<endl; else { int i=front; cout<<"front is : "<<front<<endl; cout<<"rear is : "<<rear<<endl; cout<<"The queue is : "; while(i!=rear) { cout<<queue[i]<<" "; i=(i+1)%maxn; } cout<<endl; } } int main() { int ins,temp; memset(queue,-1,sizeof(queue)); while(1) { cout<<"1.Input a data."<<endl; cout<<"2.Outout a data."<<endl; cout<<"3.Exit."<<endl; cin>>ins; switch(ins) { case 1 : cout<<"Please input a value : "; cin>>temp; add(temp); cout<<endl; break; case 2 : temp=del(); if(temp==-1) cout<<"The queue is Empty! "<<endl; else cout<<"The out value is : "<<temp<<endl; break; case 3 :return 0; } display(); system("pause"); system("cls"); } return 0; }
下面,為了對比,我簡單給出鏈表模擬隊列的代碼,這里就不再贅述了。
//鏈表仿真隊列 #include <iostream> #include <cstdlib> using namespace std; typedef struct QueueNode node; typedef struct QueueNode *link; struct QueueNode { int data; struct QueueNode *next; }; link front =NULL;//隊頭 link rear =NULL; //隊尾 void addqueue(int value) { link new_node; new_node=(link)malloc(sizeof(node)); new_node->data=value; new_node->next=NULL; if(front==NULL) //若為隊列第一個元素 front=new_node; else rear->next=new_node; rear=new_node; } int delqueue() { link top; int temp; if(front!=NULL) { top=front; front=front->next; temp=top->data; free(top); return temp; } else { rear=NULL; return -1; } } void display() { link point; point=front; cout<<"The queue is : "; while(point!=NULL) { cout<<point->data<<' '; point=point->next; } cout<<endl; } int main() { int select; int i,temp; while(1) { cout<<"1.Input a data\n"; cout<<"2.Output a data\n"; cout<<"3.Exit\n"; cin>>select; switch(select) { case 1:cout<<"Please input a value: "; cin>>temp; addqueue(temp); break; case 2:if(delqueue()==-1)//如果隊列是空 cout<<"The queue is empty!\n"; else cout<<"The out value is: "<<temp<<endl; break; case 3:return 0; } display(); cout<<endl<<endl; system("pause"); system("cls"); } return 0; }
關於隊列的討論就到這里了,若有不足,請指正!

