STL源码刨析_stack & _queue

目录

一. 介绍

1. stack 介绍

2. queue 介绍

二. 模拟实现

1. stack 模拟实现

2. queue 模拟实现

三. deque

1. deque 接口

2. 底层


一. 介绍

1. stack 介绍

stack(栈)是一种容器适配器,它提供了一种后进先出(LIFO)的数据结构。以下是关于stack的介绍:

  • 特点:stack是一种具有特定功能的容器,它只能通过顶部(或称为栈顶)进行元素的插入和删除操作。插入操作称为入栈(push),删除操作称为出栈(pop)。对stack的访问受到限制,只能访问栈顶的元素。
  • 使用容器:stack的实现通过在内部使用其他容器来存储元素。默认情况下,STL中的stack使用deque(双端队列)作为底层容器。也可以通过指定其他容器类型来创建自定义底层容器的stack。
  • 基本操作:除了入栈和出栈操作外,stack还提供了其他一些常用的操作,如访问栈顶元素(top)、判断栈是否为空(empty)以及获取栈的大小(size)。
  • 不支持随机访问:与向量(vector)和列表(list)等容器不同,stack不支持通过索引进行随机访问。只能访问栈顶元素,且只能进行入栈和出栈操作。
  • 适用性:stack通常用于一些需要后进先出操作的场景,如逆序遍历、回溯算法、函数调用堆栈等。由于其简洁性和固定操作的特性,在许多算法和数据结构中都能够发挥作用。

总体上,stack是一种功能简单而强大的容器适配器,可用于实现后进先出的数据结构。通过提供入栈、出栈、访问栈顶等操作,stack提供了一种方便且高效的方式来管理数据。

2. queue 介绍

queue(队列)是一种容器适配器,它提供了一种先进先出(FIFO)的数据结构。以下是关于queue的介绍:

  • 特点:queue是一种具有特定功能的容器,它在队尾进行元素的插入操作,而在队头进行元素的删除操作。插入操作称为入队(push),删除操作称为出队(pop)。队列中的元素按照先进先出的顺序进行处理。
  • 使用容器:queue的实现通过在内部使用其他容器来存储元素。默认情况下,STL中的queue使用deque(双端队列)作为底层容器。也可以通过指定其他容器类型来创建自定义底层容器的queue。
  • 基本操作:除了入队和出队操作外,queue还提供了其他一些常用的操作,如访问队头元素(front)、访问队尾元素(back)、判断队列是否为空(empty)以及获取队列的大小(size)。
  • 不支持随机访问:与向量(vector)和列表(list)等容器不同,queue不支持通过索引进行随机访问。只能访问队头和队尾的元素,且只能进行入队和出队操作。
  • 适用性:queue通常用于一些需要先进先出操作的场景,如任务调度、事件处理、缓冲区管理等。通过提供入队、出队、访问队头和队尾的操作,queue提供了一种方便且高效的方式来管理数据。

总体上,queue是一种功能简单而强大的容器适配器,可用于实现先进先出的数据结构。通过提供入队、出队、访问队头和队尾等操作,queue提供了一种方便且高效的方式来管理数据。

二. 模拟实现

我们的 stack 和 queue 都是适配器,所以我们实现就不用很麻烦,我们前面也写过 stack 和 queue,我们知道什么容器适合 stack 和 queue 那么我们这次就使用 vector 来适配 stack 使用 list 来适配 queue。

1. stack 模拟实现

这里我们模拟实现的逻辑就是复用,我们的 stack 的类里面有一个 vector 的对象,但是我们不一定使用 vector 我们还可以使用 list, 所以我们的 stack 的模板可以多传一个参数,来表示我们适配的容器时使用什么容器,然后我们可以复用我们容器的函数,例如我们的 stack 里面有一个 push 但是我们的 stack 只有一个入口和出口,还是后进先出的,所以我们使用的容器是 vector 的话,我们就可以使用 push_back 和 pop_back。

下面我们也就不一个一个介绍了,我们直接看代码~

    template>
	class stack
	{
	public:
		stack() {};

		~stack() {};

		void push(const T& val)
		{
			_con.push_back(val);
		}

		void pop()
		{
			_con.pop_back();
		}

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

		T& top()
		{
			return _con.back();
		}

		bool empty()
		{
			return _con.empty();
		}
	private:
		Container _con;
	};

2. queue 模拟实现

queue 和 stack 其实基本都是一样的,但是我们的 queue 的容器就不能使用 vector 了,其实并不是不能使用,而是使用 vector 的效率很低,因为我们的 vector 需要头删、尾插, 我们知道我们的 vector 的中间或者头部的插入删除都是很慢的,所以我们的 queue 可以使用 list ,我们下main还是直接看代码。

	template>
	class queue
	{
	public:
		queue() {};

		~queue() {};

		void push(const T& val)
		{
			_con.push_back(val);
		}

		void pop()
		{
			_con.pop_front();
		}

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

		T& front()
		{
			return _con.front();
		}

		T& back()
		{
			return _con.back();
		}

		bool empty()
		{
			return _con.empty();
		}
	private:
		Container _con;
	};

模拟实现就完了~

三. deque

deque 是一个既可以随机插入删除,也可以支持随机访问的一个容器,但是我们经常宾补怎么使用它,我们的 deque 被作为 stack 和 queue 的默认容器,可是为什么选择 deque 呢?我们下面简单的了解一下 deque。

1. deque 接口

STL源码刨析_stack & _queue_第1张图片其他的接口我们就不看了,我们主要看一下这些接口 

 我们看到上面,我们的 deque 即提供了头插,头删,还有我们的 operator[],说明我们的 deque 的头插和头删的效率并不慢,而且还提供了我们的 operator[],说明我们的 deque 还支持随机访问,所以说它就是很适合做 stack 和 queue 的容器。

2. 底层

我们这里说一下它的底层,我们的 deque 的底层是一个一个连续的空间,而我们还有一个数组就是专门管理这些连续的空间,就像下面这样

STL源码刨析_stack & _queue_第2张图片

然后我们头插就向最前面的那个数组插入,尾插就像后面的插入,如果满了,就扩容,到管理的那个数组里面在加一个指针,指向一块新的数组,总的来说 deque 是很复杂的,这么两句也说不清楚,但是 deque 其实并不是很重要,我们不需要掌握它,所以了解一下即可

源码在 码云 里面。 

你可能感兴趣的:(c++,开发语言)