少年未央

导航

循环队列

  由于数组在删除元素时,需要花费大量时间移动大量元素,因此基于数组的队列在执行出队操作时,速度很慢,很少有实际的应用,所以多采用循环队列的方式。

  为了避免大量的数据移动,通常将一维数组中的各个元素看成是一个首尾相接的封闭的圆环,既第一个元素时最后一个元素的下一个元素,这种形式的顺序队列成为循环队列。

循环队列的代码如下:

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
	}
}

posted on 2010-01-12 23:46  少年未央  阅读(446)  评论(0编辑  收藏  举报