環形堆棧

查看Queue的源碼發現其實隊列裏面維護的是一個數組,並且這個數組是一直增長的,隊列push一個就放到數組的最後,pop的時候就把數組最前面取出而後置爲Null,這樣必然致使在大量的pop和push操做後
會在數組前面產生大量的值爲Null的數組元素。這個時候就能夠用到 TrimToSize 方法進行重新分配數組,把多餘的Null去掉。

如今能夠實現一個定長的環形堆棧RingStack,能夠對循環利用。

  /// <summary>
    /// 環形堆棧類,長度固定,頂與底相接造成一個圓環,需自定義覆蓋時丟棄對象的處理方法
    /// </summary>
    /// <typeparam name="T">環形堆棧中對象的類型</typeparam>
    /// <remarks>屬於一個固定大小的堆棧式緩存,當增加速度過快時自動覆蓋最早壓入的對象</remarks>
    public sealed class RingStack<T>
    {
        /// <summary>
        /// 堆棧的容量
        /// </summary>
        public readonly int Capacity;

        /// <summary>
        /// 堆棧的數據集
        /// </summary>
        private T[] _Items;

        /// <summary>
        /// 堆棧頂部的指針
        /// </summary>
        private int _TopIndex;

        /// <summary>
        /// 堆棧底部的指針
        /// </summary>
        private int _BottomIndex;

        /// <summary>
        /// 對象的數量
        /// </summary>
        private int _Count;

        /// <summary>
        /// 獲取堆棧中對象的數量
        /// </summary>
        /// <remarks>此屬性的讀取是內部鎖定的,所以多線程操做是安全的</remarks>
        public int Count
        {
            get
            {
                lock (this)
                {
                    return _Count;
                }
            }
        }

        /// <summary>
        /// 覆蓋時丟棄對象的處理方法
        /// </summary>
        public Action<T> Drop;

        /// <summary>
        /// 初始化環形堆棧的新實例
        /// </summary>
        /// <param name="capacity">堆棧的容量</param>
        public RingStack(int capacity)
        {
            Capacity = capacity;
            _Items = new T[Capacity];
            _TopIndex = _BottomIndex = 0;
            _Count = 0;
        }

        /// <summary>
        /// 從堆棧中彈出一個對象
        /// </summary>
        /// <param name="item">彈出的對象</param>
        /// <returns>返回是否成功彈出對象,true表示彈出對象成功,false表示彈出對象失敗</returns>
        /// <remarks>此操做是內部鎖定的,所以多線程操做是安全的</remarks>
        public bool Pop(ref T item)
        {
            lock (this)
            {
                if (_TopIndex == _BottomIndex)
                {
                    return false;
                }
                item = _Items[_TopIndex];
                if ((--_TopIndex) == -1)
                {
                    _TopIndex = Capacity - 1;
                }
                --_Count;
                return true;
            }
        }

        /// <summary>
        /// 將指定的對象壓入堆棧
        /// </summary>
        /// <param name="item">須要壓入的對象</param>
        /// <remarks>此操做是內部鎖定的,所以多線程操做是安全的</remarks>
        public void Push(T item)
        {
            Console.WriteLine(string.Format("top:{0},bott:{1}", _TopIndex, _BottomIndex));
            lock (this)
            {
                if ((++_TopIndex) == Capacity)
                {
                    _TopIndex = 0;
                }
                if (_TopIndex == _BottomIndex)
                {
                    if ((++_BottomIndex) == Capacity)
                    {
                        _BottomIndex = 0;
                    }
                    if (Drop != null)
                    {
                        Drop(_Items[_BottomIndex]);
                    }
                    --_Count;
                }

                _Items[_TopIndex] = item;
                //_TopIndex++;
                ++_Count;

                
            }
        }

        /// <summary>
        /// 清除堆棧中的全部對象
        /// </summary>
        /// <remarks>此操做是內部鎖定的,所以多線程操做是安全的</remarks>
        public void Clear()
        {
            lock (this)
            {
                T t = default(T);
                while (_Count > 0)
                {
                    Pop(ref t);
                    if (Drop != null)
                    {
                        Drop(t);
                    }
                }
            }
        }
    }
相關文章
相關標籤/搜索