C# Queue 和Stack的实现
Queue 和Stack的使用就不用多说吧,一个是先进先出,一个是后进先出。 这里我主要关注其实现原理。
queue的实现如下:
public class Queue<T> : IEnumerable<T>,System.Collections.ICollection,IReadOnlyCollection<T> { private T[] _array; private int _head; // First valid element in the queue private int _tail; // Last valid element in the queue private int _size; // Number of elements. public Queue(int capacity) { if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNumRequired); _array = new T[capacity]; _head = 0; _tail = 0; _size = 0; } public Queue(IEnumerable<T> collection) { if (collection == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); _array = new T[_DefaultCapacity]; _size = 0; _version = 0; using(IEnumerator<T> en = collection.GetEnumerator()) { while(en.MoveNext()) { Enqueue(en.Current); } } } public void Enqueue(T item) { if (_size == _array.Length) { int newcapacity = (int)((long)_array.Length * (long)_GrowFactor / 100); if (newcapacity < _array.Length + _MinimumGrow) { newcapacity = _array.Length + _MinimumGrow; } SetCapacity(newcapacity); } _array[_tail] = item; _tail = (_tail + 1) % _array.Length; _size++; _version++; } public T Dequeue() { if (_size == 0) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue); T removed = _array[_head]; _array[_head] = default(T); _head = (_head + 1) % _array.Length; _size--; _version++; return removed; } public bool Contains(T item) { int index = _head; int count = _size; EqualityComparer<T> c = EqualityComparer<T>.Default; while (count-- > 0) { if (((Object) item) == null) { if (((Object) _array[index]) == null) return true; } else if (_array[index] != null && c.Equals(_array[index], item)) { return true; } index = (index + 1) % _array.Length; } return false; } private void SetCapacity(int capacity) { T[] newarray = new T[capacity]; if (_size > 0) { if (_head < _tail) { Array.Copy(_array, _head, newarray, 0, _size); } else { Array.Copy(_array, _head, newarray, 0, _array.Length - _head); Array.Copy(_array, 0, newarray, _array.Length - _head, _tail); } } _array = newarray; _head = 0; _tail = (_size == capacity) ? 0 : _size; _version++; } }
Stack的实现:
public class Stack<T> : IEnumerable<T>, System.Collections.ICollection,IReadOnlyCollection<T> { private T[] _array; // Storage for stack elements private int _size; // Number of items in the stack. public Stack(int capacity) { if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNumRequired); _array = new T[capacity]; _size = 0; _version = 0; } public Stack(IEnumerable<T> collection) { if (collection==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); ICollection<T> c = collection as ICollection<T>; if( c != null) { int count = c.Count; _array = new T[count]; c.CopyTo(_array, 0); _size = count; } else { _size = 0; _array = new T[_defaultCapacity]; using(IEnumerator<T> en = collection.GetEnumerator()) { while(en.MoveNext()) { Push(en.Current); } } } } public void Push(T item) { if (_size == _array.Length) { T[] newArray = new T[(_array.Length == 0) ? _defaultCapacity : 2*_array.Length]; Array.Copy(_array, 0, newArray, 0, _size); _array = newArray; } _array[_size++] = item; _version++; } public T Pop() { if (_size == 0) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack); _version++; T item = _array[--_size]; _array[_size] = default(T); // Free memory quicker. return item; } public bool Contains(T item) { int count = _size; EqualityComparer<T> c = EqualityComparer<T>.Default; while (count-- > 0) { if (((Object) item) == null) { if (((Object) _array[count]) == null) return true; } else if (_array[count] != null && c.Equals(_array[count], item) ) { return true; } } return false; } }
Queue 和Stack都是依靠数组来实现,并且都有带int capacity的构造函数。假如我们定义一个数组长度为5,Queue 和Stack都添加了5个元素,现在需要移除2个元素,Queue 移除arr[0],arr[1]两个元素(移除通过下标_head+1完成的),Stack移除arr[4],arr[3]两个元素(通过_size-1完成的),现在再添加2个元素,Queue 的arr5个元素都已被占用,需要创建新的数组,并且把原先3,4,5个元素拷贝到新的数组里面,但是Stack就好很多,新增加的元素可以直接赋值到arr[3],arr[4],查找Contains方法的实现都是循环数组arr里面的每个元素
windows技术爱好者