要實現min函數複雜度爲O(1) 肯定不能遍歷彈入的數據也不能簡單維護一個小頂堆(小頂堆的維護需要lg(n)時間)
這個時候可以利用棧先進後出的特性:
考慮2 4 3 1 四個依次入棧的數字。在我們維護的min數據中,我們不需要保存1 2 3 4, 事實上,由於棧只能按照1 3 4 2的順序出棧,4和3永遠也不會成爲最小的數。也就是說,我們在維護min數據時,只需在遇到一個新的最小數據(即比當前的最小數據更小或相等)時,我們就將遇到的最小數據放在當前的最小數據前面(這個數據結構可用棧來維護)。這樣我們在以上入棧序列2 4 3 1中,先保存最小數據2 遇到4 3時不改變,遇到1時,將1 放在2的前面。這樣在彈出序列1 3 4 2時,如果彈出的數據是當前最小數據,我們就將該數據在min維護的數據結構中刪除掉,例如在彈出1時,min序列就只剩下2,而由於2永遠在3 4之後彈出,因此它理所當然在彈出它本身之前是最小的。另外還要注意重複最小數,比如入棧序列1 3 2 1。在彈出1之後,最小元素仍然是1,也就是說,最小棧在遇到與當前最小元素相等的元素時,也應該更新。
本例中min數據結構也用棧來維護。棧頂元素就是當前元素主棧中的最小元素
#include<iostream>
using namespace std;
class Stack
{
//定義內部棧結構 用於構建正常數據棧和最小數據棧
typedef struct _stack
{
int* pElem; //指向元素數據的指針
int size; //棧的最大容量
int top; //棧的當前棧頂位置
_stack(int n):size(n)
{
top = 0;
pElem = new int[size];
}
~_stack()
{
delete []pElem;
pElem = NULL;
}
}stack;
public:
//構造時,初始化正常棧和最小數據棧
Stack(int n):s(n), minstack(n)
{
}
bool pop(int* e)
{
//判斷棧空
if (s.top == 0)
return false;
int value = s.pElem[--s.top];
//判斷將要彈出的是否是最小元素 如果是 則更新最小元素棧
if (value == minstack.pElem[minstack.top-1])
--minstack.top;
*e = value;
return true;
}
bool push(int value)
{
//判斷棧滿
if (s.top == s.size)
return false;
//如果當前最小元素棧爲空或者要壓入的元素小於等於當前最小元素 則壓入
//這裏不需要擔心最小棧溢出 因爲前面已經判斷並且top==0必須放在||前面 否則top==0時訪問top-1會越界
//注意這裏必須是<=而不能是= 比如1 2 3 1 當1彈出時,最小元素仍然是1 因此minstack裏面應該有兩個1
if (minstack.top==0 || value<=minstack.pElem[minstack.top-1])
minstack.pElem[minstack.top++] = value;
s.pElem[s.top++] = value;
return true;
}
//取最小元素 直接是最小數據棧頂元素
bool min(int *pmin)
{
if (minstack.top == 0)
return false;
*pmin = minstack.pElem[minstack.top-1];
return true;
}
private:
stack s;
stack minstack;
};
void main()
{
Stack s(5);
s.push(9);
s.push(7);
s.push(10);
s.push(5);
s.push(8);
cout<<"壓入序列9 7 10 5 8"<<endl;
cout<<"彈出序列"<<endl;
int v;
while (s.pop(&v))
{
cout<<"pop "<<v<<"\t";
if (s.min(&v))
cout<<"min value : "<<v<<endl;
else
cout<<"there is no min value!"<<endl;
}
return ;
}
總結: 本題的關鍵點就在於理解棧結構,由於其先進後出的特性,使得在一個更小元素上的其他元素永遠也不會成爲最小元素,只有遇到比當前最小元素更小(或相等)的元素時,才更新最小數據棧,換句話說,在正常數據棧每彈出一個元素的過程中,min函數得到的最小元素一定是非遞減的,也就是說最小棧的入棧數據序列一定是非遞增的,以此得到了最小棧維護數據的特性。就可以建立該棧了