2015-12-24 21 views
6

Ho bisogno di copiare std :: vector in std :: stack.Copia elementi da std :: vector in std :: stack C++

  1. Attraversare il vettore e inserire nello stack è solo la strada?

  2. Se esiste un altro modo, qual è la scelta migliore dal punto di vista delle prestazioni?

std::stack<A> m_stack; 
std::vector<A> m_vec; 

for (auto& elem : m_vec) 
{ 
    m_stack.push(elem); 
} 

risposta

11

Dal momento che una pila è un adattatore contenitore, è possibile creare la pila dal contenitore sottostante:

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

O, se volete che il vostro stack per essere deque - supportato da:

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

si verificherà una copia qui? –

+0

@HumamHelfawi: Sì. Ho pensato che l'OP lo volesse, dal momento che ha detto "Ho bisogno di copiare". Puoi anche spostare il vettore se non hai più bisogno dell'originale. –

+0

la semantica del movimento potrebbe entrare in immagine qui ?? – basav

0

Vedere this question per i modi in cui è possibile utilizzare std::copy in una pila, ma non esiste un modo più ovvio di un ciclo con chiamate da premere.

Per quanto riguarda le prestazioni, l'unico modo per dire è misurarlo. (Codice per chiarezza e correttezza prima, quindi preoccuparsi della velocità.)

1

Un po 'di divertimento con pile che dimostrano vari metodi per ottenere i valori nello stack da un altro contenitore.

Supponendo abbiamo fornito una definizione appropriata per:

template<class T, class Container> 
auto stack_pusher(std::stack<T, Container>& stack); 

Potremmo quindi scrivere:

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; 
} 

per il quale l'uscita sarebbe:

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

Ecco l'elenco completo (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; 
}