C++:栈与队列

C++:栈与队列_第1张图片

---------------"你不会因为懒惰而悔恨" 


 (1)栈与队列的功能:

①实现:

 关于STL库中,栈 和队列的功能和 当初用C实现栈和队列的功能相似。

C++:栈与队列_第2张图片

C++:栈与队列_第3张图片 

其中,最值得注意的,就是红色标记处------容器

我们知道,不管是栈、队列 它的底层,既可以用顺序表、也可以用链表来实现。

C++:栈与队列_第4张图片 同一类型,不同容器。 

②访问:

不同于list\vector,它们拥有自己的迭代器,支持访问。队列和栈都不支持随机访问。

我们知道,栈的原则是:FILO(先进后出,后进先出)。

C++:栈与队列_第5张图片

 

 队列的原则是:FIFO(先进先出,后进后出)。

C++:栈与队列_第6张图片        

 不过与stack不同的是,queue还封装了取队尾的元素,而stack没有取栈底的元素。

C++:栈与队列_第7张图片

 简单把栈和队列介绍到这里把。


(2)栈和队列的模拟实现:

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 
	};
}

下面是测试:

C++:栈与队列_第8张图片

 这种设计很大的优点在于,利用容器(Container)实现复用。


Queue: 

	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;
	};

C++:栈与队列_第9张图片

当然可以看出,容器在这里面的引入,让代码变得简单易懂。 

当然,使用容器内,也没有封装的函数,肯定达不到效果!!!

C++:栈与队列_第10张图片


(3)优先级队列 

优先级队列,顾名思义,它和队列最大的区别就在于优先级。

在linux中的进程调度中,优先级高的会被先调度,反之低的则会被后调度。其底层的原理,也就是依靠着优先级队列。

 

优先级队列除开容器和上述队列、栈无区别外(默认容器使用vector),还加了一组Compare是一种适配器!!! 

①greater和less适配器> 

C++:栈与队列_第11张图片 

直观上来看,优先级队列,默认认为“数字大的”,优先级高,所以先输出。 

greater:

C++:栈与队列_第12张图片 

less:

C++:栈与队列_第13张图片


②排序:

优先级队列最重要的就是数据的取出都是经过排序的,而其中底层的默认实现容器,又是vector(数组)。

所以,在实现排序的方式上,选择了堆排序(默认情况下,选择大堆排序)。


(4)优先级队列模拟实现:
 

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++:栈与队列_第14张图片 

 如果对堆排序并不清楚的读者,可以先去看看堆排序的原理。再来看看这篇文章,会有所受益。

 ②适配器:

关于适配器,可以简单的理解为,c++中一个特殊的语法(仿函数).

仿函数:让一个类像 函数一样去使用。

C++:栈与队列_第15张图片

 

在名域内,封装比较函数:

//排降序----->大堆
	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;
		}
	};

C++:栈与队列_第16张图片

 

大堆:
C++:栈与队列_第17张图片

小堆:

C++:栈与队列_第18张图片 


总结:

本篇内容较为简单,且都是之前的基础知识。所以也就没啥能总结的。


本篇也就结束啦,希望对诸位读者有益,

感谢你的阅读

祝你好运~

C++:栈与队列_第19张图片

你可能感兴趣的:(C++,大数据)