• 环形堆栈


    查看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);
                        }
                    }
                }
            }
        }


  • 相关阅读:
    追踪神秘的成都Uber:月入2万元是现实还是传说
    打造自己博客(wordpress)的wap手机版本
    今天刚申请成为Uber司机 已经接了5单了....大家有什么想问的吗?
    UBER司机奖励政策
    原生应用native、Web应用、混合应用hybrid:3者的优缺点解析
    “基数排序”之数组中缺失的数字
    html5 新增语义标签
    如何判断Javascript对象是否存在
    HTML 5 <details> 标签
    html5 notifications通知
  • 原文地址:https://www.cnblogs.com/yangleiWPF/p/4565412.html
Copyright © 2020-2023  润新知