《編程之美》-取隊列中的最大值(讀書分享)

題目:設計一種數據結構和算法,讓取隊列最大值的操做的事件複雜度降到最低。對隊列操做後依然可以簡便取出最大值。


對於棧來說,Push和Pop均是在棧頂完成的,因此很容維護最大值,並且他的時間複雜度是O(1),基本實現以下所示: 算法

1.棧類: 數據結構

public class MyStack
    {
        private int _capacity;
        private int[] _stackItems;
        private int _maxStackItemIndex;
        private int _stackTop;
        private int[] _link2NextMaxitem;


        public MyStack(int capacity)
        {
            _capacity = capacity;
            _stackTop = -1;
            _maxStackItemIndex = -1;
            _link2NextMaxitem = new int[_capacity];
            _stackItems = new int[_capacity];
        }
        public void Push(int item) {//壓棧
            _stackTop++;
            if (_stackTop >= _capacity)
            {
               return false;//越界了
            }
            else
            {
                _stackItems[_stackTop] = item;
                //維護列表,經典, 不管堆棧如何變化_link2NextMaxItem[..._link2NextMaxItem[_link2NextMaxItem[_maxStackItemIndex]]]如此環環相扣的數據保存模式保證了「當時」注意這裏是「當時的」第二大數的索引老是能夠經過當前的_link2NextMaxItem[_maxStackItemIndex]來得到(同時發生的事情是最大的項被彈出,也就是pop函數裏面發生的事情,第二大數成了最大的了),_stackItems[_maxStackItemIndex]則是一直保存着最大項,

                if (item > Max())
                {                                                                                               _link2NextMaxitem[_stackTop] = _maxStackItemIndex;//如下兩句順序不能變,思考一下童鞋
                 _maxStackItemIndex = _stackTop; 
                                                                        
                } else   _link2NextMaxitem[_stackTop] = -1;


            }
        }
        public int Pop() {//彈出元素
            int rt = 0;
            if (_stackTop < 0)
                throw new Exception("Queue is null");


            rt = _stackItems[_stackTop];
            //維護列表
            if (_stackTop == _maxStackItemIndex)
            {
                _maxStackItemIndex = _link2NextMaxitem[_stackTop];
            }
            _stackTop--;
            return rt;
        }
        public int Max()    //取最大    
        {
            if (_maxStackItemIndex >= 0)
                return _stackItems[_maxStackItemIndex];
            else
                return -1;
        }


        public bool IsEmpty()
        {
            return _stackTop == -1;
        }
     
    }
  

聯繫上面思想,用兩堆棧實現一個隊列:隊列入隊的實現:利用棧B入棧全部元素;隊列出隊的實現:將棧B中的元素放入棧A,對棧A進行出棧操做正好知足隊列元素的出隊順序要求 數據結構和算法

2.隊列類(使用了1中定義的堆棧類做爲隊列的底層數據結構來實現),按照流程畫個圖就明白了: 函數

/// 隊列類

    public class MyQueue
    {
        //利用堆棧與隊列的類似性,用兩個堆棧來實現隊列
        private MyStack _stacka;
        private MyStack _stackb;

        public MyQueue(int capacity)
        {
            _stacka = new MyStack(capacity);
            _stackb = new MyStack(capacity);
        }

        public void Enqueue(int item)
        {
            _stackb.Push(item);
        }

        public int Dequeue()
        {
            if (_stacka.IsEmpty())
            {
                while (!_stackb.IsEmpty())
                    _stacka.Push(_stackb.Pop());
            }
            return _stacka.Pop();
        }

        public int Max()
        {
            return Math.Max(_stacka.Max(), _stackb.Max());
        }
    }
相關文章
相關標籤/搜索