Programing

두 벡터를 연결하는 가장 좋은 방법은 무엇입니까?

lottogame 2020. 5. 26. 07:43
반응형

두 벡터를 연결하는 가장 좋은 방법은 무엇입니까?


멀티 트 레딩을 사용하고 결과를 병합하려고합니다. 예를 들면 다음과 같습니다.

std::vector<int> A;
std::vector<int> B;
std::vector<int> AB;

AB가 A의 내용과 B의 내용을 순서대로 갖기를 원합니다. 이와 같은 작업을 수행하는 가장 효율적인 방법은 무엇입니까?


AB.reserve( A.size() + B.size() ); // preallocate memory
AB.insert( AB.end(), A.begin(), A.end() );
AB.insert( AB.end(), B.begin(), B.end() );

이것이 정확히 멤버 함수의 기능 std::vector::insert입니다

std::vector<int> AB = A;
AB.insert(AB.end(), B.begin(), B.end());

실제로 두 벡터를 실제로 연결해야하는지 또는 반복을 위해 연결 모양을 제공 하려는지에 따라 다릅니다. 부스트 :: 결합 기능

http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/utilities/join.html

당신에게 이것을 줄 것입니다.

std::vector<int> v0;
v0.push_back(1);
v0.push_back(2);
v0.push_back(3);

std::vector<int> v1;
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
...

BOOST_FOREACH(const int & i, boost::join(v0, v1)){
    cout << i << endl;
}

너에게 줄거야

1
2
3
4
5
6

참고 boost :: join은 두 벡터를 새 컨테이너에 복사하지 않지만 두 컨테이너의 범위를 포함하는 한 쌍의 반복자 (범위)를 생성합니다. 약간의 성능 오버 헤드가 있지만 모든 데이터를 새 컨테이너에 먼저 복사하는 것보다 적을 수 있습니다.


Kiril V. Lyadvinsky의 답변을 바탕으로 새 버전을 만들었습니다. 이 스 니펫은 템플릿 및 과부하를 사용합니다. 그것으로, 당신은 쓸 수 vector3 = vector1 + vector2vector4 += vector3. 그것이 도움이되기를 바랍니다.

template <typename T>
std::vector<T> operator+(const std::vector<T> &A, const std::vector<T> &B)
{
    std::vector<T> AB;
    AB.reserve( A.size() + B.size() );                // preallocate memory
    AB.insert( AB.end(), A.begin(), A.end() );        // add A;
    AB.insert( AB.end(), B.begin(), B.end() );        // add B;
    return AB;
}

template <typename T>
std::vector<T> &operator+=(std::vector<T> &A, const std::vector<T> &B)
{
    A.reserve( A.size() + B.size() );                // preallocate memory without erase original data
    A.insert( A.end(), B.begin(), B.end() );         // add B;
    return A;                                        // here A could be named AB
}

아직 언급되지 않은 또 하나의 간단한 변형 :

copy(A.begin(),A.end(),std::back_inserter(AB));
copy(B.begin(),B.end(),std::back_inserter(AB));

그리고 병합 알고리즘을 사용하십시오.

#include <algorithm> #include <vector> #include <iterator> #include <iostream> #include <sstream> #include <string> template<template<typename, typename...> class Container, class T> std::string toString(const Container<T>& v) { std::stringstream ss; std::copy(v.begin(), v.end(), std::ostream_iterator<T>(ss, "")); return ss.str(); }; int main() { std::vector<int> A(10); std::vector<int> B(5); //zero filled std::vector<int> AB(15); std::for_each(A.begin(), A.end(), [](int& f)->void { f = rand() % 100; }); std::cout << "before merge: " << toString(A) << "\n"; std::cout << "before merge: " << toString(B) << "\n"; merge(B.begin(),B.end(), begin(A), end(A), AB.begin(), [](int&,int&)->bool {}); std::cout << "after merge: " << toString(AB) << "\n"; return 1; }


Bradgonesurfing의 대답의 방향으로, 많은 경우 실제로 두 벡터 (O (n))를 연결할 필요 가 없지만 대신 연결된 것처럼 (O (1)) 작동 합니다. 이 경우 Boost 라이브러리가 없어도 가능합니다.

The trick is to create a vector proxy: a wrapper class which manipulates references to both vectors, externally seen as a single, contiguous one, which can then be accessed/traversed exactly like you would do on a real vector.

USAGE

std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };

VecProxy<int> AB(A, B);  // ----> O(1). No copies performed!

for (size_t i = 0; i < AB.size(); i++)
    std::cout << AB[i] << " ";  // ----> Output: 1 2 3 4 5 10 20 30

std::cout << AB[6]; // ----> Output: 20

IMPLEMENTATION

template <class T>
class VecProxy {
private:
    std::vector<T>& v1, v2;
public:
    VecProxy(std::vector<T>& ref1, std::vector<T>& ref2) : v1(ref1), v2(ref2) {}
    const T& operator[](const size_t& i) const;
    const size_t size() const;
};

template <class T>
const T& VecProxy<T>::operator[](const size_t& i) const{
    return (i < v1.size()) ? v1[i] : v2[i - v1.size()];
};

template <class T>
const size_t VecProxy<T>::size() const { return v1.size() + v2.size(); };

MAIN BENEFIT

It's O(1) (constant time) to create it, and with minimal extra memory allocation. In practice, it's a fast operation even when considering huge vectors, since you replace |B| (or |A|+|B|) element copies by zero. Also, it delivers exactly the desired behavior.

Vectors concatenation is at least O(|B|) (when B is appended to A), irrespective of the employed technique. In your case, since you intend to work with a 3rd vector, AB, it is O(|A|+|B|). Depending on both the vectors' size and the number of concatenation operations needed, this can be a bottleneck. The trick above addresses it.

SOME STUFF TO CONSIDER

  • You should only go for it if you really know what you're doing when dealing with references. This solution is intended for the specific purpose of the question made, for which it works pretty well. To employ it in any other context may lead to unexpected behavior if you are not sure on how references work.
  • In this example, AB does not provide a non-const access operator ([ ]). Feel free to include it, but keep in mind: since AB contains references, to assign it values will also affect the original elements within A and/or B. Whether or not this is a desirable feature, it's an application-specific question one should carefully consider.
  • Any changes directly made to either A or B (like assigning values, resizing, etc.) will also "modify" AB. This is not necessarily bad (actually, it can be very handy: AB does never need to be explicitly updated to keep itself synchronized to both A and B), but it's certainly a behavior one must be aware of.
  • Because every access to an element is preceded by a test (namely, "i < v1.size()"), VecProxy access time, although constant, is also slower than that of vectors. It thus may not be the way to go if you need, say, to perform millions of access operations per second, i.e. if the bottleneck lies in the access operations.
  • This approach can be generalized to n vectors. I haven't tried, but it shouldn't be a big deal.
  • It does not make sense (to my eyes) to provide copy constructors to such proxies (since they are not vectors after all).
  • It is not possible (or at least too far from easy) to globally sort a VecProxy, since not all elements pertain to the same container.

If your vectors are sorted*, check out set_union from <algorithm>.

set_union(A.begin(), A.end(), B.begin(), B.end(), AB.begin());

There's a more thorough example in the link

*thanks rlbond


All the solutions are correct, but I found it easier just write a function to implement this. like this:

template <class T1, class T2>
void ContainerInsert(T1 t1, T2 t2)
{
    t1->insert(t1->end(), t2->begin(), t2->end());
}

That way you can avoid the temporary placement like this:

ContainerInsert(vec, GetSomeVector());

참고URL : https://stackoverflow.com/questions/3177241/what-is-the-best-way-to-concatenate-two-vectors

반응형