2015-12-24 19 views
6

Tôi cần sao chép std :: vector vào std :: stack.Sao chép các phần tử từ std :: vector vào std :: stack C++

  1. Chuyển ngang qua vector và đẩy vào ngăn xếp chỉ là cách?

  2. Nếu có cách nào khác thì lựa chọn tốt hơn từ quan điểm hiệu suất là gì?

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

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

Trả lời

11

Từ một chồng là một bộ chuyển đổi container, bạn có thể tạo ngăn xếp từ container cơ bản:

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

Hoặc, nếu bạn muốn ngăn xếp của bạn sẽ được deque - được hỗ trợ:

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

sao chép sẽ xảy ra ở đây? –

+0

@HumamHelfawi: Có. Tôi cho rằng OP muốn điều đó, vì cô ấy nói "Tôi cần phải sao chép". Bạn cũng có thể di chuyển vectơ vào nếu bạn không cần bản gốc nữa. –

+0

di chuyển ngữ nghĩa có thể đi vào hình ảnh ở đây ?? – basav

0

Xem this question để biết cách cho phép std::copy được sử dụng trên ngăn xếp, nhưng ra khỏi hộp, không có cách nào rõ ràng hơn vòng lặp có cuộc gọi để đẩy.

Về hiệu suất, cách duy nhất để nói là đo lường nó. (Mã cho sự rõ ràng và chính xác đầu tiên, và sau đó lo lắng về tốc độ.)

1

Một số thú vị với ngăn xếp thể hiện các phương pháp khác nhau để nhận giá trị vào ngăn xếp từ một vùng chứa khác.

Giả sử chúng tôi cung cấp một định nghĩa thích hợp cho:

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

Sau đó chúng tôi có thể viết:

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

mà đầu ra sẽ là:

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

Dưới đây là danh sách đầy đủ (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; 
} 
Các vấn đề liên quan