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里面的每个元素

posted on   dz45693  阅读(1773)  评论(0编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2016-11-22 VS SuppressMessage忽略特定方法的警告信息
2012-11-22 Asp.Net MVC 项目预编译 View

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示