给定这样一个问题:
有一组从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 就可以了,速度会更快,并且更省内存。具体代码,自己动手吧。
同样的思路,同样的方法,可以用在操作系统虚拟地址范围的查找,文件偏移范围的查找,时间范围的查找,等等,等等。
分享到:
相关推荐
1. **容器类**:如`std::vector`、`std::map`等,提供数据存储和操作的能力,支持动态大小调整和高效的查找、插入、删除操作。 2. **迭代器**:用于遍历容器中的元素,是C++标准模板库(STL)的重要组成部分。 3. ...
1. **多线程**:使用`std::thread`库或者Windows API的`CreateThread`函数创建多个线程,每个线程负责扫描一部分IP地址范围。 2. **网络扫描**:可能使用`socket`API创建网络套接字,向目标IP发送探测包。如果是TCP...
6. map(映射):关联容器,以键值对的形式存储数据,提供高效的查找功能。 7. multimap(多重映射):与map类似,但允许键的重复。 8. set(集合):无序的唯一元素集合,元素之间可以比较。 9. multiset(多重集合...
- **容器内的数据结构**: 如`set`和`multiset`使用红黑树实现,`unordered_set`和`unordered_map`使用哈希表。 5. **算法**: - **排序算法**: 冒泡排序,选择排序,插入排序,快速排序,归并排序,堆排序等。 -...
`std::set`和`std::map`是基于红黑树的数据结构,用于存储唯一元素,并提供快速查找功能。 2. 迭代器:迭代器是访问容器中元素的接口,类似于指针,但具有更多功能,如正向、反向和随机访问迭代器。 3. 算法:STL...
#### 示例:使用`find()`函数 以下是一个简单的示例,展示了如何使用`find()`函数在数组中查找特定的值: ```cpp #include #include #define SIZE 100 int main() { int iarray[SIZE]; iarray[20] = 50; // ...
例如,可能会用到`std::vector`和`std::map`等容器模板,以及`std::algorithm`头文件中的函数模板。 8. **单元测试**:为了确保代码质量,开发过程中可能会使用如Google Test这样的单元测试框架,对每个模块进行...
3. **算法**:刷题平台如牛客网、LeetCode上的算法题目是面试必备,熟练掌握各种排序(如快速排序、归并排序)、查找算法(如二分查找、哈希查找)等。 4. **数据库事务的特征**:ACID(原子性、一致性、隔离性、...
9. **实例228**:可能涉及到了C++的STL(Standard Template Library),包括容器(如`vector`、`list`、`map`)、算法(如排序、查找)和迭代器的使用。 10. **实例221**:可能关于并发和异步编程,如`std::async`...
6. **智能指针**:std::unique_ptr、std::shared_ptr、std::weak_ptr的理解和使用,以及RAII(Resource Acquisition Is Initialization)原则。 三、实战与综合应用 1. **算法与数据结构**:常见的排序算法(冒泡...
` 使程序能够直接使用`std`命名空间下的元素而无需前缀。 - **主函数**:`int main()` 是程序的入口点。可以带参数或不带参数,通常形式为 `int main(int argc, char* argv[])` 来接收命令行参数。 - **注释**: ...
3. 存储数据:将读取到的数据结构化存储,例如使用std::vector或std::map等容器,以便于查找。 4. 实现查询功能:用户输入IP地址后,程序通过比较找到匹配的条目,返回相关地理位置信息。 5. 错误处理:考虑文件不...
例如,`std::vector`提供动态数组功能,`std::map`实现关联数组,`std::sort`则可以对序列进行排序。理解这些容器和算法的工作原理,能帮助开发者编写更高效、可维护的代码。 在Linux高级编程中,会接触到以下关键...
C++标准库中的`std::unordered_map`和`std::unordered_set`是其代表。 - **树**:包括二叉树(如二叉搜索树、平衡树AVL、红黑树等)、B树、B+树等,它们在数据库索引、文件系统等方面有广泛应用。 - **图**:图...
- **STL容器**:熟悉vector、list、set、map等容器的使用和操作。 3. **异常处理** - **try-catch语句**:掌握异常抛出和捕获机制,理解throw和catch关键字的用法。 - **异常类层次**:了解std::exception及其...
2. **C++标准库**:在实现通讯管理系统时,可能会用到C++标准库中的容器(如`std::vector`、`std::map`)来存储和管理数据,以及算法(如排序、查找)来处理通信事件。 3. **多线程**:为了实现并发处理,C++提供了...
在MFC中,可以使用容器类如std::vector或std::map来存储和操作用户的好友列表。当用户请求添加或删除好友时,系统会更新相应的数据结构,并可能触发消息通知其他用户。 此外,为了提高用户体验,聊天室通常会提供...
3. **STL(Standard Template Library)**:熟悉容器(如vector、list、set、map)、迭代器、算法(如排序、查找)以及函数对象。 4. **C++内存管理**:了解栈与堆的区别,掌握动态内存分配(new/delete)和智能...
本实验通过详细的步骤和示例,介绍了Cisco路由器在IP路由方面的一些核心概念和技术,包括但不限于最长匹配原则、OSPF协议的使用、静态路由的配置以及如何通过路由映射实现基于源地址的路由选择等。这些技术在实际...
7. **STL(Standard Template Library)**:熟悉容器(如vector、list、deque、set、map等)、迭代器、算法(排序、查找等)和函数对象(如比较函数、适配器等)的使用,这是现代C++编程的必备技能。 8. **C++11及...