什么是stack
stack
是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。stack
是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定
的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。stack
的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下
操作:
empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作
- 标准容器
vector、deque、list
均符合这些需求,默认情况下,如果没有为stack
指定特定的底层容器,默认情况下使用deque
。
stack的使用
1. stack构造函数
这些是C++标准库中std::stack类的构造函数声明。std::stack是一个适配器容器,它可以使用不同的底层容器来实现栈的功能。这些构造函数声明提供了不同的方式来创建和初始化std::stack对象,可以根据需求选择合适的构造函数。
这里的各种构造函数选项包括不同的初始化方式、移动初始化、使用不同的分配器(allocator)以及结合不同的容器类型等。你可以根据需要选择适当的构造函数来创建std::stack对象。
这些构造函数的使用方式与普通类的构造函数相似,你可以使用这些构造函数来实例化std::stack对象,并为其提供合适的参数,比如底层容器、分配器等。
你可以使用以下构造函数之一:
initialize (1):
std::stack<int> myStack1; // 使用默认构造函数,默认底层容器是 std::deque
move-initialize (2):
std::stack<int> sourceStack; sourceStack.push(1); sourceStack.push(2); sourceStack.push(3); std::stack<int> myStack2(std::move(sourceStack)); // 使用移动构造函数,sourceStack中的元素移动到myStack2
allocator (3):
std::allocator<int> myAllocator; std::stack<int, std::vector<int, std::allocator<int>>> myStack3(myAllocator); // 使用指定的分配器
init + allocator (4):
std::vector<int> vec4 = {1, 2, 3, 4, 5}; std::allocator<int> myAllocator4; std::stack<int, std::vector<int, std::allocator<int>>> myStack4(vec4, myAllocator4); // 使用指定的容器和分配器
move-init + allocator (5):
std::vector<int> vec5 = {5, 4, 3, 2, 1}; std::allocator<int> myAllocator5; std::stack<int, std::vector<int, std::allocator<int>>> myStack5(std::move(vec5), myAllocator5); // 使用移动构造函数,同时指定容器和分配器
copy + allocator (6):
std::stack<int> sourceStack6; sourceStack6.push(1); sourceStack6.push(2); sourceStack6.push(3); std::allocator<int> myAllocator6; std::stack<int, std::vector<int, std::allocator<int>>> myStack6(sourceStack6, myAllocator6); // 复制构造函数,同时指定分配器
move + allocator (7):
std::stack<int> sourceStack7; sourceStack7.push(7); sourceStack7.push(8); sourceStack7.push(9); std::allocator<int> myAllocator7; std::stack<int, std::vector<int, std::allocator<int>>> myStack7(std::move(sourceStack7), myAllocator7); // 使用移动构造函数,同时指定分配器
这些示例基于不同的构造函数变体,以不同的方式初始化了 std::stack
对象,包括使用不同的容器类型和分配器。具体的使用情景会根据你的代码需求而有所不同。
2.empty()
bool empty() const;
是 C++ 标准库中 std::stack
类的成员函数之一。它用于判断栈是否为空。
返回类型:bool
,表示栈是否为空,如果栈为空则返回 true
,否则返回 false
。
const
关键字表示这个函数不会修改类的成员变量。
你可以在实际使用中,通过调用这个函数来检查栈是否为空,以便进行相应的操作。以下是一个示例:
#include <iostream> #include <stack> int main() { std::stack<int> myStack; if (myStack.empty()) { std::cout << "Stack is empty." << std::endl; } else { std::cout << "Stack is not empty." << std::endl; } myStack.push(42); if (myStack.empty()) { std::cout << "Stack is empty." << std::endl; } else { std::cout << "Stack is not empty." << std::endl; } return 0; }
在上述示例中,我们先创建一个空的栈 myStack
,然后通过 empty()
函数来检查栈是否为空。在栈为空时输出 "Stack is empty."
,否则输出 "Stack is not empty."
。之后,我们将一个元素压入栈中,并再次检查栈的状态。输出应该是 "Stack is not empty."
。
3.size()
size_type size() const;
是 C++ 标准库中 std::stack
类的成员函数之一。它用于返回当前栈中元素的数量(大小)。
返回类型:size_type
,通常是一个无符号整数类型,表示栈中元素的数量。
const
关键字表示这个函数不会修改类的成员变量。
你可以在实际使用中,通过调用这个函数来获取栈中元素的数量。以下是一个示例:
#include <iostream> #include <stack> int main() { std::stack<int> myStack; std::cout << "Initial size: " << myStack.size() << std::endl; myStack.push(42); myStack.push(15); myStack.push(7); std::cout << "Size after pushing elements: " << myStack.size() << std::endl; myStack.pop(); std::cout << "Size after popping an element: " << myStack.size() << std::endl; return 0; }
在上述示例中,我们首先创建一个空的栈 myStack
,然后使用 size()
函数获取栈的大小。之后,我们将三个元素压入栈中,再次使用 size()
函数获取栈的大小。接着,我们弹出一个元素,并再次使用 size()
函数获取栈的大小。输出应该是栈的大小在不同操作后的变化。
3.top()
reference top();
和 const_reference top() const;
是 C++ 标准库中 std::stack
类的成员函数之一。它们用于获取栈顶元素的引用。
reference top();
:返回栈顶元素的引用。如果需要修改栈顶元素,可以使用这个版本。
const_reference top() const;
:返回栈顶元素的常量引用。如果你不需要修改栈顶元素,而只是需要读取它,可以使用这个版本。
在这两个版本中,const
关键字表示在函数内部不会修改类的成员变量,确保在使用 top()
函数的过程中不会发生意外的修改。
以下是一个示例:
#include <iostream> #include <stack> int main() { std::stack<int> myStack; myStack.push(42); myStack.push(15); // 使用 top() 获取栈顶元素 int topElement = myStack.top(); std::cout << "Top element: " << topElement << std::endl; // 修改栈顶元素 myStack.top() = 99; std::cout << "New top element: " << myStack.top() << std::endl; return 0; }
在上述示例中,我们首先将两个元素压入栈中,然后使用 top()
函数获取栈顶元素,并输出它。接着,我们使用 top()
函数修改了栈顶元素的值,然后再次使用 top()
函数获取新的栈顶元素,并输出它。注意,为了修改栈顶元素,我们使用了 top()
函数的第一个版本。
4.push
void push(const value_type& val);
和 void push(value_type&& val);
是 C++ 标准库中 std::stack
类的成员函数之一。它们用于将一个新的元素压入栈中。
void push(const value_type& val);
:将传入的值的常量引用const value_type&
压入栈中。这个版本用于传递一个常量引用的值,不会修改传入的值。
void push(value_type&& val);
:将传入的值的右值引用value_type&&
压入栈中。这个版本用于传递一个右值引用的值,通常用于移动语义,可能会修改传入的值。
这两个版本的 push 函数允许你在栈顶添加新的元素。如果需要保持传入值的不变性,可以使用第一个版本;如果你想利用移动语义来避免不必要的复制,可以使用第二个版本。
以下是一个示例:
#include <iostream> #include <stack> int main() { std::stack<int> myStack; myStack.push(42); // 使用右值,将 42 压入栈中 myStack.push(15); int newElement = 99; myStack.push(newElement); // 使用常量引用,将 newElement 压入栈中 std::cout << "Stack size: " << myStack.size() << std::endl; while (!myStack.empty()) { std::cout << myStack.top() << " "; // 输出栈顶元素 myStack.pop(); // 弹出栈顶元素 } return 0; }
在上述示例中,我们使用不同版本的 push
函数将元素压入栈中,包括使用右值42
和常量引用newElement
。然后,我们循环输出栈中的元素,并弹出栈顶元素,以清空栈。最终输出的应该是栈中元素的值。