stack和queue的模拟实现并不复杂,所以不做过多讲解。
一、stack的模拟实现
. stack.h
cpp
#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace LC
{
template<class T, class Container = vector<T>>
class stack
{
public:
void push(const T& x)
{
_con.push_back(x);
}
const T& top()
{
return _con.back();
}
void pop()
{
_con.pop_back();
}
bool empty()
{
return _con.empty();
}
size_t size()const
{
return _con.size();
}
private:
Container _con;
};
}
. test.cc
cpp
#define _CRT_SECURE_NO_WARNINGS
#include"stack.h"
int main()
{
LC::stack<int> s1;
s1.push(1);
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
cout << "s1.size():" << s1.size() << endl;
while (!s1.empty())
{
cout << s1.top() << " ";
s1.pop();
}
cout << endl;
LC::stack<double> s2;
s2.push(1.1);
s2.push(2.2);
s2.push(3.3);
s2.push(4.4);
s2.push(5.5);
cout << "s2.size():" << s2.size() << endl;
while (!s2.empty())
{
cout << s2.top() << " ";
s2.pop();
}
return 0;
}

二、queue的模拟实现
. queue.h
cpp
#pragma once
#include<iostream>
#include<list>
using namespace std;
namespace LC
{
template<class T, class Container = list<T>>
class queue
{
public:
void push(const T& x)
{
_con.push_back(x);
}
bool empty()
{
return _con.empty();
}
size_t size()const
{
return _con.size();
}
const T& front()
{
return _con.front();
}
const T& back()
{
return _con.back();
}
void pop()
{
_con.pop_front();``
}
private:
Container _con;
};
}
. test.cc
cpp
#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"
int main()
{
LC::queue<double> q1;
q1.push(1);
q1.push(2);
q1.push(3);
q1.push(4);
q1.push(5);
/*q1.push(1.1);
q1.push(2.2);
q1.push(3.3);
q1.push(4.4);
q1.push(5.5);*/
cout << "q1.size():" << q1.size() << endl;
while (!q1.empty())
{
cout << q1.front() << " ";
q1.pop();
}
return 0;
}

三、priority_queue

优先级队列是一种容器适配器,特别设计为其首个元素始终是所包含元素中最大的一个,基于某种严格的弱排序准则。
1. 构造函数
cpp
//传入一个仿函数对象和容器对象
explicit priority_queue (const Compare& comp = Compare(),const Container& ctnr = Container());
//在传入仿函数对象和容器对象的基础上增加了一段迭代器区间
template <class InputIterator>
priority_queue (InputIterator first, InputIterator last,const Compare& comp = Compare(),const Container& ctnr = Container());
2. empty
cpp
//判断优先级队列是否为空
bool empty() const;
3. size
cpp
//返回优先级队列中元素的个数
size_type size() const;
4. top
cpp
//返回的是priority_queue中优先级最高的元素
const value_type& top() const;
5. push
cpp
//插入一个新的元素,并调用push_heap算法进行重新排序
void push (const value_type& val);
6. pop
cpp
//删除priority_queue中优先级最高的元素
void pop();
7. swap
cpp
//交换两个priority_queue对象的内容
void swap (priority_queue& x) noexcept
四、priority_queue的模拟实现
1. 仿函数
cpp
//按降序排序
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
//按升序排序
template<class T>
class Greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
2. 成员变量
cpp
template<class T, class Container = vector<T>, class Compare = Less<T>>
class priority_queue
{
private:
Container _con;
};
3. push
cpp
void push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);//调整优先级
}
4. adjust_up
cpp
void adjust_up(size_t child)
{
Compare _com;
size_t parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[child] > _con[parent])
if (_com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
向上调整,将优先级最大的元素排在队首,利用父子节点的下标关系,比较父子之间的大小,孩子大于(或小于)父亲,孩子往上调整,父亲往下走(交换孩子与父亲的数据),继续下一次判断。_com是仿函数对象,主要是为了便于控制升序,降序。
5. pop
cpp
void pop()
{
swap(_con[0], _con[size() - 1]);
_con.pop_back();
adjust_down(0);
}
删除数据,首先将删除的队首数据调整到队尾,再删除数据,接着向下调整优先级。
6. adjust_down
cpp
void adjust_down(size_t parent)
{
Compare _com;
size_t child = 2 * parent + 1;
while (child < size())
{
//if (child + 1 < size() && _con[child + 1] > _con[child])
if (child + 1 < size() && _com(_con[child], _con[child + 1]))
{
++child;
}
if (_com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
如果右孩子大于左孩子,下标指向右孩子,接着判断孩子是否大于(或小于)父亲,符合条件,交换数据,继续调整,否则,调整完毕,退出循环。
7. top,size,empty
cpp
const T& top()
{
return _con[0];
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
优先级队列的底层结构是堆,所以,这里不做过多讲解,如果还有疑问的话,可以看数据结构------树这篇文章,有更详细的讲解。
五、priority_queue的完整代码
. priority_queue.h
cpp
#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace LC
{
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
class Greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<class T, class Container = vector<T>, class Compare = Less<T>>
class priority_queue
{
public:
void adjust_up(size_t child)
{
Compare _com;
size_t parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[child] > _con[parent])
if (_com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);
}
void adjust_down(size_t parent)
{
Compare _com;
size_t child = 2 * parent + 1;
while (child < size())
{
//if (child + 1 < size() && _con[child + 1] > _con[child])
if (child + 1 < size() && _com(_con[child], _con[child + 1]))
{
++child;
}
if (_com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
void pop()
{
swap(_con[0], _con[size() - 1]);
_con.pop_back();
adjust_down(0);
}
const T& top()
{
return _con[0];
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}
. test.cc
cpp
#define _CRT_SECURE_NO_WARNINGS
#include"priority_queue.h"
void testpriority_queue1()
{
LC::priority_queue<int, vector<int>, LC::Less<int>> q1;
q1.push(1);
q1.push(4);
q1.push(2);
q1.push(7);
q1.push(6);
cout << typeid(q1).name() << endl;
cout << "q1.size():" << q1.size() << endl;
while (!q1.empty())
{
cout << q1.top() << " ";
q1.pop();
}
}
int main()
{
testpriority_queue1();
return 0;
}