队列的各种实现方式


队列是什么???

  今天我们来谈一谈队列。

  队列同样是一种线性表,但其运算受到一定的限制。其限制在于仅允许在队的一段(这里我们把它叫做队尾)进行插入操作,另一端(把它叫做队首)则进行删除操作。

  这和现实生活中的排队类似,由于有秩序,整个队列遵循先进先出原则。故又把队列称为先进先出表。

  我们首先用数组对其进行模拟。

队列之数组实现:

 

//数组模拟队列
#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-2025 CODEPRJ.COM