C++ 从整数范围中搜索

C++ 从整数范围中搜索,c++,algorithm,c++11,C++,Algorithm,C++11,我需要从整数列表中查找一个整数。我对它们进行排序,并使用下限来查找给定整数所处的范围。这需要O(lgn)。有什么办法能比这更好吗 以下是需要改进的提示 给定的列表总是正整数 名单是固定的。没有插入或删除 一种方法是创建一个数组并索引到该数组中。这可能不节省空间。 我可以使用无序的地图吗?我应该定义什么散列函数 // Sort in reverse order to aid the lookup process vector<unsigned int> sortedByRange; /

我需要从整数列表中查找一个整数。我对它们进行排序,并使用下限来查找给定整数所处的范围。这需要O(lgn)。有什么办法能比这更好吗

以下是需要改进的提示

  • 给定的列表总是正整数
  • 名单是固定的。没有插入或删除
  • 一种方法是创建一个数组并索引到该数组中。这可能不节省空间。 我可以使用无序的地图吗?我应该定义什么散列函数

    // 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