堆叠在 C++ STL 示例

⚡ 智能摘要

堆叠在 C++ STL 实现了一个 LIFO 容器适配器,该适配器从单个端添加和删除元素,并进行包装。ping 底层序列容器,例如双端队列、向量或列表,用于管理有序数据。

  • 🔘 后进先出原则: std::stack 遵循后进先出 (LIFO) 的顺序,因此最近压入的元素总是第一个被移除的元素。
  • 📦 容器适配器: 栈是对现有序列容器的包装,当没有提供容器类型时,默认使用双端队列。
  • 核心业务: push、pop 和 top 函数分别用于插入一个项目、移除顶部项目和读取顶部项目。
  • 🔍 国家背景调查: empty 和 size 函数分别报告栈是否包含元素以及当前存储了多少个元素。
  • 🔁 额外功能: emplace 和 swap 函数用于就地构建元素和交换两个栈的内容。
  • 🤖 人工智能辅助: GitHub Copilot 等 AI 编码助手可以根据简短的注释生成堆栈推送、弹出和遍历样板代码。

堆叠在 C++ STL

什么是 std::stack?

堆栈是一种基于 LIFO(后进先出)技术的数据结构。std::stack 只允许从一端添加和删除元素。

`std::stack` 类是一个容器适配器。容器对象保存相同数据类型的数据。你可以使用各种序列容器创建栈。如果没有指定容器,则默认使用双端队列容器。容器适配器不支持迭代器,因此不能用于操作数据。

堆栈语法

要创建堆栈,我们必须包括在我们的代码中引入头文件。然后我们使用这个语法来定义 std::stack:

template <class Type, class Container = deque<Type> > class stack;
  • 类型 – 是 std::stack 中包含的元素的类型。它可以是任何有效的 C++ 类型甚至是用户定义的类型。
  • 容器 – 是底层容器对象的类型。

会员类型

以下是堆栈成员类型:

  • 值类型– 第一个模板参数,T。它表示元素类型。
  • 容器类型– 第二个模板参数,Container。它表示底层容器类型。
  • 尺寸类型– 无符号整数类型。

Opera堆栈中的

A C++ stack支持以下基本操作:

  • – 它将一个元素添加到堆栈中。
  • 流行的 – 它从堆栈中移除/弹出一个元素。
  • 窥视 – 返回堆栈顶部的元素,但不将其移除。
  • 已满 检查堆栈是否已满。
  • 的isEmpty 检查栈是否为空。

堆栈实现

以下步骤展示了当元素被压入和弹出时,栈顶位置是如何移动的:

步骤 1)我们最初有一个空栈。空栈顶的值设为 -1。

步骤 2)接下来,我们将元素 5 压入栈中。栈顶将指向元素 5。

步骤 3)接下来,我们将元素 50 压入栈中。栈顶元素移动并指向元素 50。

步骤 4)我们执行了弹出操作,移除了栈顶元素。元素 50 从栈中弹出。现在栈顶指向元素 5。

堆栈实现

push() 和 pop()

`stack::push()` 函数会将一个新元素添加到栈顶。插入元素后,栈的大小会加 1。该函数接受以下语法:

stack.push(value)

该值是要插入堆栈的项目。

`stack::pop()` 函数会移除栈顶元素。移除的元素是栈中最新的元素。移除后,栈的大小会减 1。以下是函数语法:

stack.pop()

此函数不接受任何参数。

例如1:

#include <iostream> 
#include <stack> 
using namespace std;
int main() {
	stack<int> st;
	st.push(10);
	st.push(20);
	st.push(30);
	st.push(40);
	
         st.pop();
	st.pop();

	while (!st.empty()) {
		cout << ' ' << st.top();
		st.pop();
	}
}

输出:

push() 和 pop()

以下是代码截图:

push() 和 pop()

Code 说明:

  1. 在我们的代码中包含 iostream 头文件以使用其功能。
  2. 在我们的代码中包含堆栈头文件以使用其功能。
  3. 在我们的代码中包含 std 命名空间,以便使用它的类而不调用它。
  4. 调用main()函数。程序逻辑应该添加到此函数中。
  5. 创建一个堆栈 st 来存储整数值。
  6. 使用 push() 函数将值 10 插入堆栈。
  7. 使用 push() 函数将值 20 插入堆栈。
  8. 使用 push() 函数将值 30 插入堆栈。
  9. 使用 push() 函数将值 40 插入堆栈。
  10. 使用pop()函数从堆栈中删除顶部元素,即40。顶部元素现在变成了30。
  11. 使用pop()函数从堆栈中删除顶部元素,即30。顶部元素现在变成了20。
  12. 使用 while 循环和 empty() 函数检查堆栈是否不为空。 ! 是 NOT 运算符。
  13. 在控制台上打印堆栈的当前内容。
  14. 在堆栈上调用 pop() 函数。
  15. while 循环主体的结束。
  16. main() 函数体结束。

空(),大小(),顶部()

堆栈具有内置函数,你可以使用这些函数来操作堆栈及其值。这些函数包括:

  • 空的()– 检查栈是否为空。
  • 尺寸()– 返回栈的大小,即栈中元素的数量。
  • 最佳()– 访问堆栈顶部的元素。

例如2:

#include <iostream> 
#include <stack>  
using namespace std;
void createStack(stack <int> mystack)
{
	stack <int> ms = mystack;
	while (!ms.empty())
	{
		cout << '\t' << ms.top();
		ms.pop();
	}
	cout << '\n';
}
int main()
{
	stack <int> st;
	st.push(32);
	st.push(21);
	st.push(39);
	st.push(89);
	st.push(25);

	cout << "The stack st is: ";
	createStack(st);
	cout << "\n st.size() : " << st.size();
	cout << "\n st.top() : " << st.top();
	cout << "\n st.pop() : ";
	st.pop();
	createStack(st);
	return 0;
}

输出:

空(),大小(),顶部()

以下是代码截图:

空(),大小(),顶部()

Code 说明:

  1. 在我们的代码中包含 iostream 头文件以便使用其功能。
  2. 在我们的代码中包含堆栈头文件以便使用其功能。
  3. 在我们的程序中包含 std 命名空间,以便使用它的类而不调用它。
  4. 创建函数 createStack,我们可以使用它来创建堆栈 mystack。堆栈将保存一组整数。
  5. createStack 函数主体的开头。
  6. 创建 mystack 数据类型的实例并将其命名为 ms。
  7. 使用 while 循环和 empty() 函数检查堆栈是否为空。
  8. while 循环体的开始。
  9. 使用存储在堆栈顶部的 top() 函数。\t 字符将创建一个新选项卡。
  10. 使用pop()函数删除堆栈顶部的元素。
  11. while 循环主体的结束。
  12. 在控制台上打印一个空白行。
  13. createStack 函数主体结束。
  14. 调用 main() 函数。程序逻辑应添加在 main() 函数主体内。
  15. 函数 main() 的主体的开始。
  16. 创建一个堆栈对象st。
  17. 使用push()函数将元素32插入到堆栈中。
  18. 使用push()函数将元素21插入到堆栈中。
  19. 使用push()函数将元素39插入到堆栈中。
  20. 使用push()函数将元素89插入到堆栈中。
  21. 使用push()函数将元素25插入到堆栈中。
  22. 在控制台上打印一些文本。
  23. 调用createStack函数执行上面的插入操作到栈中。
  24. 将堆栈的大小与其他文本一起打印在控制台上。
  25. 在控制台上打印堆栈顶部的元素。
  26. 在控制台上打印一些文本。
  27. 删除堆栈顶部的元素。然后它将返回堆栈中剩余的元素。
  28. 调用createStack函数执行上述操作。
  29. 程序成功完成后必须返回值。
  30. 函数 main() 主体结束。

emplace() 和 swap()

这些是其他内置堆栈函数:

  • emplace()– 构造一个新元素,然后将其插入到栈顶。
  • 交换()– 将栈的内容与另一个栈的内容交换。

例如3:

#include <iostream>    
#include <stack>
#include <cstdlib>
using namespace std;
int main() {
	stack<int> st1;
	stack<int> st2;

	st1.emplace(12);
	st1.emplace(19);

	st2.emplace(20);
	st2.emplace(23);

	st1.swap(st2);

	cout << "st1 = ";
	while (!st1.empty()) {
		cout << st1.top() << " ";
		st1.pop();
	}

	cout << endl << "st2 = ";
	while (!st2.empty()) {
		cout << st2.top() << " ";
		st2.pop();
	}
}

输出:

emplace() 和 swap()

以下是代码截图:

emplace() 和 swap()

Code 说明:

  1. 在我们的代码中包含 iostream 头文件以使用其功能。
  2. 在我们的代码中包含堆栈头文件以使用其功能。
  3. 在我们的代码中包含 cstdlib 头文件以使用其功能。
  4. 在我们的代码中包含 std 命名空间,以便使用它的类而不调用它。
  5. 调用 main() 函数。程序逻辑将添加到此函数主体内。
  6. 声明一个名为 st1 的堆栈来存储整数值。
  7. 声明一个名为 st2 的堆栈来存储整数值。
  8. 使用 emplace() 函数将整数 12 插入到名为 st1 的堆栈中。
  9. 使用 emplace() 函数将整数 19 插入到名为 st1 的堆栈中。
  10. 使用 emplace() 函数将整数 20 插入到名为 st2 的堆栈中。
  11. 使用 emplace() 函数将整数 23 插入到名为 st2 的堆栈中。
  12. 使用 swap() 函数交换两个堆栈 st1 和 st2 的内容。堆栈 st1 的内容应移动到堆栈 st2。堆栈 st2 的内容应移动到堆栈 st1。
  13. 在控制台上打印一些文本。
  14. 使用while语句和empty()函数检查堆栈st1是否不为空。
  15. 在控制台上打印堆栈 st1 的内容。在控制台上打印堆栈元素时,“ ”会在堆栈元素之间添加空格。
  16. 对堆栈 st1 执行 pop() 函数,删除顶部元素。
  17. while 语句主体结束。
  18. 在控制台上打印一些文本。endl 是 C++ 结束行的关键字。它将鼠标光标移动到下一行并从那里开始打印。
  19. 使用while语句和empty()函数检查堆栈st2是否不为空。
  20. 在控制台上打印堆栈 st2 的内容。在控制台上打印堆栈元素时,“ ”会在堆栈元素之间添加空格。
  21. 对堆栈 st2 执行 pop() 函数,删除顶部元素。
  22. while 语句主体结束。
  23. main() 函数体结束。

STL 中的堆栈

STL(标准模板库)附带了提供通用的 C++ 数据结构。因此,堆栈也可以在 STL 中实现。我们只需将此库包含在代码中并使用它来定义堆栈。

stack<T> st; 

上述语法声明了一个堆栈 st,其中包含数据类型 T 的元素。

例如4:

#include <iostream>      
#include <stack>
#include <cstdlib>
using namespace std;
int main() {
	stack<int> st;
	st.push(12);
	st.push(19);
	st.push(20);
	cout << st.top();   
	cout << st.size();  
}

输出:

STL 中的堆栈

以下是代码截图:

STL 中的堆栈

Code 说明:

  1. 在我们的代码中包含 iostream 头文件以使用其功能。
  2. 在我们的代码中包含堆栈头文件以使用其功能。
  3. 在我们的代码中包含 cstdlib 头文件以使用其功能。
  4. 在我们的代码中包含 std 命名空间,以便使用它的类而不调用它。
  5. 调用 main() 函数。程序逻辑应添加在此函数主体内。
  6. 声明一个堆栈 st 来存储整数数据。
  7. 将元素 12 添加至堆栈。
  8. 将元素 19 添加至堆栈。
  9. 将元素 20 添加至堆栈。
  10. 在控制台上打印堆栈顶部的元素。
  11. 在控制台上打印堆栈的大小。
  12. 函数 main() 主体结束。

常见问题

栈遵循后进先出(LIFO)顺序,因此它首先移除最近添加的元素。队列遵循先进先出(FIFO)顺序,首先移除最旧的元素。两者适用于不同的处理需求。

是的。`std::stack` 接受任何序列容器作为其第二个模板参数,例如 `std::stack`。 >. 默认的双端队列适用于大多数情况,而当栈的增长是可预测的时,向量可以提高内存局部性。

由于栈只访问其顶元素,因此 push 和 pop 操作的时间复杂度均为 O(1)。底层的双端队列在添加元素时不会移动现有元素,因此无论栈的大小如何,性能都保持可预测。

std::stack 不公开迭代器,因此基于范围的循环无法编译。要读取栈中的每个值,可以复制栈并重复调用副本的 top() 和 pop() 方法,或者在需要遍历时选择使用双端队列 (deque)。

pop() 函数的设计初衷是返回 void,将数据删除和访问操作分离,以确保异常处理安全性。如果一步到位地读取和删除数据,一旦复制操作出错,就可能导致数据丢失,因此需要先调用 top() 函数,然后再调用 pop() 函数。

不。`std::stack` 没有内置同步机制,因此多个线程并发的 `push` 和 `pop` 调用会导致数据竞争。在跨线程使用同一个栈之前,请使用互斥锁或其他锁定机制来保护共享访问。

是的。AI 编码助手读取注释或函数名,并生成 std​​::stack 声明、push 和 pop 循环以及遍历逻辑。 Rev查看生成的边界检查(例如在 pop() 之前执行 empty() 测试)对于确保程序安全仍然非常重要。

是的。 GitHub 副驾驶 它会在你输入时自动完成 push、pop、top 和 empty() 调用,并提供容器选择建议。它的版本是 2026。 C++ 代码智能增加了符号感知能力,因此多文件堆栈建议保持一致。

总结一下这篇文章: