由于数组在删除元素时,需要花费大量时间移动大量元素,因此基于数组的队列在执行出队操作时,速度很慢,很少有实际的应用,所以多采用循环队列的方式。
为了避免大量的数据移动,通常将一维数组中的各个元素看成是一个首尾相接的封闭的圆环,既第一个元素时最后一个元素的下一个元素,这种形式的顺序队列成为循环队列。
循环队列的代码如下:
using System;
namespace Review
{
/// <summary>
/// 循环队列类
/// </summary>
public class Queue
{
#region "成员变量"
private object[] _array;//存放元素的数组
private int _growFactor;//增长因子
private int _head;//队头指针
private const int _MinimumGrow=4;//最小增长值
private const int _ShrinkThreshold=0x20;//初始容量
private int _size;//当前元素个数
private int _tail;//队尾指针
#endregion
#region "属性"
/// <summary>
/// 返回元素个数
/// </summary>
public int Count
{
get{return this._size;}
}
#endregion
#region "方法"
/// <summary>
/// 构造方法
/// </summary>
public Queue() : this(_ShrinkThreshold,2f)
{
}
/// <summary>
/// 构造方法
/// </summary>
/// <param name="capacity">初始容量</param>
/// <param name="growFactor">增长因子</param>
public Queue(int capacity,float growFactor)
{
//capacity指定初始容量,growFactor参数指定增长因子
if(capacity<0)
{
throw new ArgumentOutOfRangeException("capacity","初始容量不能小于0");
}
if((growFactor<1.0)||(growFactor>10.0))
{
//增长因子必须在1到10之间
throw ArgumentOutOfRangeException("growFactor","增长因子必须在1-10之间");
}
this._array=new object[capacity];
this._head=0;
this._tail=0;
this._size=0;
this._growFactor=(int)(growFactor*100f);
}
/// <summary>
/// 出队
/// </summary>
/// <returns></returns>
public virtual object Dequeue()
{
if(this._size==0)
{
throw new InvalidOperationException("队列为空");//队列下溢
}
object tmpObj=this._array[this._head];//出队
this._array[this._head]=null;//删除出队元素
//移动队头指针
this._head=(this._head+1)%this._array.Length;
this._size--;
return tmpObj;
}
/// <summary>
/// 入队
/// </summary>
/// <param name="obj"></param>
public virtual void Enqueue(object obj)
{
if(this._size==this._array.Length)
{
//计算新容量
int capacity=(int)((this._array.Length*this._growFactor)/100L);
if(capacity<(this._array.Length+_MinimumGrow))
{
//至少要增加四个元素
capacity=this._array.Length+_MinimumGrow;
}
this.SetCapacity(capacity);//设置容量
}
this._array[this._tail]=obj;
this._tail=(this._tail+1)%this._array.Length;//移动队尾指针
this._size++;
}
/// <summary>
/// 设置容量
/// </summary>
/// <param name="capacity"></param>
private void SetCapacity(int capacity)
{
//在内存空新开辟空间
object[] destinationArray=new object[capacity];
if(this._head<this._tail)
{
//元素搬家
Array.Copy(this._array,this._head,destinationArray,0,this._size);
}
else//当头指针在尾指针后面时
{
//先搬头指针后面的元素,再搬数组头部到尾部指针之间的元素
Array.Copy(this._array,this._head,destinationArray,0,this._array.Length-this._head);
Array.Copy(this._array,0,destinationArray,this._array.Length-this._head,this._tail);
}
this._array=destinationArray;
this._head=0;
this._tail=(this._size==capacity)? 0 : this._size;
}
#endregion
}
}