优先级队列、仿函数和反向迭代器

image-20230112094358779

优先级队列

1.优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。

2.此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。

3.优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。

4.标准容器类vector和deque满足这些需求。默认情况下,如果没有特定的priority_queue类实例化指定容器类,则使用vector。

5.实际数据类型是数组

priority_queue的模拟实现

默认情况下,priority_queue是大堆

框架

template<class T,class Container = vector<T>>
    class class Priority_Queue
	{
    
    
	public:
        //实现
        ......
    private:
    Container _con;

无参的构造(默认构造)

Priority_Queue()//会调用适配器的默认构造
		{
    
    }

迭代器区间构造

		template<class InputIterator>
		Priority_Queue(InputIterator first, InputIterator last)
			:_con(first,last)
		{
    
    
			//向下建堆
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
    
    
				adjust_down(i);//向下调整
			}
		}

向上调整

void adjust_up(size_t child)
		{
    
    
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
    
    
				if (_con[child] > _con[parent])//建大堆
				{
    
    
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
    
    
					break;
				}
			}
		}

image-20230111181717938

向下调整

		void adjust_down(size_t parent)
		{
    
    
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
    
    
				if (child + 1 < _con.size() && _con[child + 1] > _con[child])//大堆
				{
    
    
					child++;
				}
				if (_con[child]> _con[parent])//大堆
				{
    
    
					swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
					
				}
				else
				{
    
    
					break;
				}
			}
		}

image-20230111181753777

插入

		void push(const T& val)
		{
    
    
			_con.push_back(val);
			adjust_up(_con.size() - 1);//把新插入的儿子的下标传过去,然后向上调整
		}

删除

		void pop()
		{
    
    
			swap(_con[0], _con[_con.size() - 1]);//头删-先和最后的儿子交换,然后再尾删
			_con.pop_back();
			adjust_down(0);//向下调整
		 }

取堆顶的数据

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

求数据个数

		size_t size() const
		{
    
    
			return _con.size();
		}

验满

		bool empty()const
		{
    
    
			return _con.empty();
		}

初识仿函数

通过查阅优先级队列的大堆小堆的实现,大于和小于的地方使用的是仿函数里面的比较。仿函数引用的头文件是 #include< functional >

模拟实现

template<class T>
	class less//大根堆
	{
    
    
	public:
		bool operator()(const T& x,const T& y)const
		{
    
    
			return x < y;//后一个是否小于前一个
		}
	};
	template<class T>
	class greater//小根堆
	{
    
    
	public:
		bool operator()(const T& x, const T& y)const
		{
    
    
			return x > y;//后一个是否大于前一个
		}
	};

1.这里的仿函数的大于小于的比较由仿函数的实现决定,而底层不会暴露出来,更安全。

2.仿函数针对的是泛型,用法更广泛。比如比较的是内嵌类型,那么天然的>或者<可能可以满足,而对应自定义类型的比较,就需要自己去实现然后封装起来。

比如用在冒泡排序,以往的冒泡排序的实现,具体的升序和降序由模拟实现中的>或<号决定,而这符号等于暴露了底层实现。那么这里可以通过仿函数隐藏起来,不保留底层实现。

image-20230111203406289

仿函数更改后的向上调整

		void adjust_up(size_t child)
		{
    
    
			Compare Com;
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
    
    
				//if (_con[parent]<_con[child])//建大堆
				  if(Com(_con[parent],_con[child]))
				{
    
    
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
    
    
					break;
				}
			}
		}

仿函数更改后的向下调整

void adjust_down(size_t parent)
		{
    
    
			Compare Com;
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
    
    
				//if (child + 1 < _con.size() && _con[child] < _con[child+1])//大堆
				if(child+1<_con.size()&&Com(_con[child],_con[child+1]))
				{
    
    
					child++;
				}
				//if (_con[parent]> _con[child])//大堆
				if(Com(_con[parent],_con[child]))
				{
    
    
					swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
					
				}
				else
				{
    
    
					break;
				}
			}
		}

image-20230111204637666

反向迭代器

反向迭代器和迭代器的起始是对称的,但反向迭代器在解引用的时候有所不同,取数据时先反向迭代器–再解引用。

image-20230112093236573

image-20230112093248833

具体实现

template<class Iterator, class Ref, class Ptr>
class ReverseIterator
{
    
    
	typedef ReverseIterator<Iterator, Ref, Ptr> Self;

public:
	ReverseIterator(Iterator it)
		:_it(it)
	{
    
    }

	Ref operator*()
	{
    
    
		Iterator tmp = _it;
		return *(--tmp);
	}

	Ptr operator->()
	{
    
    
		return &(operator*());
	}

	Self& operator++()//前置++
	{
    
    
		--_it;
		return *this;
	}

	Self& operator--()//前置--
	{
    
    
		++_it;
		return *this;
	}

	Self operator++(int)//后置++
	{
    
    
		Iterator tmp = _it;
		++_it;
		return tmp;
	}

	Self operator--(int)//后置--
	{
    
    
		Iterator tmp = _it;
		--_it;
		return tmp;
	}

	bool operator!= (const Self& s) const
	{
    
    
		return _it != s._it;
	}

	bool operator==(const Self& s)const
	{
    
    
		return _it == s._it;
	}
private:
	Iterator _it;
};

list里面对反向迭代器的适配

image-20230112091913394

猜你喜欢

转载自blog.csdn.net/m0_71841506/article/details/128654194
今日推荐