1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
#include <iostream>
#include <string>
#include <random>
#include <ctime>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <unordered_map>
#include <unordered_set>
struct object
{
std::string id ;
object( std::string&& name = "" ) : id( std::move(name) ) {}
};
object random_object()
{
static char alphabet[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
static constexpr std::size_t N = sizeof(alphabet) - 1 ;
static std::mt19937 twister( std::time(nullptr) ) ;
static std::uniform_int_distribution<std::size_t> distr( 2, 10 ) ;
std::shuffle( alphabet, alphabet+N, twister ) ;
return { { alphabet, alphabet + distr(twister) } } ;
}
int main()
{
const std::size_t N = 1024 * 128 ;
std::vector<object> master ;
while( master.size() < N ) master.push_back( random_object() ) ;
std::cout << "Master size: " << master.size() << '\n' ;
std::srand( std::time(nullptr) ) ;
std::vector< object > _subset; // create random subset
for( std::size_t j = 0 ; j < N ; j += 2 ) _subset.push_back( master[j] ) ;
std::random_shuffle( _subset.begin(), _subset.end() ) ; // rearrange subset
std::vector< object > subset[4] = {_subset, _subset, _subset, _subset}; // all 4 tests should use the same subset (test #4 is in the next post)
{ // Test #1. Sort subset[0] according to order in master.
const auto start = std::clock() ;
// destructively move subset elements to a hash table
std::unordered_set<std::string> set ;
for( object& obj : subset[0] ) set.insert( std::move( obj.id ) ) ;
std::vector< object > temp ; // scratch area
// iterate through the master, look up, append to temp
for( const object& obj : master )
{
auto iter = set.find(obj.id) ;
if( iter != set.end() )
{
std::string mvalue = *iter ;
temp.emplace_back( std::move(mvalue) ) ;
}
}
subset[0].swap(temp) ; // copy temp to subset, discard subset
const auto end = std::clock() ;
std::cout << "Test #1. Subset size: " << subset[0].size() << ". Result: " << ( end - start ) / double(CLOCKS_PER_SEC) << " seconds.\n" ;
}
{ // Test #2. Sort subset[1] according to reverse order in master.
const auto start = std::clock() ;
std::unordered_set<std::string> set ;
for( object& obj : subset[1] ) set.insert( std::move( obj.id ) ) ;
std::vector< object > temp ;
for(std::vector<object>::const_reverse_iterator it = master.crbegin(); it != master.crend(); ++it)
{
auto iter = set.find(it->id) ;
if( iter != set.end() )
{
std::string mvalue = *iter ;
temp.emplace_back( std::move(mvalue) ) ;
}
}
subset[1].swap(temp) ;
const auto end = std::clock() ;
std::cout << "Test #2. Subset size: " << subset[1].size() << ". Result: " << ( end - start ) / double(CLOCKS_PER_SEC) << " seconds.\n" ;
}
{ // Test #3. Sort subset[2] according to master[0] < master[N-1] < master[1] < master[N-2] < master[2] < master[N-3] < master[3] < ...
const auto start = std::clock() ;
std::unordered_set<std::string> set ;
for( object& obj : subset[2] ) set.insert( std::move( obj.id ) ) ;
std::vector< object > temp ;
std::vector<object>::const_iterator it = master.begin(), it_halfway = std::next (master.begin(), N/2);
std::vector<object>::const_reverse_iterator jt = master.crbegin(), jt_halfway = std::next (master.crbegin(), N/2);
while (it != it_halfway) // while (it != master.end()) is wrong
{
while (jt != jt_halfway) // while (jt != master.crend()) is wrong
{
auto iter = set.find(it->id) ;
if( iter != set.end() )
{
std::string mvalue = *iter ;
temp.emplace_back( std::move(mvalue) ) ;
}
iter = set.find(jt->id) ;
if( iter != set.end() )
{
std::string mvalue = *iter ;
temp.emplace_back( std::move(mvalue) ) ;
}
++it; ++jt;
}
}
subset[2].swap(temp) ;
const auto end = std::clock() ;
std::cout << "Test #3. Subset size: " << subset[2].size() << ". Result: " << ( end - start ) / double(CLOCKS_PER_SEC) << " seconds.\n" ;
}
}
/*
Output:
Master size: 131072
Test #1. Subset size: 72841. Result: 0.063 seconds.
Test #2. Subset size: 72841. Result: 0.078 seconds.
Test #3. Subset size: 72841. Result: 0.063 seconds.
*/
|