C# Queue 和Stack的实现

Queue 和Stack的使用就不用多说吧,一个是先进先出,一个是后进先出。 这里我主要关注其实现原理。

queue的实现如下:

 public class Queue : IEnumerable,System.Collections.ICollection,IReadOnlyCollection {
        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 collection)
        {
            if (collection == null)
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);

            _array = new T[_DefaultCapacity];
            _size = 0;
            _version = 0;

            using(IEnumerator 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 c = EqualityComparer.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 : IEnumerable, System.Collections.ICollection,IReadOnlyCollection 
 {
        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 collection) 
        {
            if (collection==null)
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);

            ICollection c = collection as ICollection;
            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 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 c = EqualityComparer.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里面的每个元素

你可能感兴趣的:(C# Queue 和Stack的实现)