有没有有效的方法来做“矢量”的“改组”

时间:2018-01-09 21:46:30

标签: c++ algorithm data-structures

我有一个大尺寸的未排序数组,每个元素都包含一个唯一的整数,

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;

}

1 个答案:

答案 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, 3indices[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(); }; 查找表不能是valuesconst

constexpr