隊列的各種實現方式


隊列是什么???

  今天我們來談一談隊列。

  隊列同樣是一種線性表,但其運算受到一定的限制。其限制在於僅允許在隊的一段(這里我們把它叫做隊尾)進行插入操作,另一端(把它叫做隊首)則進行刪除操作。

  這和現實生活中的排隊類似,由於有秩序,整個隊列遵循先進先出原則。故又把隊列稱為先進先出表。

  我們首先用數組對其進行模擬。

隊列之數組實現:

 

//數組模擬隊列
#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; 
} 
View Code

  在以上代碼實現的過程中,我們可以發現,每次出隊操作后都會有數組的空間浪費,這會導致隊滿后仍有大量空間浪費,我們稱之為“假溢出”。

  解決假溢出的方法是將線型數組擬成環形,將線性隊列擬為循環隊列,這樣便可以避免大量空間浪費。

  不過,口頭上說有些抽象,讓我們看圖。

 

循環隊列

  每當隊尾達到數組的最大長度時,我們便將下一個待插入的元素的插入位置(即隊尾)轉移至數組首端,若該位置可插入,則插入成功,否則判斷隊滿。

  可以看出:

  隊空時,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;
}
View Code

 

  下面,為了對比,我簡單給出鏈表模擬隊列的代碼,這里就不再贅述了。

//鏈表仿真隊列 
#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;
}         
View Code

  關於隊列的討論就到這里了,若有不足,請指正!

 

謝謝~\(≧▽≦)/~啦啦啦

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM