C++开发必备之stl进阶(六 栈)

std::stack(栈)

在 C++ 中,std::stack 是标准模板库(STL)中的容器适配器,遵循**后进先出(LIFO,Last In First Out)**的原则。也就是说,最后插入的元素最先被访问。stack 本质上是对容器的一种封装,底层可以基于 std::dequestd::vectorstd::list 实现。

1. 基本概念

std::stack 是一个容器适配器,它限制了底层容器的操作,仅提供对栈的基本操作接口。常见的操作有:

  • push():将元素压入栈顶。
  • pop():移除栈顶元素。
  • top():访问栈顶元素。
  • empty():检查栈是否为空。
  • size():返回栈中元素的个数。

2. 栈的声明与初始化

std::stack 默认使用 std::deque 作为底层容器,但也可以使用 std::vectorstd::list

使用默认容器(std::deque):
#include <iostream>
#include <stack>

int main() {
    std::stack<int> s;  // 创建一个空栈

    s.push(10);  // 向栈中压入元素 10
    s.push(20);  // 向栈中压入元素 20
    s.push(30);  // 向栈中压入元素 30

    std::cout << "Stack top element: " << s.top() << std::endl;  // 输出栈顶元素
    return 0;
}

使用 std::vectorstd::list 作为底层容器:

#include <iostream>
#include <stack>
#include <vector>
#include <list>

int main() {
    std::stack<int, std::vector<int>> s1;  // 使用 vector 作为底层容器
    std::stack<int, std::list<int>> s2;    // 使用 list 作为底层容器

    s1.push(1);
    s2.push(2);

    std::cout << "s1 top: " << s1.top() << std::endl;
    std::cout << "s2 top: " << s2.top() << std::endl;

    return 0;
}

3. 常用操作

3.1 push()

向栈顶添加一个元素。

std::stack<int> s;
s.push(10);  // 栈现在包含元素 10
s.push(20);  // 栈现在包含元素 10, 20 (20 在栈顶)
3.2 pop()

移除栈顶元素,注意此操作并不会返回被移除的元素,若需要访问栈顶元素可以先调用 top()

std::stack<int> s;
s.push(10);
s.push(20);

s.pop();  // 移除栈顶元素,栈顶元素现在是 10
3.3 top()

返回栈顶元素的引用(不删除),可以通过它来访问或修改栈顶的元素。

std::stack<int> s;
s.push(10);
s.push(20);

int topElement = s.top();  // 访问栈顶元素,不会删除
std::cout << "Top element: " << topElement << std::endl;
3.4 empty()

判断栈是否为空,返回布尔值。

std::stack<int> s;
std::cout << std::boolalpha << s.empty() << std::endl;  // 输出 true,因为栈为空
3.5 size()

返回栈中元素的个数。

std::stack<int> s;
s.push(10);
s.push(20);

std::cout << "Stack size: " << s.size() << std::endl;  // 输出 2

4. 完整示例

以下是使用 std::stack 的一个完整示例,它展示了栈的基本操作。

#include <iostream>
#include <stack>

int main() {
    std::stack<int> s;

    // 向栈中压入元素
    s.push(10);
    s.push(20);
    s.push(30);

    // 栈的大小
    std::cout << "Stack size: " << s.size() << std::endl;

    // 访问栈顶元素
    std::cout << "Top element: " << s.top() << std::endl;

    // 移除栈顶元素
    s.pop();
    std::cout << "After pop, new top element: " << s.top() << std::endl;

    // 栈是否为空
    if (!s.empty()) {
        std::cout << "Stack is not empty" << std::endl;
    }

    return 0;
}

输出

Stack size: 3
Top element: 30
After pop, new top element: 20
Stack is not empty

5. 使用 std::stack 实现常见问题

5.1 括号匹配问题

使用栈可以轻松实现括号匹配的算法。

#include <iostream>
#include <stack>
#include <string>

bool isValid(const std::string& s) {
    std::stack<char> stack;
    for (char c : s) {
        if (c == '(' || c == '[' || c == '{') {
            stack.push(c);
        } else {
            if (stack.empty()) return false;
            char top = stack.top();
            if ((c == ')' && top == '(') ||
                (c == ']' && top == '[') ||
                (c == '}' && top == '{')) {
                stack.pop();
            } else {
                return false;
            }
        }
    }
    return stack.empty();
}

int main() {
    std::string s = "{[()]}";
    if (isValid(s)) {
        std::cout << "Valid parentheses" << std::endl;
    } else {
        std::cout << "Invalid parentheses" << std::endl;
    }

    return 0;
}

输出

Valid parentheses
5.2 使用栈实现整数反转

我们可以使用栈将整数中的每一位压入栈中,然后按顺序弹出,以实现整数反转。

#include <iostream>
#include <stack>

void reverseNumber(int n) {
    std::stack<int> s;

    while (n > 0) {
        s.push(n % 10);  // 将每一位压入栈中
        n /= 10;
    }

    while (!s.empty()) {
        std::cout << s.top();  // 输出栈顶元素
        s.pop();               // 移除栈顶元素
    }
    std::cout << std::endl;
}

int main() {
    int num = 12345;
    reverseNumber(num);  // 输出:54321
    return 0;
}

输出

54321

6. std::stack的底层实现

std::stack 本质上是一个容器适配器,它封装了一个底层容器,默认情况下底层容器是 std::deque。你可以选择使用 std::vectorstd::list 作为底层容器。

  • std::deque:默认的底层容器,双端队列,支持在两端进行高效的插入和删除。
  • std::vector:动态数组,栈顶的操作是高效的,但在头部插入或删除较慢。
  • std::list:双向链表,支持在头尾快速插入删除元素,但不支持随机访问。

7. 注意事项

  • 栈不支持遍历std::stack 是一个容器适配器,不能直接像 std::vectorstd::list 那样进行遍历,因为它只暴露了栈顶的访问权限。如果需要遍历栈中的所有元素,可以通过 pop() 一次访问一个元素。
  • 底层容器的选择std::deque 是默认的底层容器,但你也可以根据需求选择其他容器(如 std::vectorstd::list)。一般来说,如果只关心栈顶的操作,可以直接使用默认的 std::deque
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值