为有限范围的N个整数数组实现查找数组

时间:2014-01-05 21:06:29

标签: c++ c arrays algorithm data-structures

我有一个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。

3 个答案:

答案 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;
}