二分查找(下):如何快速定位IP对应的省份地址?
Posted mysky007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找(下):如何快速定位IP对应的省份地址?相关的知识,希望对你有一定的参考价值。
问题
假设我们有 12 万条这样的 IP 区间与归属地的对应关系,如何快速定位出一个 IP 地址的归属地呢?
二分查找的变形
变体一:查找第一个值等于给定值的元素
1 public int bsearch(int[] a, int n, int value) { 2 int low = 0; 3 int high = n - 1; 4 while (low <= high) { 5 int mid = low + ((high - low) >> 1); 6 if (a[mid] >= value) { 7 high = mid - 1; 8 } else { 9 low = mid + 1; 10 } 11 } 12 13 if (low < n && a[low]==value) return low; 14 else return -1; 15 }
换了一种实现方法
1 public int bsearch(int[] a, int n, int value) { 2 int low = 0; 3 int high = n - 1; 4 while (low <= high) { 5 int mid = low + ((high - low) >> 1); 6 if (a[mid] > value) { 7 high = mid - 1; 8 } else if (a[mid] < value) { 9 low = mid + 1; 10 } else { 11 if ((mid == 0) || (a[mid - 1] != value)) return mid; 12 else high = mid - 1; 13 } 14 } 15 return -1; 16 }
a[mid]跟要查找的 value 的大小关系有三种情况:大于、小于、等于。对于 a[mid]>value 的情况,我们需要更新 high= mid-1;对于 a[mid]<value 的情况,我们需要更新 low=mid+1
变体二:查找最后一个值等于给定值的元素
1 public int bsearch(int[] a, int n, int value) { 2 int low = 0; 3 int high = n - 1; 4 while (low <= high) { 5 int mid = low + ((high - low) >> 1); 6 if (a[mid] > value) { 7 high = mid - 1; 8 } else if (a[mid] < value) { 9 low = mid + 1; 10 } else { 11 if ((mid == n - 1) || (a[mid + 1] != value)) return mid; 12 else low = mid + 1; 13 } 14 } 15 return -1; 16 }
变体三:查找第一个大于等于给定值的元素
1 public int bsearch(int[] a, int n, int value) { 2 int low = 0; 3 int high = n - 1; 4 while (low <= high) { 5 int mid = low + ((high - low) >> 1); 6 if (a[mid] >= value) { 7 if ((mid == 0) || (a[mid - 1] < value)) return mid; 8 else high = mid - 1; 9 } else { 10 low = mid + 1; 11 } 12 } 13 return -1; 14 }
变体四:查找最后一个小于等于给定值的元素
1 public int bsearch7(int[] a, int n, int value) { 2 int low = 0; 3 int high = n - 1; 4 while (low <= high) { 5 int mid = low + ((high - low) >> 1); 6 if (a[mid] > value) { 7 high = mid - 1; 8 } else { 9 if ((mid == n - 1) || (a[mid + 1] > value)) return mid; 10 else low = mid + 1; 11 } 12 } 13 return -1; 14 }
问题解决分析
1. 如果 IP 区间与归属地的对应关系不经常更新,我们可以先预处理这 12 万条数据,让其按照起始 IP 从小到大排序。如何来排序呢?我们知道,IP 地址可以转化为 32 位的整型数。所以,我们可以将起始地址,按照对应的整型值的大小关系,从小到大进行排序。
2. 然后,这个问题就可以转化为我刚讲的第四种变形问题“在有序数组中,查找最后一个小于等于某个给定值的元素”了
3. 当我们要查询某个 IP 归属地时,我们可以先通过二分查找,找到最后一个起始 IP 小于等于这个 IP 的 IP 区间,然后,检查这个 IP 是否在这个 IP 区间内,如果在,我们就取出对应的归属地显示;如果不在,就返回未查找到
以上是关于二分查找(下):如何快速定位IP对应的省份地址?的主要内容,如果未能解决你的问题,请参考以下文章
Windows 逆向使用 CE 分析内存地址 ( 运行游戏 | 使用 CE 工具分析游戏内子弹数量对应的内存地址 | 内存地址初步查找 | 使用二分法定位最终的内存地址 )