對於棧來說,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()); } }