如何在C++中遍历堆栈

How to traverse stack in C++?

本文关键字:遍历 堆栈 C++      更新时间:2023-10-16

是否可以在C++中遍历std::stack

使用以下方法进行导线测量不适用。因为CCD_ 2没有成员CCD_。

std::stack<int> foo;
// ..
for (__typeof(foo.begin()) it = foo.begin(); it != foo.end();  it++)
{
    // ...
}

是否可以在C++中遍历std::stack?

没有。堆栈是一种数据结构,当您有兴趣将元素放在顶部并从顶部获取元素时,应该使用它。如果您想要一个可迭代的堆栈,可以为堆栈角色(std::vector?)使用不同的数据结构,也可以自己编写一个。

不可能直接遍历std:: stack,因为它没有end成员,堆栈数据结构就是这样,即只有一个指针。但是,仍然有两个懒惰的黑客可以穿越它:

1) 基于循环:

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

基于循环的方法的问题:

  • 原始堆栈变空

2) 基于递归:

template <typename T>
void traverse_stack(stack<T> & st) {
    if(st.empty())
        return;
    T x = st.top();
    cout << x << " ";
    st.pop();
    traverse_stack(st);
    st.push(x);
}

基于递归方法的优点:

  • 保留原始堆栈元素

基于递归方法的问题:

  • 维护内部堆栈
  • 对于大尺寸的堆栈,可能会失败

正如您所提到的,出于调试目的需要打印,也许这样的东西对您有用:

// Example program
#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <algorithm>
template <typename T>
void StackDebug(std::stack<T> s)
{
    std::vector<T> debugVector = std::vector<T>();
    while (!s.empty( ) )
    {
        T t = s.top( );
        debugVector.push_back(t);
        s.pop( );
    }
    // stack, read from top down, is reversed relative to its creation (from bot to top)
    std::reverse(debugVector.begin(), debugVector.end());
    for(const auto& it : debugVector)
    {
        std::cout << it << " ";
    }
}
int main()
{
    std::stack< int > numbers;
    numbers.push( 9 );
    numbers.push( 11 );
    StackDebug(numbers);
}

正如预期的那样,输出为"9 11"

I不认为可以遍历堆栈。我能想到的最好的方法是使用矢量std::vector使用push_back(), pop_back()

堆栈不提供开始成员函数或结束成员函数,因此不能将其与同时需要这两个函数的基于范围的for循环一起使用。

在您的情况下,如果您真的想遍历它,最好选择其他数据结构。

我们不能遍历堆栈。堆栈是一种容器适配器,专门设计用于在LIFO上下文(后进先出)中操作,其中元素仅从容器的一端插入和提取。元素是从特定容器的"后面"推/弹出的,即堆栈的顶部。堆栈不打算显示这种行为,因此我们有其他容器

#include <stack>
using std::stack;    
stack< int > numbers;
numbers.push( 1 );
numbers.push( 2 );
while ( not numbers.empty( ) )
{
    int number = numbers.top( );
    numbers.pop( );
}

http://en.cppreference.com/w/cpp/container/stack

如果您想实现LIFO概念并能够同时迭代,请使用std::deque。要模拟堆栈,请使用push_front()、front()、pop_front)

https://en.cppreference.com/w/cpp/container/deque

内部deque是";"单独分配的固定大小阵列";,因此,在处理大量数据时,效果明显好于堆栈,但差于矢量。

可以在STL的std::stack上编写一个简单的包装器,并在底层容器上迭代,引用引用:

容器必须满足SequenceContainer 的要求

这个容器可以通过受保护的成员c访问,所以类似这样的东西可能适用于您的情况:

#include <stack>
#include <iostream>
#include <iterator>
template <typename T, typename Container = std::deque<T>>
struct DebugStack : private std::stack<T, Container> {
    auto& push(T& elem) {
        std::stack<T>::push(elem);
        return *this;
    }
    auto& push(T&& elem) {
        std::stack<T>::push(elem);
        return *this;
    }
    auto& pop() {
        std::stack<T>::pop();
        return *this;
    }
    T top() {
        return std::stack<T>::top();
    }
    void print() {
        auto const& container = std::stack<T>::c;
        //T should be printable
        std::copy(begin(container), end(container), std::ostream_iterator<T>(std::cout, " "));
        std::cout<<'n';
    }
};
int main() {
    {
        DebugStack<int> stack;
        stack.push(1).push(2).push(3).push(4);
        stack.print();
        stack.pop().pop().pop();
        stack.print();
    }
    {
        DebugStack<std::string> stack;
        stack.push("First").push("Second").push("Third").push("Fourth");
        stack.print();
        stack.pop().pop().pop();
        stack.print();
    }
}

输出:

1 2 3 4 
1 
First Second Third Fourth 
First 

由于C++14引入了返回类型的自动推导,因此可以将auto返回类型更改为DebugStack(如这里所示),以使该解决方案与C++11一起使用。

我不会这么做,但您可以在不使用指针转换弹出的情况下获得堆栈值,这对编译后的类如何存储在内存中做出了一些假设,这通常不是一个好主意。

只要您不更改默认的底层容器std::deque,您就可以:

std::stack<int>s;
s.push(1234);
s.push(789);
std::deque<int>* d;
d = (std::deque<int>*)&s;
cout << (*d)[0] << endl;
cout << (*d)[1] << endl;

不弹出堆栈的输出:

1234
789
        stack<int> s,dbg; //s = not what's supposed to be
        while(!s.empty()) {
            cout << s.top() << " "; //print top of stack
            dbg.push(s.top());      //push s.top() on a debug stack
            s.pop();                //pop top off of s
        }
        //pop all elements of dbg back into stack as they were
        while(!dbg.empty()) {
            s.push(dbg.top());
            dbg.pop();
        }

我只是想看看Leetcode问题的堆栈到底出了什么问题。显然,在现实世界中,仅仅使用调试器可能更有意义。

由于c++堆栈没有某种迭代器
这是一个带有迭代器的基本堆栈。

突变体堆栈.hpp

#pragma once
#include <stack>
template <class T>
class MutantStack : public std::stack<T>
{
public:
    typedef typename std::stack<T>::container_type::iterator iterator;
    typedef typename std::stack<T>::container_type::const_iterator const_iterator;
    MutantStack(void) {}
    iterator begin(void)
    {
        return this->c.begin();
    }
    iterator end(void)
    {
        return this->c.end();
    }
    const_iterator cbegin(void) const
    {
        return this->c.cbegin();
    }
    const_iterator cend(void) const
    {
        return this->c.cend();
    }
};

您可以执行for循环:

for (stack<T> newStack = stack; !newStack.empty(); newStack.pop()){
   T item = newStack.top();
}