给定这样一个问题:
有一组从IP范围到地理位置信息的数据,不同地点的IP范围没有重叠,实现从单个IP地址查到相应的地理位置。
数据示例
- start end geo-loc
- 1000 2000 北京
- 3000 3500 上海
- 4000 5000 广州
- 5200 5500 延安
- 6000 7000 西藏
这里将只重点说明实现方式,具体为什么这么做,仅简单介绍。std::map 有三个不太常用的成员函数:
iterator lower_bound(const key_type& key);
iterator upper_bound(const key_type& key);
pair<iterator, iterator> equal_range(const key_type& key);
实现代码:
- #include <map>
-
- struct Data
- {
- unsigned startIP;
- std::string geoLoc;
- };
-
- typedef std::map<unsigned, Data> ipmap_t;
- ipmap_t ipmap;
-
-
-
- ipmap_t::iterator iter = ipmap.upper_bound(ip);
- if (iter != ipmap.end() && iter->second.startIP <= ip) {
-
- }
按照stl的惯例,upper_bound 返回的是比查找的key大的,iter->first 最小的那个iterator。这里正好利用,找到以后,我们可以保证 ip < iter->first, 也就是IP的上界(开区间上界,不包含),所以,只需要再判断ip是否大于等于下界,也就是startIP,就可以了。
整个过程,相当的简单,明了,不需要自定义Key,不需要多余的Key比较。
为什么不用startIP作为Key并且用lower_bound查找? 我还是说一下吧,lower_bound在查找失败时,其结果等于upper_bound,这样,我们需要对查找成功和失败的情况分别处理,逻辑上要复杂很多,并且容易出错。
使用endIP作为Key并且使用upper_bound查找,可以这样理解:找到endIP大于指定IP的第一个结点,如果这个结点的startIP小于等于指定IP,它就是我们要找的结点。
Map可以应付运行中添加删除的情况,如果不需要运行中添加删除,使用排序的 vector ,再结合 std::upper_bound 就可以了,速度会更快,并且更省内存。具体代码,自己动手吧。
同样的思路,同样的方法,可以用在操作系统虚拟地址范围的查找,文件偏移范围的查找,时间范围的查找,等等,等等。
分享到:
相关推荐
代码重点是hash_table,附加std::map与其做对比,实现的是一条sql语句:select c_nationkey, c_mktsegment, count(*), max(c_acctbal) from aaa_customer_1g group by c_nationkey, c_mktsegment order by c_...
c++11引入了std::bind及std::function,实现了函数的存储和绑定,即先将可调用的对象保存起来,在需要的时候再调用。定义了SignalObject信号类和SlotObject槽类,其中信号类中的 std::function(int)> _call就是要...
std::list没有[]函数或Get()函数,又不能总是front()的方式排出,如何遍历获得其中的元素呢?比如 遍历显示元素内容为例 ,用两种方式实现。
本程序提供了std::string 类型的Format格式化函数,以及两种格式化string字符串的方法,主方法在str.hpp文件中,测试文件在string_format.cpp中,已测试可用
mfc中引用#include "MyJson.h",就可以直接使用了,代码简单方便,总共2个个文件,安全明了,不需要复杂的引用编译,只需要一个类就可以完成json字符串转map,
一个详细全面的关于vector排序的例子。 涉及到 如何继承std::binary_function, CString, bool>、如何重载operator().
linux 下 std::list的使用
使用C++类模板实现的std::vector容器。 对于学习动态数组有很大的帮助。
friend std::ostream & operator(std::ostream& os, const TinyString<K>& str); template, size_t L> friend bool operator == (const TinyString<K>& s1, const TinyString<L>& s2); //...... uint8...
前面两讲《C++11 并发指南二(std::thread 详解) 》,《C++11 并发指南三(std::mutex 详解) 》分别介绍了 std::thread 和 std::mutex,相信读者对 C++11 中的多线程编程有了一个最基本的认识,本文将介绍 C++11 标准...
从逆向角度看C++ STL代码之std::map
std::string、char*、const char*转托管byte数组或托管字符串String
C++11中提供了异步线程接口std::async,std::async是异步编程的高级封装,相对于直接使用std::thread,std::async的优势在于: 1、std::async会自动创建线程去调用线程函数,相对于低层次的std::thread,使用起来非常...
C++11中的std::async是个模板函数。std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对象。Fn返回的值可通过std::future对象的get成员...
Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mutex> 头文件中,所以如果你需要使用 std::mutex,就必须包含 <mutex> 头文件。 <mutex> 头文件介绍 Mutex 系列类(四种) std::mutex,...
主要介绍了C++ 11 std::function和std::bind使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::shared_future相反)( std::future references shared state that is not shared with any other asynchronous return objects (as opposed to ...
std::ios::sync_with_stdio(false); cin.tie(0); return 0; } 可以增强cin和cout的效率。 在做acm一些题时,经常出现 数据集超大造成 cin读入过多 超时的情况。 这是因为在c++中cin,cout虽然方便但是效率低。 ...
std::move函数可以以非常简单的方式将左值引用转换为右值引用。(左值、左值引用、右值、右值引用 参见:http://www.cnblogs.com/SZxiaochun/p/8017475.html) 通过std::move,可以避免不必要的拷贝操作。 std::move...
摘要:在这篇文章里,将从各个角度介绍下std::array的用法,希望能带来一些启发。 td::array是在C++11标准中增加的STL容器,它的设计目的是提供与原生数组类似的功能与性能。也正因此,使得std::array有很多与其他...