---------------"你不会因为懒惰而悔恨"
关于STL库中,栈 和队列的功能和 当初用C实现栈和队列的功能相似。
其中,最值得注意的,就是红色标记处------容器。
我们知道,不管是栈、队列 它的底层,既可以用顺序表、也可以用链表来实现。
不同于list\vector,它们拥有自己的迭代器,支持访问。队列和栈都不支持随机访问。
我们知道,栈的原则是:FILO(先进后出,后进先出)。
队列的原则是:FIFO(先进先出,后进后出)。
不过与stack不同的是,queue还封装了取队尾的元素,而stack没有取栈底的元素。
简单把栈和队列介绍到这里把。
namespace dy
{
template> //缺省 这里给的是数据结构中 厉害的双端队列
class stack
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
//栈顶数据
T& top()
{
return _con.back(); //vector 和 list 都有back
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con; //交给Contaniner
};
}
下面是测试:
这种设计很大的优点在于,利用容器(Container)实现复用。
template >
class queue
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
//队头出
_con.pop_front();
}
//队头
T& front()
{
return _con.front();
}
//队尾
T& back()
{
return _con.back();
}
bool empty()
{
return _con.empty();
}
size_t size()
{
return _con.size();
}
private:
Container _con;
};
当然可以看出,容器在这里面的引入,让代码变得简单易懂。
当然,使用容器内,也没有封装的函数,肯定达不到效果!!!
优先级队列,顾名思义,它和队列最大的区别就在于优先级。
在linux中的进程调度中,优先级高的会被先调度,反之低的则会被后调度。其底层的原理,也就是依靠着优先级队列。
优先级队列除开容器和上述队列、栈无区别外(默认容器使用vector),还加了一组Compare是一种适配器!!!
直观上来看,优先级队列,默认认为“数字大的”,优先级高,所以先输出。
优先级队列最重要的就是数据的取出都是经过排序的,而其中底层的默认实现容器,又是vector(数组)。
所以,在实现排序的方式上,选择了堆排序(默认情况下,选择大堆排序)。
template>
class priority_queue
{
public:
void AdjustUp(size_t child)
{
//通过 子节点 找父亲节点
size_t parent = (child - 1) / 2;
//直到child 调整到0节点处
while (child > 0)
{
//因为调整大堆 所以 要把数字大的数 往上换
if (_con[parent] < _con[child])
{
swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
//否则就不用继续走下去了
break;
}
}
}
//为了不破坏堆的结构, 所以采用堆排序的插入方式
void push(const T& x)
{
_con.push_back(x);
//进行向上调整法
AdjustUp(_con.size()-1);
}
//采用堆排序的 删除方式
//删除堆顶的 即 堆顶的数 和最后一个数互换 并向下调整形成新堆
void Adjustdown(size_t parent)
{
size_t child = parent * 2 + 1;
//孩子下标 不超过节点个数
while (child < _con.size())
{
//调整大堆 ----> 比较两孩子谁更大
//当然也有可能没有右孩子
if (child + 1 < _con.size() && _con[child + 1] > _con[child])
{
child+=1;
}
//大的往上换
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]);
_con.pop_back();
Adjustdown(0);
}
//返回堆顶的数据
T& top()
{
return _con[0];
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
如果对堆排序并不清楚的读者,可以先去看看堆排序的原理。再来看看这篇文章,会有所受益。
关于适配器,可以简单的理解为,c++中一个特殊的语法(仿函数).
在名域内,封装比较函数:
//排降序----->大堆
template
struct less
{
//parent child
bool operator()(const T& r, const T& l)
{
return r < l;
}
};
//排升序序 ----->小堆
template
struct greater
{
bool operator()(const T& r, const T& l)
{
return r > l;
}
};
小堆:
本篇内容较为简单,且都是之前的基础知识。所以也就没啥能总结的。
本篇也就结束啦,希望对诸位读者有益,
感谢你的阅读
祝你好运~