当一个元素被插入时,它的优先级被设置,有三个固定值:低、中、高。一旦被放入队列,元素的优先级就不能改变。
如果没有具有任何优先级的元素,那么指向尾部的相应指针必须为空。
无参数的构造函数,复制,移动。
复制和移动分配运算符。
确定队列中具有特定优先级的元素的数量和元素的总数量。
检查是否有空队列。
插入一个具有价值和优先权的元素。
从队列中删除一个元素。
获得关于队列头部元素的优先级和价值的信息。
通过菜单实现的头部程序应检查上述所有方法的操作。
#include <iostream>
#include <list>
#include <algorithm>
enum class Priority
{
Low,
Medium,
High
};
template <typename T, typename List = std::list<std::pair<T, Priority>>>
class PriorityQueue
{
public:
typedef List list_type;
typedef typename List::value_type value_type;
typedef typename List::size_type size_type;
typedef typename List::iterator iterator;
typedef typename List::const_iterator const_iterator;
PriorityQueue() : _high_end(_list.end()), _medium_end(_list.end()) {}
PriorityQueue(const PriorityQueue &other) : _list(other._list)
{
init();
}
PriorityQueue(PriorityQueue &&other)
: _list(std::move(other._list))
{
init();
other._high_end = other._list.end();
other._medium_end = other._list.end();
}
PriorityQueue(const std::initializer_list<value_type> &list) : _high_end(_list.end()), _medium_end(_list.end())
{
for (const auto &[value, priority] : list)
insert(value, priority);
}
~PriorityQueue() {}
PriorityQueue &operator=(const PriorityQueue &other)
{
if (this != &other)
{
_list = other._list;
init();
}
return *this;
}
PriorityQueue &operator=(PriorityQueue &&other)
{
_list = std::move(other._list);
init();
other._high_end = other._list.end();
other._medium_end = other._list.end();
return *this;
}
iterator begin(Priority priority)
{
iterator it;
switch (priority)
{
case Priority::Low:
it = _medium_end;
break;
case Priority::Medium:
it = _high_end;
break;
case Priority::High:
it = _list.begin();
break;
}
return it;
}
iterator end(Priority priority)
{
iterator it;
switch (priority)
{
case Priority::Low:
it = _list.end();
break;
case Priority::Medium:
it = _medium_end;
break;
case Priority::High:
it = _high_end;
break;
}
return it;
}
const_iterator begin(Priority priority) const
{
const_iterator it;
switch (priority)
{
case Priority::Low:
it = _medium_end;
break;
case Priority::Medium:
it = _high_end;
break;
case Priority::High:
it = _list.begin();
break;
}
return it;
}
const_iterator end(Priority priority) const
{
const_iterator it;
switch (priority)
{
case Priority::Low:
it = _list.end();
break;
case Priority::Medium:
it = _medium_end;
break;
case Priority::High:
it = _high_end;
break;
}
return it;
}
bool empty() const { return _list.empty(); }
size_type size() const { return _list.size(); }
size_type size(Priority priority) const
{
size_type sz = 0;
switch (priority)
{
case Priority::Low:
sz = std::distance(const_iterator(_medium_end), _list.end());
break;
case Priority::Medium:
sz = std::distance(_high_end, _medium_end);
break;
case Priority::High:
sz = std::distance(_list.begin(), const_iterator(_high_end));
break;
}
return sz;
}
iterator insert(const T &value, Priority priority)
{
iterator it;
switch (priority)
{
case Priority::Low:
{
auto sz_medium = size(Priority::Medium);
auto sz_low = size(Priority::Low);
it = _list.insert(_list.end(), std::make_pair(value, priority));
if (sz_low == 0)
{
_medium_end = it;
if (sz_medium == 0)
_high_end = it;
}
break;
}
case Priority::Medium:
{
auto sz_medium = size(Priority::Medium);
it = _list.insert(_medium_end, std::make_pair(value, priority));
if (sz_medium == 0)
_high_end = it;
break;
}
case Priority::High:
it = _list.insert(_high_end, std::make_pair(value, priority));
break;
}
return it;
}
iterator erase(iterator pos)
{
iterator it = _list.erase(pos);
if (pos == _high_end)
_high_end = it;
if (pos == _medium_end)
_medium_end = it;
return it;
}
void remove(const T &value)
{
auto it = _list.begin();
while (1)
{
it = find_if(it, _list.end(), [value](const auto &v)
{ return v.first == value; });
if (it == _list.end())
break;
it = erase(it);
}
}
value_type front() const
{
return _list.front();
}
private:
void init()
{
_high_end = std::find_if(_list.begin(), _list.end(), [](const auto &v)
{ return v.second != Priority::High; });
_medium_end = std::find_if(_high_end, _list.end(), [](const auto &v)
{ return v.second != Priority::Medium; });
}
list_type _list;
iterator _high_end;
iterator _medium_end;
};
std::ostream &operator<<(std::ostream &os, Priority priority)
{
switch (priority)
{
case Priority::Low:
os << "Low";
break;
case Priority::Medium:
os << "Medium";
break;
case Priority::High:
os << "High";
break;
}
return os;
}
template <typename T, typename List>
std::ostream &operator<<(std::ostream &os, const PriorityQueue<T, List> &q)
{
os << "{ ";
for (auto priority : {Priority::High, Priority::Medium, Priority::Low})
{
if (priority != Priority::High)
os << ", ";
os << priority << ": [";
for (auto it = q.begin(priority); it != q.end(priority); ++it)
{
if (it != q.begin(priority))
os << ", ";
os << it->first;
}
os << "]";
}
os << "}";
return os;
}
int main()
{
PriorityQueue<int> q = {{1, Priority::Low}, {2, Priority::Medium}, {3, Priority::High}, {4, Priority::High}, {5, Priority::Medium}, {6, Priority::Low}};
std::cout << "q = " << q << std::endl;
PriorityQueue<int> p1 = q;
std::cout << "after p1 = q:\n";
std::cout << "p1 = " << p1 << std::endl;
PriorityQueue<int> p2 = std::move(p1);
std::cout << "after p2 = std::move(p1):\n";
std::cout << "p2 = " << p2 << std::endl;
std::cout << "p1 = " << p1 << std::endl;
q.insert(5, Priority::High);
std::cout << "after q.insert(5, Priority::Hight):\n";
std::cout << "q = " << q << std::endl;
q.remove(5);
std::cout << "after q.remove(5):\n";
std::cout << "q = " << q << std::endl;
std::cout << "q.front(): {" << q.front().first << ", " << q.front().second << "}" << std::endl;
return 0;
}
$ g++ -Wall -std=c++17 main.cpp
$ ./a.out
q = { High: [3, 4], Medium: [2, 5], Low: [1, 6]}
after p1 = q:
p1 = { High: [3, 4], Medium: [2, 5], Low: [1, 6]}
after p2 = std::move(p1):
p2 = { High: [3, 4], Medium: [2, 5], Low: [1, 6]}
p1 = { High: [], Medium: [], Low: []}
after q.insert(5, Priority::Hight):
q = { High: [3, 4, 5], Medium: [2, 5], Low: [1, 6]}
after q.remove(5):
q = { High: [3, 4], Medium: [2], Low: [1, 6]}
front: {3, High}
给代码会失去学习的效果。
我的想法:
1,先实现一个单向链表。实现其基本方法。
2,优先级的改造。将存储的数据部分增加一个优先级的值。
3,改造插入算法。添加更多操作。
#include <iostream>
#include <string>
#include <queue>
using namespace std;
void print_pqueue (priority_queue<int> pq) {
// Prints the Priority Queue
priority_queue<int> copy_q = pq;
cout << "Priority Queue : ";
while (!copy_q.empty()) {
cout << copy_q.top() << " ";
copy_q.pop();
}
cout << "\n";
}
int main() {
// Program demonstrating use of Priority Queue
// methods
// Create an empty priority queue of integers
priority_queue<int> queue_int;
// Is the Queue empty now? Yes!
cout << "Is the Queue empty now? : " << (queue_int.empty() ? "Yes" : "No") << endl;
// Let's add some elements!
cout << "Adding some elements...\n";
queue_int.push(100);
queue_int.push(200);
queue_int.push(400);
queue_int.push(50);
cout << "Number of elements : " << queue_int.size() << endl;
cout << "Top element : " << queue_int.top() << endl << endl;
print_pqueue(queue_int);
cout << "Popping element from the top...\n\n";
queue_int.pop();
print_pqueue(queue_int);
return 0;
}