1.定義棧的資料結構,要求新增乙個min()函式,能夠得到棧的最小元素。要求函式min(),push(),及pop()函式的時間複雜度都是o(1).
思考1:
如果說我們給棧這個類新增乙個成員變數min,用來記錄棧中的最小值。
1. 假設第一次push進入元素1時,設定min=1;
2. 再次想讓2進棧時,先把2和min進行比較,發現2沒有min小,min的值不用改變,然後再把2進棧;
3. 想讓3進棧時,重複2中的步驟
這時棧中的元素為1、2、3,min的值為1,當我們想要知道棧中的最小值時,可以直接返回min的值,時間複雜度為o(1)。再多考慮一點,如果我們進行一次出棧操作,發現棧頂元素3比min大,不用改變min的值。這時棧中元素為1、2,min=1,
似乎依舊是正確的。我們再多考慮一點,這是我們入棧0,由於0是小於的min,所以設定min=0,這時棧中元素為1、2、0,min為0,這時我們就能發現問題了,把0出棧,0和min的值是相同的,我們不知道該把min設定為何值。這個思路是不對的。
思考2:
首先思考一下為什麼思考1的思路有問題:
狀態a:(1、2、3 min=1)
把0入棧得到狀態b
狀態b:(1、2、3、0,min= 0),
把棧頂元素0出棧後沒法知道0入棧前的狀態a中的最小值為多少,因為得到min=0的過程沒有之前的min=1和入棧元素0的參與,也就沒法恢復狀態a。
這是如果想知道0出棧後的最小值就得遍歷陣列,這是時間複雜度就不是o(1)了。
所以我們要把入棧元素值和入棧前的min,以及入棧後的min建立聯絡。
發現:什麼時候入棧後的min才會變化呢,只有當小於min的值入棧時。
當小於min的值入棧時,入棧後的min值應該等於入棧元素的本來值,於是我們可以不把本來值存入棧頂,而是把入棧前的min的資訊記錄到棧頂,即把入棧元素的本來值-入棧前的min(這個差值是小於0的)存入棧頂。這樣便把三者的關係建立了。想要獲得棧頂元素,只需要把入棧後的min返回出去,然後min - 棧頂值即可或得入棧前的min。
當大於min的值入棧時,把入棧元素的本來值-min(這個值是大於0的)的差值存入棧頂,入棧後的min的值等於入棧前的min的值。當棧頂元素出棧時,由於知道棧頂存的是差值,且該差值是大於0的,所以知道min的值不需要改變。
利用這個思路就可以實現題目中的要求了。
具體的實現明天再補上。
補上實現**:
#include
template
class stackwithmin
bool push(datatype data)
elseelse
}
return
true;
}datatype pop()
else
}datatype getmin()
return _min;
}private:
datatype* _datas;
int _capacity;
int _top;
datatype _min;
};
旭說資料結構之佇列
佇列又是一種特殊的線性表。特殊之處在於 想要移除線性表中的元素,必須從首元素開始移除 想要往線性表中插入元素,必須在尾部進行插入 與棧遵循的先入後出原則不同,它遵循的是先入先出的原則。拿到乙個佇列,我們可以對它進行入隊 隊尾插入 和出隊 隊首刪除 操作。假如我想要使用佇列,我肯定要先拿到乙個佇列。如...
旭說資料結構之樹的簡介
線性表是一對一的資料結構。樹是一對多的資料結構。樹的定義是 有n n 0 個結點,樹的定義中允許結點個數為0的情形,結點之間有一定的關係,什麼關係呢,1.當n 0 時,我們稱這個樹為空樹 2.當 n 0 時,有乙個特定的結點被稱之為根節點 root 然後其餘結點都連在根結點的下面並進行延伸,與根節點...
旭說資料結構之鍊錶補充(雙向鍊錶)
上文已經介紹了鍊錶中的單鏈表,這裡我們再敘述一下雙向鍊錶 1.雙向鍊錶 對比單鏈表,雙向鍊錶能夠直接找到節點的前驅,也就能從任意乙個節點到達鍊錶的頭結點和尾節點。如下圖所示 下面我們還是從使用的角度出發來定義雙向鍊錶的介面。我想使用乙個雙向鍊錶,那我就new乙個來用。然後我就往裡插入元素。之後我又想...