双重二分查找的应用

前几天面试的时候遇到一个问题,给定n个ip地址和m个ip地址块,如何判断,这n个地址是否在这m个ip地址块中的任意一个中。

后来想到了一个双重二分查找的方法,思路如下:

以IPv4地址为例,一共32位,为了方便记忆采用点分10进制方法标识。其本质是32位无符号整形,每一位不是0就是1,这样用来标

记2^32-1个不同的unsigned型整数,

每一个数代表一个网络地址。所以,对于一个给定的IP地址块,可以看成是一个具有上限和下限的unsigned整形区间,例如在区间

[142.235.6.34,142.235.160.140]之间

的IP地址其整形值的范围为[2397767202,2397806732],如果需要查询的IP地址转换成unsigned int型之后在上述区间,则表示命

中,否则没有命中。

在给定的n个地址块中,首先要进行重复区间的合并问题,这里涉及到区间树。区间树基于红黑树实现。这里先不作讨论。在测试例

子中我们生成n个没有交集的IP地址块。这样就

可以得到n个unsigned int型的区间,每一个区间的记为[low_i, high_i],low_i表示第i个地址块的下限,high_i表示第i个地址块的上

限,则有high_i-1<low_i(n>=i>=2)。

         下面以[10,20],[30,50], [70,90], [100,129], [150,210]这五个区间为例。

如果tar_num>210或是tar_num<10,则直接可以断定这个数不在给定的区间范围;

假设我们查找的数是tar_num=95,那么初始状态如下:



关键代码:

 //二分查找法
 bool binary_search_check(string ip){
	 int size = low.size();
	 unsigned int ip_int = str_to_uint(ip);
	 unsigned int t1 = high[size - 1], t2 = low[0];
	 if (ip_int >t1|| ip_int < t2)return false;
	 //判断上限范围
	 int low_t = 0,high_t=size-1,mid_t;
	 int low_index = -1;
	 while (low_t<high_t){
		 mid_t = (low_t + high_t)/2;
		 if (high[mid_t] < ip_int)low_t = mid_t + 1;
		 else high_t = mid_t;
	 }
	 low_index = low_t;//找到下限范围
	 //判断下限范围
	 low_t = 0, high_t = size - 1, mid_t;//当low和high相邻的时候,防止陷入死循环
	 int high_index = -1;
	 while (high_t-low_t>1){
		 mid_t = (low_t + high_t)/2;
		 if (low[mid_t] <= ip_int)low_t = mid_t;
		 else high_t = mid_t-1;
	 }
	 if (high_t==low_t) high_index = low_t;//找到下限范围
	 else{
		 if (low[high_t] > ip_int)high_index = low_t;
		 else high_index = high_t;
	 }
	 //判断
	 if (high_index == low_index)return true;
	 else return false;
 }


以上是个人思路,若有不足,欢迎邮件讨论!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值