我有一个arr[N]
,需要为所有可能的值集arr
实现一个查找数组,例如数组为bool arr[N]
的最简单大小写的2 ^ N个可能值。
这可以通过定义N维布尔查找数组来完成。例如,对于N = 4且arr
是布尔值,它将是bool lookup[2][2][2][2]
。然后,lookup
可以arr
存储和检索lookup[arr[0]][arr[1]][arr[2]][arr[3]]
的任何可能值。
由于N
变化,因此写入和执行效率也很低,因此实际的实现必须使用for
循环进行存储和检索。这是一个问题,因为查找是一种非常常见的操作,并且尽可能快地进行查找是本练习的重点。
还有其他方法可以实现这个想法吗?我会对布尔arr
的解决方案感兴趣,可能使用某种位表示,以及更通用的解决方案,其中arr
中的值范围宽于2。
答案 0 :(得分:1)
对于布尔值的情况,您确实应该使用位:任何易处理的N
必须符合N^2
个条目到内存中,大约为2 ^ 32到2 ^ 38现代机器,所以无论如何你都无法到达N = 64
。
也就是说,您可以为每个数组条目使用最低有效位,并简单地分配2^N
值的存储。然后,数组的位表示可以简单地作为此商店的索引。
这样的事情:
uint64_t compressArray(long length, bool* array) {
uint64_t result = 0;
for(long i = length; i--; ) result = (result << 1) | (array[i] ? 1 : 0);
return result;
}
...
int* store = malloc(sizeof(*store) * (1 << N));
bool* array = ...;
// Now you can access the ints in store like this:
store[compressArray(N, array)] = 3;
答案 1 :(得分:1)
如果我理解正确的话...... 对于布尔类型,如果在一维数组中使用元素索引来表示您的位,就足够了。 例如对于arr [4]
ar[0] = 0, ar[1] = 0, ar[2] = 0, ar[3] = 0 0000
ar[0] = 1, ar[1] = 0, ar[2] = 0, ar[3] = 0 0001
ar[0] = 0, ar[1] = 1, ar[2] = 0, ar[3] = 0 0010
ar[0] = 1, ar[1] = 1, ar[2] = 0, ar[3] = 0 0011
等...
例如,对于包含1到3的值的arr,您可以为每个值使用两位。
答案 2 :(得分:0)
以下可能会有所帮助:
因此,从您的示例ValueRange = 2
开始,bool
可以获取2个值;
Size = N
#include <cassert>
#include <cstddef>
#include <vector>
template<typename T, int ValueRange, int Size>
class MultiArray
{
static_assert(ValueRange > 1, "Need at least 2 or more values");
static_assert(Size > 0, "Size should be strictly positive");
public:
MultiArray() : values(computeTotalSize())
{
assert(!values.empty());
}
const T& get(const std::vector<size_t>& indexes) const
{
return values[computeIndex(indexes)];
}
T& get(const std::vector<size_t>& indexes)
{
return values[computeIndex(indexes)];
}
size_t computeIndex(const std::vector<size_t>& indexes) const
{
assert(indexes.size() == Size);
size_t index = 0;
size_t mul = 1;
for (size_t i = 0; i != Size; ++i) {
assert(indexes[i] < ValueRange);
index += indexes[i] * mul;
mul *= ValueRange;
}
assert(index < values.size());
return index;
}
std::vector<size_t> computeIndexes(size_t index) const
{
assert(index < values.size());
std::vector<size_t> res(Size);
size_t mul = values.size();
for (size_t i = Size; i != 0; --i) {
mul /= ValueRange;
res[i - 1] = index / mul;
assert(res[i - 1] < ValueRange);
index -= res[i - 1] * mul;
}
return res;
}
private:
size_t computeTotalSize() const
{
size_t totalSize = 1;
for (int i = 0; i != Size; ++i) {
totalSize *= ValueRange;
}
return totalSize;
}
private:
std::vector<T> values;
};
所以像这样使用它:
int main()
{
MultiArray<int, 2, 4> m;
m.get({0, 0, 1, 0}) = 42;
m.get({1, 1, 0, 0}) = 42;
// Just for test purpose:
for (size_t i = 0; i != 16; ++i) {
assert(m.computeIndex(m.computeIndexes(i)) == i);
}
return 0;
}