deque中的修改類接口
因爲deque是雙端隊列,因此有頭插頭刪和尾插尾刪操做。
下面的棧和隊列的底層都是經過的deque實現的。
爲何要用deque做爲其底層數據結構呢?
主要是由於:棧和隊列都只需在一頭進行操做,故不須要迭代器,只要具備pushback和popback的功能便可,在元素增加時deque比vector效率更高、內存使用率高,因此用deque做爲底層數據結構更合適。算法
根據文檔裏的內容咱們能夠看到stack中有這些接口。
在使用時要包含stack頭文件
由於其底層是用deque實現的:因此有關它的模擬實現也就是對deque的一個封裝。
例如:數據結構
template<class T,class Container=deque<T>> class stack//棧 { public: stack() { } void push(const T&data) { _con.push_back(data); } private: Container _con; }
注意隊列不一樣的是由front和back操做,分別是隊首和隊尾元素。app
底層使用堆實現的!
建立優先隊列的默認是按照大堆(比較參數是less)方式!也就是說每一個根節點都大於它的孩子節點。less
構造函數:std::priority_queue<int, std::vector<int>, std::greater<int> >
third (myints,myints+4);
上例是構造了一個小堆類型的優先級隊列
它的模板參數列表:template<class T, class Container=vector<T>, class Compare=less<T>>
因此若是想要用小堆建立對象時要把第三個參數改成great。ide
這裏咱們把庫函數中的less這個函數拿來看一下:函數
template<class _Ty = void> struct less : public binary_function<_Ty, _Ty, bool> { // functor for operator< bool operator()(const _Ty& _Left, const _Ty& _Right) const { // apply operator< to operands return (_Left < _Right); } };
若是在優先級隊列內存放自定義類型數據,須要須要用戶提供<、>的重載,有時也要對提供比較器規則,參考less和greater在庫函數中的實現,即對()進行重載。spa
模擬實現優先級隊列:code
namespace mine { template <class T, class Container = vector<T>, class Compare = less<T>>//默認(less)建立的是大堆 class priority_queue { public: priority_queue() :c() {} template<class Iterator> priority_queue(Iterator first, Iterator last)//區間構造,將root進行向下調整 : c(first, last) { // 將c中的元素調整成堆的結構 int count = c.size(); int root = ((count - 2) >> 1); for (; root >= 0; root--) AdjustDown(root); } void push(const T & data) { c.push_back(data); AdjustUP(c.size()-1);//傳入下標 } void pop()//頭刪的話先將頭元素與最後一個元素交換,把最後一個元素刪掉後再執行向下排序 { if (empty()) return; else { swap(c.front(), c.back()); c.pop_back(); AdjustDown(0); } } int size()const { return c.size(); } bool empty()const { return c.empty(); } const T & top()const { return c.front(); } private: //這裏的向上調整和向下調整都是大堆模式 void AdjustDown(int parent)//向下調整算法,把較小元素調整下去 { int child = parent * 2 + 1;//child表明下標 while (child < c.size()) { //找到以parent爲根的較大的孩子 //若是根有右孩子而且左孩子比右孩子小,讓child等於右孩子 //即child此時爲較大的孩子 if (child + 1 < c.size() && com(c[child], c[child + 1])) { child = child + 1; } //若是孩子節點比父親節點大則交換 if (com(c[parent], c[child])) { swap(c[child], c[parent]); parent = child; child = parent * 2 + 1; } else return; } } void AdjustUP(int child)//向上調整算法,將較大元素調整上去 { int parent = (child - 1) >> 1; while (child)//沒有到根的話繼續循環 { //若是父親節點比孩子節點小,交換 //將較大節點調整到根位置 if (com(c[parent], c[child])) { swap(com(c[parent], c[child])); child = parent; parent = (child - 1) >> 1; } else { return; } } } private: Container c; Compare com; }; }
這裏最重要的就是向上調整和向下調整算法,同時也要注意比較規則在其中的用法。詳細過程見代碼註釋。對象