Multitreading kullanıyorum ve sonuçları birleştirmek istiyorum. Örneğin:
std::vector<int> A;
std::vector<int> B;
std::vector<int> AB;
AB'nin A ve B içeriklerini bu sırayla almasını istiyorum. Böyle bir şey yapmanın en etkili yolu nedir?
Multitreading kullanıyorum ve sonuçları birleştirmek istiyorum. Örneğin:
std::vector<int> A;
std::vector<int> B;
std::vector<int> AB;
AB'nin A ve B içeriklerini bu sırayla almasını istiyorum. Böyle bir şey yapmanın en etkili yolu nedir?
Yanıtlar:
AB.reserve( A.size() + B.size() ); // preallocate memory
AB.insert( AB.end(), A.begin(), A.end() );
AB.insert( AB.end(), B.begin(), B.end() );
Üye işlevi tam olarak std::vector::insert
bunun içindir
std::vector<int> AB = A;
AB.insert(AB.end(), B.begin(), B.end());
insert
rastgele erişimli yineleyiciler üzerinde uzmanlaştıysa ve ön tarafa ayrılmışsa şaşırmam .
distance
O (1) karmaşıklığı olduğu). Yine de, performans garantileri, insert
önceden planlama yaparak genellikle daha iyi yapabileceğiniz zamanlara dikkat etmeniz gereken bir şeydir.
size < capacity
çoğu zaman, dallanma tahmini muhtemel olmayan yeniden tahsis şubesinin talimatları düşük yineleme sayısı hariç şube kaynaklı gecikme minimize, talimat boru hattı olmak olacaktır çünkü. Bu, iyi bir vektör uygulaması ve ayrıca CPU talimatı boru hattı ve [iyi] şube tahmini olduğunu varsayar, ancak bunlar modern bir takım zinciri ve masaüstü makinesi için oldukça güvenilir varsayımlardır. Akıllı telefonlar hakkında bilmiyorum ..
İki vektörü gerçekten fiziksel olarak birleştirmeniz gerekip gerekmediğine veya yineleme uğruna birleştirme görünümü vermek isteyip istemediğinize bağlıdır. Boost :: birleştirme işlevi
http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/utilities/join.html
bunu size verecek.
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;
}
sana vermeliyim
1
2
3
4
5
6
Notu: join, iki vektörü yeni bir kaba kopyalamaz, ancak her iki kabın aralığını kapsayan bir çift yineleyici (aralık) oluşturur. Bazı performans yükleri olacak, ancak önce tüm verileri yeni bir kapsayıcıya kopyalamaktan daha az olacaktır.
Kiril V. Lyadvinsky'nin cevabına dayanarak yeni bir versiyon yaptım. Bu pasaj şablonu ve aşırı yükleme kullanır. Bununla beraber vector3 = vector1 + vector2
ve yazabilirsiniz vector4 += vector3
. Umarım yardımcı olabilir.
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
}
::
alınır;)
v1 + v2
ek temsil etmez açık değil.
@
F # gibi kullanmak olacaktır
Bradgonesurfing'in cevabı yönünde, çoğu zaman bir kişinin iki vektörü (O (n)) birleştirmesi gerekmez , bunun yerine sadece birleştirilmiş gibi çalışırlar (O (1)) . Bu sizin durumunuzsa, Boost kütüphanelerine ihtiyaç duymadan yapılabilir.
İşin püf noktası, bir vektör proxy oluşturmaktır: harici olarak tek bir bitişik olarak görülen her iki vektöre yapılan referansları işleyen bir sarıcı sınıf .
KULLANIM
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] << " "; // 1 2 3 4 5 10 20 30
UYGULAMA
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(); };
ANA FAYDA
Onu oluşturmak için O (1) (sabit zaman) ve minimum ekstra bellek ayırma.
DİKKAT EDİLECEK BAZI ÖĞELER
Henüz bahsedilmeyen bir basit varyant:
copy(A.begin(),A.end(),std::back_inserter(AB));
copy(B.begin(),B.end(),std::back_inserter(AB));
Ve birleştirme algoritması kullanarak:
#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;
}
Vektörleriniz sıralanırsa *, <algoritma> 'dan set_union ' a bakın.
set_union(A.begin(), A.end(), B.begin(), B.end(), AB.begin());
Bağlantıda daha ayrıntılı bir örnek var
* teşekkürler rlbond
Tüm çözümler doğrudur, ancak bunu uygulamak için bir işlev yazmayı daha kolay buldum. bunun gibi:
template <class T1, class T2>
void ContainerInsert(T1 t1, T2 t2)
{
t1->insert(t1->end(), t2->begin(), t2->end());
}
Bu şekilde geçici yerleşimi şu şekilde önleyebilirsiniz:
ContainerInsert(vec, GetSomeVector());