【C++】优先级队列的基本概念以及其模拟实现

文章目录

  • 补充知识:仿函数
  • 一、优先级队列:
    • 1.引入
    • 2.介绍
  • 二、priority_queue的模拟实现
    • 1.大体框架
    • 2.私有成员函数:
      • 1.向下调整(AdjustDown)
      • 2.向上调整(AdjustUp)
    • 3.公有成员函数
      • 1大小(size).
      • 2是否为空(empty).
      • 3.移除堆顶的元素(pop)
      • 4.元素插入(push)
      • 5.堆顶的元素(top)
      • 6.构造函数
        • 1.默认无参构造
        • 2.迭代器构造


补充知识:仿函数

C++仿函数(function object)是一种可以像函数一样调用的对象。仿函数通常是一个类,它重载了函数调用运算符operator(),使得对象可以被调用。

【C++】优先级队列的基本概念以及其模拟实现_第1张图片

一、优先级队列:

1.引入

优先级队列(Priority Queue)在底层实现上使用了一种称为堆(Heap)的数据结构,通常使用数组(比如C++中的std::vector)来表示。堆是一种完全二叉树数据结构,具有以下特点:

  1. 堆是一个完全二叉树,也就是说除了最底层,其他层都必须是完全填满的,最底层的节点依次从左到右填充。
    2.堆中的每个节点的值都大于等于(或小于等于)其子节点的值,这就是所谓的堆序性质。

2.介绍

  1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。
  2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。
  3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类
  4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭
    代器访问,并支持以下操作:
    empty():检测容器是否为空
    size():返回容器中有效元素个数
    front():返回容器中第一个元素的引用
    push_back():在容器尾部插入元素
    pop_back():删除容器尾部元素
  5. 标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。

虽然底层实现中使用了vector,但优先级队列仍然保持了队列的特性,即根据优先级出队元素

二、priority_queue的模拟实现

1.大体框架

namespace simulation {
template<class T, class Container = vector<T>, class Compare = less<T>>
	//Compare这里传的是仿函数,默认为系统里自带的less仿函数,也可以自己添加
	//用于比较大小,Container为底层实现容器,默认为vector
	class priority_queue {

	private://私有成员函数
		void AdjustDown(int parent) {	 
		}
		void AdjustUp(int child) {
				 }

	public://公有成员函数
		void pop() { }
		void push(const T & x) {}
		const T& top() { }
		bool empty() {}
		size_t size() {}
		priority_queue(){}

	private:
		Container _con;//成员变量
		 
	};

2.私有成员函数:

1.向下调整(AdjustDown)

【C++】优先级队列的基本概念以及其模拟实现_第2张图片
图中是在建小堆,但我们代码以大堆为例,除了大于小于的方向不同,但逻辑是一样的

void AdjustDown(int parent) {
			//向下调整条件:
	       // 左右子树都是大堆/小堆
			int child = parent * 2 + 1;
			Compare com;//仿函数的实例化
			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;
				}
			}
		}

2.向上调整(AdjustUp)

【C++】优先级队列的基本概念以及其模拟实现_第3张图片
【C++】优先级队列的基本概念以及其模拟实现_第4张图片

void AdjustUp(int child) {
			//向上调整条件:
	    // 除了child这个位置前面的数据构成堆
			int parent = (child - 1) / 2;
			Compare com;
			while (child > 0) {
				if (com(_con[parent], _con[child])) {
					swap(_con[parent], _con[child]);
					child = parent;
					//接着向上
					parent = (child - 1) / 2;
				}
				else {
					break;
				}
			}
		}

3.公有成员函数

1大小(size).

2是否为空(empty).

3.移除堆顶的元素(pop)

【C++】优先级队列的基本概念以及其模拟实现_第5张图片

void pop() {
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}

4.元素插入(push)

【C++】优先级队列的基本概念以及其模拟实现_第6张图片

void push(const T& x) {
			_con.push_back(x);
			//新元素向上调整
			AdjustUp(_con.size() - 1);
		}

5.堆顶的元素(top)

const T& top() {
			return _con[0];
		}

6.构造函数

1.默认无参构造

priority_queue() {
//内容可以什么都不写,因为初始化会去内置类型不用管,自定义类型会去调用其
//默认构造函数,这里会直接调用成员变量_con的默认构造
//当你写了迭代器构造后,这个无参构造你必须要有,因为当你写了一个构造函数
//以后,编译器就不会自己再生成默认构造函数
		}

2.迭代器构造

template<class InputIterator>
		priority_queue(InputIterator first, InputIterator last) {
			while (first != last) {
				_con.push_back(*first);
				++first;
			}
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--) {
				AdjustDown(i);
			}
		}

你可能感兴趣的:(c++,java,rpc)