【数据结构】第三章 栈和队列--队列

笔记【数据结构】第三章 栈和队列–队列

队列的逻辑结构

队列:只允许在一端进行插入操作,而另一端进行删除操作的线性表。

空队列:不含任何数据元素的队列。

允许插入(也称入队、进队)的一端称为队尾,允许删除(也称出队)的一端称为队头。

队列的操作特性:先进先出(FIFO,LILO)

队列的顺序存储结构及实现

**顺序队列:**队列的顺序存储结构

队头指针和队尾指针的说明

队头指针指向队列中的第一个元素之前的元素,队尾指针指向队列中的最后一个元素
队头指针指向队列中的第一个元素,队尾指针指向队列中的最后一个元素的后一个位置

假溢出:当元素被插入到数组中下标最大的位置上之后,队列的空间就用尽了,尽管此时数组的低端还有空闲空间,这种现象叫做假溢出。

如何解决假溢出?

循环队列:将存储队列的数组头尾相接。

如何实现循环队列?

不存在物理的循环结构,用软件方法实现。

求模:rear=(rear+1)% MAXSIZE

   front=(front+1)% MAZSIZE

如何确定不同的队空、队满的判定条件?

方法一:附设一个存储队列中元素个数的变量num,当num=0时队空,当num=QueueSize时为队满;

方法二:修改队满条件,浪费一个元素空间,队满时数组中只有一个空闲单元;

方法三:设置标志flag,当front=rear且flag=0时为队空,当front=rear且flag=1时为队满。

队满的条件:(rear+1) mod QueueSize==front

循环队列类的声明



const int QueueSize=100; 

template <class T>    

class CirQueue{ 

 
public:

     
CirQueue( ); 

     
~ CirQueue( );

     
void EnQueue(T x); 

    
T DeQueue( );             

    
T GetQueue( ); 

    
bool Empty( ){

     
if (rear==front) return true;

      
return false;

  
};

 
private:

    
T data[QueueSize];   

    
int front, rear;

};




循环队列的实现——入队

template <class T>

 void CirQueue<T>::EnQueue(T x)

 {

  
if ((rear+1) % QueueSize ==front) throw "上溢";

  
rear=(rear+1) % QueueSize;    

  
data[rear]=x;                 

 }




循环队列的实现——出队

template <class T>

T CirQueue<T>::DeQueue( )

{

    
if (rear==front) throw "下溢"; 

    
front=(front+1) % QueueSize; 

    
return data[front];

} 




循环队列的实现——读队头元素

template <class T>

T CirQueue<T>::GetQueue( )

{

   
if (rear==front) throw "下溢"; 

   
i=(front+1) % QueueSize;  

   
return data[i];

}




循环队列的实现——队列长度

template <class T>

int CirQueue<T>::GetLength( )

{

   
if (rear==front) throw "下溢"; 

   
len=(rear-front+ QueueSize) % QueueSize; 


   
return len;

}


链队列类的声明



template <class T>

class LinkQueue

{  


 
public:

     
LinkQueue( );     

     
~LinkQueue( ); 

     
void EnQueue(T x);

     
T DeQueue( );       

     
T GetQueue( );

     
bool Empty( );

 
private:

     
Node<T> *front, *rear;

};


链队列的实现——构造函数

操作接口: LinkQueue( );

算法描述:



template <class T>

LinkQueue<T>::LinkQueue( )

{

    
front=new Node<T>; 

    
front->next=NULL;  

    
rear=front;

}


链队列的实现——入队

操作接口: void EnQueue(T x);

算法描述:

s->next=NULL;

rear=s;

front=s;



template <class T>

void LinkQueue<T>::EnQueue(T x)

{ 

   
s=new Node<T>; 

   
s->data=x; 

   
s->next=NULL;

   
rear->next=s; 

   
rear=s;

}




链队列的实现——出队

算法描述:

p=front->next;

front->next=p->next;

delete p;

算法描述:

在删除节点之后,还要进行下面的处理

if (p->next==NULL)

rear=front;

template <class T>

T LinkQueue<T>::DeQueue( )

{ 

    
if (rear==front) throw "下溢";

    
p=front->next; 

    
x=p->data; 

    
front->next=p->next;        

    
delete p;

    
if (front->next==NULL) rear=front;  


    
return x;

}


循环队列和链队列的比较

时间性能:

循环队列和链队列的基本操作都需要常数时间O (1)。

空间性能:

循环队列:必须预先确定一个固定的长度,所以有存储元素个数的限制和空间浪费的问题。

链队列:没有队列满的问题,只有当内存没有可用空间时才会出现队列满,但是每个元素都需要一个指针域,从而产生了结构性开销。

火车车厢重排过程

  1. 分别对k个队列初始化;

  2. 初始化下一个要输出的车厢编号nowOut = 1;

  3. 依次取入轨中的每一个车厢的编号;

3.1 如果入轨中的车厢编号等于nowOut,则

3.1.1 输出该车厢;

3.1.2 nowOut++;

3.2 考察每一个缓冲轨队列

for (j=1; j<=k; j++)

           3.2.1 取队列 j 的队头元素c;

           3.2.2 如果c=nowOut,则

                3.2.2.1 将队列 j 的队头元素出队并输出;

                3.2.2.2 nowOut++; 

3.3 如果入轨和缓冲轨的队头元素没有编号为nowOut的车厢,则(如果前两步工作都不成立)

3.3.1 求小于入轨中第一个车厢编号的最大队尾元素所在队列编号j;

3.3.2 如果 j 存在,则把入轨中的第一个车厢移至缓冲轨 j;

3.3.2 如果 j 不存在,但有多于一个空缓冲轨,则把入轨中的第一个车厢移至一个空缓冲轨;否则车厢无法重排,算法结束;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值