您好,登錄后才能下訂單哦!
deque中的修改類接口
由于deque是雙端隊列,所以有頭插頭刪和尾插尾刪操作。
下面的棧和隊列的底層都是通過的deque實現(xiàn)的。
為什么要用deque作為其底層數(shù)據(jù)結(jié)構(gòu)呢?
主要是因為:棧和隊列都只需在一頭進行操作,故不需要迭代器,只要具有pushback和popback的功能即可,在元素增長時deque比vector效率更高、內(nèi)存使用率高,所以用deque作為底層數(shù)據(jù)結(jié)構(gòu)更合適。
根據(jù)文檔里的內(nèi)容我們可以看到stack中有這些接口。
在使用時要包含stack頭文件
因為其底層是用deque實現(xiàn)的:所以有關(guān)它的模擬實現(xiàn)也就是對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操作,分別是隊首和隊尾元素。
底層使用堆實現(xiàn)的!
創(chuàng)建優(yōu)先隊列的默認(rèn)是按照大堆(比較參數(shù)是less)方式!也就是說每個根節(jié)點都大于它的孩子節(jié)點。
對于內(nèi)置類型可以直接使用greater比較器,但是對于自定義類型需要提供比較器規(guī)則并在自定義類型中增加> 、<等比較規(guī)則
構(gòu)造函數(shù):std::priority_queue<int, std::vector<int>, std::greater<int> >
third (myints,myints+4);
上例是構(gòu)造了一個小堆類型的優(yōu)先級隊列
它的模板參數(shù)列表:template<class T, class Container=vector<T>, class Compare=less<T>>
所以如果想要用小堆創(chuàng)建對象時要把第三個參數(shù)改為great。
這里我們把庫函數(shù)中的less這個函數(shù)拿來看一下:
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);
}
};
如果在優(yōu)先級隊列內(nèi)存放自定義類型數(shù)據(jù),需要需要用戶提供<、>的重載,有時也要對提供比較器規(guī)則,參考less和greater在庫函數(shù)中的實現(xiàn),即對()進行重載。
模擬實現(xiàn)優(yōu)先級隊列:
namespace mine
{
template <class T, class Container = vector<T>, class Compare = less<T>>//默認(rèn)(less)創(chuàng)建的是大堆
class priority_queue
{
public:
priority_queue()
:c()
{}
template<class Iterator>
priority_queue(Iterator first, Iterator last)//區(qū)間構(gòu)造,將root進行向下調(diào)整
: c(first, last)
{
// 將c中的元素調(diào)整成堆的結(jié)構(gòu)
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);//傳入下標(biāo)
}
void pop()//頭刪的話先將頭元素與最后一個元素交換,把最后一個元素刪掉后再執(zhí)行向下排序
{
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:
//這里的向上調(diào)整和向下調(diào)整都是大堆模式
void AdjustDown(int parent)//向下調(diào)整算法,把較小元素調(diào)整下去
{
int child = parent * 2 + 1;//child代表下標(biāo)
while (child < c.size())
{
//找到以parent為根的較大的孩子
//如果根有右孩子并且左孩子比右孩子小,讓child等于右孩子
//即child此時為較大的孩子
if (child + 1 < c.size() && com(c[child], c[child + 1]))
{
child = child + 1;
}
//如果孩子節(jié)點比父親節(jié)點大則交換
if (com(c[parent], c[child]))
{
swap(c[child], c[parent]);
parent = child;
child = parent * 2 + 1;
}
else
return;
}
}
void AdjustUP(int child)//向上調(diào)整算法,將較大元素調(diào)整上去
{
int parent = (child - 1) >> 1;
while (child)//沒有到根的話繼續(xù)循環(huán)
{
//如果父親節(jié)點比孩子節(jié)點小,交換
//將較大節(jié)點調(diào)整到根位置
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;
};
}
這里最重要的就是向上調(diào)整和向下調(diào)整算法,同時也要注意比較規(guī)則在其中的用法。詳細過程見代碼注釋。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。