2015-12-24 27 views
6

Potrzebuję skopiować std :: vector do std :: stack.Skopiuj elementy ze std :: vector do std :: stack C++

  1. Czy przemieszczenie wektora i pchnięcie w stos jest tylko drogą?

  2. Jeśli jest inny sposób, co jest lepszym wyborem z punktu widzenia wydajności?

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

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

Odpowiedz

11

Ponieważ stos jest adapter pojemnik, można utworzyć stos z bazowym pojemniku:

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

Albo, jeśli chcesz, aby Twój stos być deque - w kopii:

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

Czy kopiowanie będzie miało miejsce tutaj? –

+0

@HumamHelfawi: Tak. Zakładałem, że PO chce tego, ponieważ powiedziała "muszę skopiować". Możesz także przenieść wektor, jeśli nie potrzebujesz już oryginału. –

+0

ruch semantyka może pojawić się tutaj? – basav

0

Zobacz this question, aby umożliwić używanie std::copy na stosie, ale po wyjęciu z pudełka, nie ma bardziej oczywistego sposobu niż pętla z połączeniami do pushowania.

Jeśli chodzi o wydajność, jedynym sposobem, aby powiedzieć, jest pomiar. (Najpierw kod dla jasności i poprawności, a potem martw się o szybkość).

1

Pewna zabawa przy stosach demonstrujących różne metody pobierania wartości na stos z innego pojemnika.

Zakładając zapewniliśmy odpowiednią definicję:

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

Mogliśmy wtedy napisać:

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

dla którego wyjście będzie:

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

Oto pełny wykaz (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; 
}