如何打印std::stack的内容并返回其大小



在c++中,如何打印出堆栈的内容并返回其大小?

std::stack<int>  values;
values.push(1);
values.push(2);
values.push(3);
// How do I print the stack?

您可以复制堆栈并逐个弹出项目以转储它们:

#include <iostream>
#include <stack>
#include <string>
int main(int argc, const char *argv[])
{
std::stack<int> stack;
stack.push(1); 
stack.push(3); 
stack.push(7); 
stack.push(19); 
for (std::stack<int> dump = stack; !dump.empty(); dump.pop())
std::cout << dump.top() << 'n';
std::cout << "(" << stack.size() << " elements)n";
return 0;
}

输出

19
7
3
1
(4 elements)

在这里观看直播:http://liveworkspace.org/code/9489ee305e1f55ca18c0e5b6fa9b546f

std::stackstd::queue都是通用容器的包装器。该容器可以作为protected成员c访问。使用c,您可以获得对元素的有效访问;否则,您可以直接复制堆栈或队列,并破坏性地访问副本的元素。

使用c:的示例

#include <iostream>     // std::wcout, std::endl
#include <stack>        // std::stack
#include <stddef.h>     // ptrdiff_t
using namespace std;
typedef ptrdiff_t   Size;
typedef Size        Index;
template< class Elem >
Size nElements( stack< Elem > const& c )
{
return c.size();
}
void display( stack<int> const& numbers )
{
struct Hack
: public stack<int>
{
static int item( Index const i, stack<int> const& numbers )
{
return (numbers.*&Hack::c)[i];
}
};
wcout << numbers.size() << " numbers." << endl;
for( Index i = 0;  i < nElements( numbers );  ++i )
{
wcout << "  " << Hack::item( i, numbers ) << endl;
}
}
int main()
{
stack<int>  numbers;
for( int i = 1;  i <= 5;  ++i ) { numbers.push( 100*i ); }
display( numbers );
}

打印std::stack的元素而不弹出它们的唯一方法是编写一个扩展std::stack的适配器(这里是一个示例)。否则,您应该将堆栈替换为std::deque

一种不使用";特殊技术";是通过

递归

由于不存在不能使用std::stack<>pop ()成员函数的边界等,我们可以使用以下递归算法。

算法:

  1. 基本情况:如果堆栈为空=>返回
  2. 弹出顶部元素并将其存储在变量中
  3. 打印存储的值
  4. 递归调用堆栈的其余元素
  5. 再次将元素推到堆栈上

尽管执行了pop操作,但堆栈不会丢失其元素,因为在打印堆栈的其余部分后,我们将以相同的顺序再次推送它们。

以下是上述算法的代码:

void printStack (std::stack <int> &values) {

if (values.empty ()) {
return;
}
int topElement = values.top ();
values.pop ();
std::cout << topElement << std::endl;
printStack (values);
values.push (topElement);
}

上述代码的输出:

3
2
1

这将从上到下印刷元素。

如果希望元素从下至上打印,只需切换递归调用和std::cout语句即可。

void printStack (std::stack <int> &values) {

if (values.empty ()) {
return;
}
int topElement = values.top ();
values.pop ();
printStack (values);
std::cout << topElement << std::endl;
values.push (topElement);
}

输出:

1
2
3

并且std::stack<>size ()成员函数可以用于获取堆栈的大小。

std::cout << values.size () << std::endl;

Hm,一个近10年前的问题。不管怎样,这里还有一个额外的答案。

第一:堆栈的大小由std::stack.size().给出

然后,在现代C++中,STL及其算法被越来越多地使用。因此,下面的解决方案利用了这一点。前提条件是堆栈使用连续内存。目前这是有保证的。

输出是通过一个线性完成的。

参见以下示例:

#include <vector>
#include <stack>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <sstream>
using Number = int;
using UnderlyingContainer = std::vector<Number>;
using Stack = std::stack< Number, UnderlyingContainer>;
std::istringstream testData("5 8 1 4 9 3");
int main()
{
// Put the test data onto the stack
Stack stack{ UnderlyingContainer {std::istream_iterator<Number>(testData),std::istream_iterator<Number>()} };
// Print the test data
if (not stack.empty())
std::copy(&stack.top() + 1 - stack.size(), &stack.top() + 1, std::ostream_iterator<Number>(std::cout, "n"));
return 0;
}

这是完全有效和可靠的代码。这里有更多的解释。

我们想要输出数据,所以我们将其复制到一个ostream_iterator。ostream_iterator引用了一个流(是的,你也可以放一个流的开口)和deliminator。也许你想用一个"。

副本的源是2个迭代器。是的,指针是迭代器。而且,我们将保证连续内存用于std::堆栈。因此,我们只需计算2个指针,并将它们交给std::copy。

如果你想使用显式迭代器。我们开始。

#include <vector>
#include <stack>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <sstream>
using Number = int;
using UnderlyingContainer = std::vector<Number>;
using Stack = std::stack< Number, UnderlyingContainer>;
using StackIterator = const Number *;
std::istringstream testData("5 8 1 4 9 3");
int main()
{
// Put the test data onto the stack
Stack stack{ UnderlyingContainer {std::istream_iterator<Number>(testData),std::istream_iterator<Number>()} };
// Print the test data
// Get iterators
StackIterator end = &stack.top() + 1;
StackIterator begin = end - stack.size();
if (not stack.empty())
std::copy(begin, end, std::ostream_iterator<Number>(std::cout, "n"));
return 0;
}

因此,您可以为堆栈创建迭代器。但是,请注意:

std::堆栈有意将其元素隐藏在引擎盖下。所以,如果你写访问数据,我会认为这是一个设计错误。通过常量指针/迭代器进行读取访问对我来说还可以。但也许你应该更好地使用std::vector。

对于编码练习,我使用以下堆栈实现:

#include <vector>
using std::vector;
template<class T>
class my_stack : public vector<T> {
public:
using vector<T>::vector; ///Takes all the constructors
void push(T value) {
vector<T>::push_back(value);
}
T pop() {
T ret_val = vector<T>::back();
vector<T>::pop_back();
return ret_val;
}

};

优点:

  • 可以轻松打印
  • 可以用所需内容初始化大括号
  • 奖励功能:pop()返回弹出的值

注意事项:
您必须小心,不要使用"被禁止的";方法如CCD_ 16。为了防止这种情况,您可以将vector继承为protected,然后指定您的打印功能变得相关:

#include <iostream>
#include <vector>
using std::vector;
template<class T>
class my_stack : protected vector<T> {
public:
using vector<T>::vector; ///Takes all the constructors
using vector<T>::size;
void push(T value) {
vector<T>::push_back(value);
}
T pop() {
T ret_val = vector<T>::back();
vector<T>::pop_back();
return ret_val;
}
friend std::ostream& operator<< <> (std::ostream&, const my_stack<T>& vec);
};
template<typename T>
std::ostream& operator<<(std::ostream& os, const my_stack<T>& in) {
for (auto& el : in) {
os << el << ' ';
}
return os;
}

http://www.cplusplus.com/reference/stl/stack/就尺寸而言,它很容易使用:

cout << mystack.size();

对于其余的内容,我在文档中没有看到任何内容,但当你推送堆栈时,你应该打印堆栈的内容,或者有一个列表来记录元素,以便打印它,当你完成测试时,不要忘记删除它

最新更新