C++ 从整数范围中搜索
我需要从整数列表中查找一个整数。我对它们进行排序,并使用下限来查找给定整数所处的范围。这需要O(lgn)。有什么办法能比这更好吗 以下是需要改进的提示C++ 从整数范围中搜索,c++,algorithm,c++11,C++,Algorithm,C++11,我需要从整数列表中查找一个整数。我对它们进行排序,并使用下限来查找给定整数所处的范围。这需要O(lgn)。有什么办法能比这更好吗 以下是需要改进的提示 给定的列表总是正整数 名单是固定的。没有插入或删除 一种方法是创建一个数组并索引到该数组中。这可能不节省空间。 我可以使用无序的地图吗?我应该定义什么散列函数 // Sort in reverse order to aid the lookup process vector<unsigned int> sortedByRange; /
// Sort in reverse order to aid the lookup process
vector<unsigned int> sortedByRange;
//... sortedByRange.push_back(..)
sort(sortedByRange.begin(), sortedByRange.end(), greater);
Range = (sortedByAddress_.begin() - sortedByRange.end();
std::cout<<"Range :"<<Range<<std::endl; //prints 3330203948
std::pair<unsigned int, unsigned int> lookup(unsigned int addr){
pair<unsigned int, unsigned int> result;
vector<unsigned int>::iterator it = lower_bound(sortedByRange.begin(),
sortedByRange.end(), addr);
result.first = *it;
result.second = *(it++);
return result;
}
//按相反顺序排序以帮助查找过程
向量分类范围;
//... 分类范围。推回(…)
排序(sortedByRange.begin()、sortedByRange.end()、更大);
范围=(sortedByAddress_u2;.begin()-sortedByRange.end();
STD::CUT< P> <强>方法1:< /强>如果您只需要知道给定的数字是否在列表中,并且最大值不是太大,则可以考虑使用位字段。那么查找将是O(1)操作。
方法2:如果值的范围很大(小整数和大整数),但列表大小不大(例如几千个),您可以尝试(以编程方式)制作一个
在列表中的值上是一对一
将给出一个范围0
…N+m
,且m
足够小
计算起来相对便宜
然后可以将常量列表的值放入一个数组中,由散列值索引,以便快速检查给定输入值的包含情况。如果列表中有孔(m
非零),则应使用特殊值指示孔(例如-1
)
包含测试:针对给定的输入
1.计算散列值;
2.如果哈希值的值超出范围,则输入不在列表中;
3.否则,当且仅当由哈希值索引的生成数组中的值与输入值相同时,输入才属于列表
在SO中,如何构造哈希函数是值得考虑的另一个问题(对于字符串值,存在为此目的生成工具的工具):-)
限制:如果列表不是在编译时创建的,而是在程序运行时计算或接收的,则此方法不适用。此外,如果这个列表经常改变,那么生成哈希函数和代码所需的计算时间可能会使这种方法不合适。 < P> <强>方法1:< /强>如果您只需要知道给定的编号是否在列表中,并且最大值不太大,则可以考虑使用位字段。那么查找将是O(1)操作
方法2:如果值的范围很大(小整数和大整数),但列表大小不大(例如几千个),您可以尝试(以编程方式)制作一个
在列表中的值上是一对一李>
将给出范围0
的值N+m
且m
足够小李>
计算起来相对便宜
然后可以将常量列表的值放入一个数组中,由哈希值索引,以便快速检查给定输入值的包含情况。如果列表中有孔(m
非零),则应使用特殊值指示孔(例如-1
)
包含测试:针对给定的输入
1.计算散列值;
2.如果哈希值的值超出范围,则输入不在列表中;
3.否则,当且仅当由哈希值索引的生成数组中的值与输入值相同时,输入才属于列表
在SO中,如何构造哈希函数是值得考虑的另一个问题(对于字符串值,存在为此目的生成工具的工具):-)
限制:如果列表不是在编译时创建的,而是在程序运行时计算或接收的,则此方法不适用。此外,如果此列表经常更改,则生成哈希函数和代码所需的计算时间可能会使此方法不适用。如果总范围不大,您可以构建任意大小的采样索引数组(您希望为其投入多少RAM?)
因此,例如,如果数据的总范围是256M,并且您有一个备用兆字节,那么您存储数据范围中每1K间隔的位置。然后,对于任何给定的数据点,您对索引数组进行O(1)(实际上是O(2):)探测,以找到该数据点的最低和最高合理范围,然后您可以对该范围进行最低_绑定。如果您的范围在大小上没有很大的变化,那么您应该可以获得平均的固定时间查找
如果你不想在这个问题上投入那么多的内存,你可以尝试一对基于平均范围大小和模糊因子的线性估计。如果结果不包含特定的数据点,您可以退回到完整的二进制搜索;否则,受限范围内的二进制搜索应为平均线性时间
这里是第一个建议,以防手工操作不够清晰。完全未经测试的代码,甚至没有尝试编译它,而且整数类型的使用也很松散。如果你使用它,试着让它更漂亮。此外,我应该(但没有)将索引范围的开始限制为*begin_u2;;如果该值明显大于0,则应修复该值
// The provided range must be sorted, and value_type must be arithmetic.
template<type RandomIterator, unsigned long size>
class IndexedLookup {
public:
using value_type = typename RandomIterator::value_type;
IndexedLookup(RandomIterator begin, RandomIterator end)
: begin_(begin),
end_(end),
delta_(*(end_ - 1) / size) {
for (unsigned long i = 0; i < size; ++i)
index_[i] = std::lower_bound(begin_, end_, i * delta_) - begin_;
// The above expression cannot be out of range
index_[size] = end_ - begin_;
}
RandomIterator lookup(value_type needle) {
int low = needle / delta_;
return std::lower_bound(index_[begin_ + low],
index_[begin_ + low + 1],
needle);
}
private:
RandomIterator begin_, end_;
value_type delta_;
std::array<int, size + 1> index_;
}
//必须对提供的范围进行排序,并且值类型必须是算术值。
模板
类索引lookup{
公众:
使用value\u type=typename随机迭代器::value\u type;
IndexedLookup(随机迭代器开始,随机迭代器结束)
:开始,
结束(结束),,
三角洲(*(端部-1)/尺寸){
for(无符号长i=0;i