stack和queue被称为适配器容器,原因正是因为他们的底层并没有自己实现,而是用vector,list和deque等,下篇我将介绍deque容器
stack和queue的框架
template<class T,class Container=list<T>>
class queue{
public:
void push(const T& x)
{_con.push_back(x);}
void pop()
{_con.pop_front();}
size_t size()
{return _con.size();}
bool empty()
{return _con.empty();}
T& front()
{return _con.front();}
T& back()
{return _con.back();}
private:
Container _con;
};
namespace xiaobo
{
template<class T, class Container=vector<T>>
class stack
{
public:
void push(const T& x)
{_con.push_back(x);}
void pop()
{_con.pop_back();}
size_t size()
{return _con.size();}
bool empty()
{return _con.empty();}
T& top()
{return _con.back();}
private:
Container _con;//接收自定义类型(list,vector等)
};
}
可以看出stack和queue底层逻辑完全一样,都是借花献佛利用模板灵活使用成员变量,让这样的代码可以焕然一新。因此我们将学一种更加完美更加棒的数据结构priority_queue优先队列
priority_queue基本框架
namespace xiaobo
{
//class T容器的内置类型,class Container容器类型=vector<T>缺省值
template<class T,class Container=vector<T>>
class priority_queue
{
bool empty()
{
return _con.empty();
}
size_t size()
{
return _con.size();
}
T& top()
{
return _con[0];
}
void push(const T& x);
void pop();
private:
Container _con;
};
}
仅看框架感觉都是换汤不换药的容器罢了,好像什么都没什么好学的。其实不然接下来将会炒冷饭,且接受新的知识,让你感到伟人的智慧
push()
priority_queue为堆排,因此应该在push时就排序
void AdJustup(int leaf)
{
int child = leaf;
int parent = (child - 1) / 2;
while (child > 0)//防止越界
{
if (_con[parent] < _con[child])//升序
{
swap(_con[parent], _con[child]);//交换
child = parent;
parent = (child - 1) / 2;
}
else
break;
//由于push到_con[_con.size()-1],只有最后一个值被改变,其他值依然是有序的
//只用看住一个值即可
}
}
void push(const T& x)
{
AdJustup(_con.size() - 1);
}
pop()
头删er
//向下堆排
void AdJustDown(int root)
{
int parent = root;
int child = parent * 2 + 1;
while (child < _con.size())
{
//防止child+1超出范围,找出子节点中最大的以便交换
if (child + 1 < _con.size() && _con[child] < _con[child + 1])
{
++child;
}
if (_con[parent] < _con[child])
{
swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
void pop()
{
//如果直接头删便需要,整个堆重新排序(效率极低)
//如果交换头部和尾部元素,只用一次向下排序即可
swap(_con[0], _con[_con.size() - 1]);
AdJustDown(0);
_con.pop_back();//最后删除该元素
}
priority_queue<int,vector<int>,greater<int>> pq;
这个为升序,前者为降序他们中间唯一的区别只有向下堆排和向上堆排中的大于和小于区别罢了,其他则是一模一样,我们不可能为了一个符号的再写一个新的,浪费时间且低效,因此再数据结构中有这样一个天降猛男
template<class T>
struct less//小于
{
bool operator()(const T& x1, const T& x2)
{
return x1 < x2;
}
};
template<class T>
struct greater//大于
{
bool operator()(const T& x1, const T& x2)
{
return x1 > x2;
}
};
用类分别封装大于和小于,这样就可以在使用中随意调换升序和降序
//模板compare装着less类或greater类
template<class T,class Container=vector<T>,class compare=less<T>>
class priority_queue
{
void Adjustup(size_t sz)
{
compare com;//模板形成对象
int child = sz - 1;
int parent = (child - 1) / 2;
while (child > 0)
{
if (com(_con[parent], _con[child]))//用对象的符号重载形成大于或小于
{
swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
//同理
void AdustDown(int root)
{
compare com;
int parent = root;
int child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
++child;
if (com(_con[parent] , _con[child]))
{
swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
}
这里补充一些小知识:
struct和class除了访问限定符以外全部相同
一部分公有一部分私有用class,全部公有用struct