我有一个大尺寸的未排序数组,每个元素都包含一个唯一的整数,
std::vector<size_t> Vec= {1, 5, 3, 7, 18...}
我需要以某种方式对矢量进行洗牌,给定一个特定的数字,查找它然后将其与新的所需位置的数字交换。这种交换需要多次完成。
目前我使用花药矢量 PositionLookup 来记住并在每次交换后更新位置。我想知道有没有更有效的方式/数据结构可以帮助做到这一点?
当前解决方案,
//look for a specific number "key" and swap it with the number in desired position "position_new"
void shuffle(key, position_new)
{
size_t temp = Vec[position_new]; // main vector
size_t position_old = PositionLookup[key]; // auxiliary vector
Vec[position_old] = temp;
PositionLookup[temp] = position_old;
Vec[position_new] = key;
PositionLookup[key] = position_new;
}
答案 0 :(得分:1)
开始时的几个微优化:如果向量具有固定大小,则可以使用std::array
或纯C数组而不是std::vector
。您还可以使用可以保存向量中所有值的最紧凑整数类型(例如std::int8_t
/ signed char
,以获取区间[-128,127],std::uint16_t
/ {{1对于区间[0,65535]等中的值。)
更大的优化机会:由于值本身永远不会改变,只有它们的索引,你只需要跟踪索引。
为简单起见,假设值为0到4.在这种情况下,我们可以有一个数组
unsigned short
这表示虚构数组中其索引的索引,此处为std::array<std::int8_t, 5> indices{{2, 3, 1, 4, 0}};
。或者换句话说,4, 2, 0, 1, 3
是indices[0]
,它是虚数组中2
的索引。
然后交换0和1的位置,你只需要做
0
这使得std::swap(indices[0], indices[1]);
数组indices
和虚数数组3, 2, 1, 4, 0
。
当然,虚数组的值可能与其索引不同。
如果(已排序)值类似于4, 2, 1, 0, 3
,您可以通过添加2来获取索引中的值,或者如果它们是-2, -1, 0, 1, 2
则可以除以3,或者如果它们是0, 3, 6, 9, 12
你可以加5然后除以2,等等。
如果值不遵循定义的模式,则可以创建第二个数组以查找与索引一起使用的值。
-5, -3, -1, 1, 3
如果直到运行时才知道这些值是一回事,显然std::array<std::int8_t, 5> indices{{2, 3, 1, 4, 0}};
constexpr std::array<std::int8_t, 5> Values{{1, 3, 5, 7, 18}};
// Imaginary array before: 18, 5, 1, 3, 7
std::swap(indices[0], indices[1]);
// Imaginary array after: 18, 5, 3, 1, 7
const auto index_to_value = [&](decltype(indices)::value_type idx) noexcept {
return Values[idx];
};
const auto value_to_index = [&](decltype(Values)::value_type val) noexcept {
return std::lower_bound(Values.begin(), Values.end(), val)
- Values.begin();
};
查找表不能是values
或const
。
constexpr