using System;
using System.Collections.Generic;
using System.Collections;
namespace StructScript
{
public class QueueScript<T> : IEnumerable<T>
{
private T[] mArray;
private int mHead; // 队列中的第一个元素
private int mTail; // 队列中的最后一个元素
private int mSize; // 队列大小
private const int mMinimumGrow = 4;
private const int mShrinkThreshold = 32;
private const int mGrowFactor = 200;
private const int mDefaultCapacity = 4;
private static T[] mEmptyArray = new T[0];
public QueueScript()
{
mArray = mEmptyArray;
}
public QueueScript(int capacity)
{
if (capacity < 0)
{
throw new IndexOutOfRangeException();
}
mArray = new T[capacity];
mHead = 0;
mTail = 0;
mSize = 0;
}
public int Count
{
get { return mSize; }
}
public void Enqueue(T item)
{
if (mSize == mArray.Length)
{
// 容量每次翻倍
int newCapacity = mArray.Length * 2;
if (newCapacity < mArray.Length + mMinimumGrow)
{
newCapacity = mArray.Length + mMinimumGrow;
}
SetCapacity(newCapacity);
}
mArray[mTail] = item;
//mArray.Length是大于等于队列的实际数据的,利用除留余数法,获得当前的索引值
mTail = (mTail + 1) % mArray.Length;
mSize++;
}
public T Dequeue()
{
if (mSize == 0)
{
throw new InvalidOperationException();
}
T removed = mArray[mHead];
mArray[mHead] = default(T);
//mArray.Length是大于等于队列的实际数据的,利用除留余数法,获得当前的索引值
mHead = (mHead + 1) % mArray.Length;
mSize--;
return removed;
}
public bool Contains(T item)
{
int index = mHead;
int count = mSize;
EqualityComparer<T> c = EqualityComparer<T>.Default;
while (count-- > 0)
{
if (((Object)item) == null)
{
if (((Object)mArray[index]) == null)
return true;
}
else if (mArray[index] != null && c.Equals(mArray[index], item))
{
return true;
}
//mArray.Length是大于等于队列的实际数据的,利用除留余数法,获得当前的索引值
index = (index + 1) % mArray.Length;
}
return false;
}
private void SetCapacity(int capacity)
{
T[] newArray = new T[capacity];
if (mSize > 0)
{
if (mHead < mTail)
{
Array.Copy(mArray, mHead, newArray, 0, mSize);
}
else
{
Array.Copy(mArray, mHead, newArray, 0, mArray.Length - mHead);
Array.Copy(mArray, 0, newArray, mArray.Length - mHead, mTail);
}
}
mArray = newArray;
mHead = 0;
mTail = (mSize == capacity) ? 0 : mSize;
}
public void Clear()
{
if (mHead < mTail)
Array.Clear(mArray, mHead, mSize);
else
{
Array.Clear(mArray, mHead, mArray.Length - mHead);
Array.Clear(mArray, 0, mTail);
}
mHead = 0;
mTail = 0;
mSize = 0;
}
public IEnumerator<T> GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this);
}
internal T GetElement(int i)
{
return mArray[(mHead + i) % mArray.Length];
}
public struct Enumerator : IEnumerator<T>
{
private QueueScript<T> _q;
private int _index; // -1 = not started, -2 = ended/disposed
private T _currentElement;
internal Enumerator(QueueScript<T> q)
{
_q = q;
_index = -1;
_currentElement = default(T);
}
public void Dispose()
{
_index = -2;
_currentElement = default(T);
}
public bool MoveNext()
{
if (_index == -2)
return false;
_index++;
if (_index == _q.mSize)
{
_index = -2;
_currentElement = default(T);
return false;
}
_currentElement = _q.GetElement(_index);
return true;
}
public T Current
{
get
{
if (_index < 0)
{
throw new InvalidOperationException();
}
return _currentElement;
}
}
Object IEnumerator.Current
{
get
{
if (_index < 0)
{
throw new InvalidOperationException();
}
return _currentElement;
}
}
void IEnumerator.Reset()
{
_index = -1;
_currentElement = default(T);
}
}
}
}
附上,测试用例:
using System;
namespace StructScript
{
class TestQueue
{
public static void Main()
{
QueueScript<string> numbers = new QueueScript<string>();
numbers.Enqueue("one");
numbers.Enqueue("two");
numbers.Enqueue("three");
numbers.Enqueue("four");
numbers.Enqueue("five");
// A queue can be enumerated without disturbing its contents.
foreach (string number in numbers)
{
Console.WriteLine(number);
}
Console.WriteLine("\nDequeuing '{0}'", numbers.Dequeue());
Console.WriteLine("Dequeuing '{0}'", numbers.Dequeue());
Console.WriteLine("\nqueueCopy.Contains(\"four\") = {0}",
numbers.Contains("four"));
Console.WriteLine("\nqueueCopy.Clear()");
numbers.Clear();
Console.WriteLine("\nqueueCopy.Count = {0}", numbers.Count);
Console.ReadLine();
}
}
}