将std :: vector中的元素复制到std :: stack c ++中

时间:2015-12-24 12:12:24

标签: c++ c++11 vector stl stack

我需要将std::vector复制到std::stack

  1. 遍历向量并推入堆栈只是方法吗?

  2. 如果还有另一种方式,从绩效的角度来看,更好的选择是什么?

  3. 代码:

     std::stack<A>   m_stack;
     std::vector<A>  m_vec;
    
     for (auto& elem : m_vec)
     {
        m_stack.push(elem);
     }
    

4 个答案:

答案 0 :(得分:12)

由于堆栈是容器适配器,您可以从基础容器创建堆栈:

std::vector<A> m_vec = /* ... */;
std::stack<A, std::vector<A>> m_stack(m_vec);

或者,如果您希望您的堆栈为deque - 支持:

std::stack<A> m_stack(std::deque<A>(m_vec.begin(), m_vec.end()));

答案 1 :(得分:1)

堆栈的一些乐趣,展示了从另一个容器中将值放到堆栈上的各种方法。

假设我们为:

提供了合适的定义
template<class T, class Container>
auto stack_pusher(std::stack<T, Container>& stack);

然后我们可以写:

int main()
{
    using namespace std;

    // construct an initial vector
    vector<int> init { 7,6 };

    // construct a stack using a copy of the initial vector's elements
    // note that the stack's storage is automatically deduced
    stack<int> stack1 { { begin(init), end(init) } };

    // construct a stack directly from a container initialised with an initialiser list
    stack<int> stack2 { { 3,4,5 } };

    // another vector
    vector<int> myvector { 1, 2, 3, 4, 5, 6, 7, 8 };

    // copy vector onto stack using a forward iterator
    copy(begin(myvector),
         end(myvector),
         stack_pusher(stack1));

    // copy vector onto stack using a reverse iterator
    copy(rbegin(myvector),
         rend(myvector),
         stack_pusher(stack2));

    // display the stacks
    while (stack1.size() or stack2.size())
    {
        // function to encode an optional T as a string
        auto encode = [](const auto& opt)
        {
            return opt ? std::to_string(opt.value()) : std::string("*");
        };

        // function to pop a value from a stack if it's not empty.
        // return an optional
        auto maybe_pop = [](auto& stack)
        {
            using element_type = std::decay_t<decltype(stack.top())>;
            boost::optional<element_type> result;
            if (stack.size()) {
                result = stack.top();
                stack.pop();
            }
            return result;
        };

        cout
        << encode(maybe_pop(stack1))
        << "\t"
        << encode(maybe_pop(stack2)) << endl;
    }

    return 0;
}

输出为:

8       1
7       2
6       3
5       4
4       5
3       6
2       7
1       8
6       5
7       4
*       3

这里是完整列表(c ++ 14):

#include <iostream>
#include <stack>
#include <vector>
#include <deque>
#include <iterator>
#include <utility>
#include <boost/optional.hpp>

// an iterator that pushes values onto a stack
template<class Stack>
struct push_iterator
: std::iterator<std::output_iterator_tag,void,void,void,void>
{
    push_iterator(Stack& stack)
    : pstack(std::addressof(stack))
    {}

    template<class T>
    auto& operator=(T&& t)
    {
        pstack->push(std::forward<T>(t));
        return *this;
    }

    auto& operator*() {
        return *this;
    }

    auto& operator++() {
        return *this;
    }

private:
    Stack* pstack;
};

// convenience class to make a push_iterator of the correct type
template<class T, class Container>
auto stack_pusher(std::stack<T, Container>& stack)
{
    return push_iterator<std::stack<T, Container>>(stack);
}

int main()
{
    using namespace std;

    // construct an initial vector
    vector<int> init { 7,6 };

    // construct a stack using a copy of the initial vector's elements
    // note that the stack's storage is automatically deduced
    stack<int> stack1 { { begin(init), end(init) } };

    // construct a stack directly from a container initialises with an initialiser list
    stack<int> stack2 { { 3,4,5 } };

    // another vector
    vector<int> myvector { 1, 2, 3, 4, 5, 6, 7, 8 };

    // copy vector onto stack using a forward iterator
    copy(begin(myvector),
         end(myvector),
         stack_pusher(stack1));

    // copy vector onto stack using a reverse iterator
    copy(rbegin(myvector),
         rend(myvector),
         stack_pusher(stack2));

    // display the stacks
    while (stack1.size() or stack2.size())
    {
        // function to encode an optional T as a string
        auto encode = [](const auto& opt)
        {
            return opt ? std::to_string(opt.value()) : std::string("*");
        };

        // function to pop a value from a stack if it's not empty.
        // return an optional
        auto maybe_pop = [](auto& stack)
        {
            using element_type = std::decay_t<decltype(stack.top())>;
            boost::optional<element_type> result;
            if (stack.size()) {
                result = stack.top();
                stack.pop();
            }
            return result;
        };

        cout
        << encode(maybe_pop(stack1))
        << "\t"
        << encode(maybe_pop(stack2)) << endl;
    }

    return 0;
}

答案 2 :(得分:1)

std::stack是一个奇怪但又难以理解的容器:

#include<vector>
#include<stack>

struct A{};

template<class T>
struct mystack : std::stack<T>{
    decltype(auto) c(){return std::stack<T>::c;}
};

int main(){
    std::vector<A>  m_vec;

    mystack<A>   m_stack;
    m_stack.c().assign(m_vec.begin(), m_vec.end());

}

#include<vector>
#include<stack>

struct A{};

template<class... T>
struct mystack : std::stack<T...>{
    decltype(auto) container(){return std::stack<T...>::c;}
};

template<class... T>
decltype(auto) container(std::stack<T...>& s){return static_cast<mystack<T...>&>(s).container();}

int main(){
    std::vector<A>  m_vec;

    std::stack<A>   m_stack;
    container(m_stack).assign(m_vec.begin(), m_vec.end());
}

答案 3 :(得分:0)

有关允许std::copy在堆栈上使用的方法,请参阅this question,但开箱即用,没有比调用推送的循环更明显的方法。

至于表现,唯一的方法是衡量它。 (首先是代码的清晰度和正确性,然后担心速度。)