N叉树的所有路径搜索

N叉树所有路径搜索(BFS深度优先搜索)

在之前求解二叉树最大深度、最小深度以及所有路径的时候,很自然的想到要枚举出所有可行路径,从而解决问题。
从上述问题当中引申出新的问题,便是如何求解“三叉树”、“四叉树”、“五叉树”,乃至“N叉树”的所有路径问题。二叉树中每个结点有一个数据项,最多有两个子节点,如果允许树的每个节点可以有两个以上的子节点,那么这个树就称为N阶的多叉树,或者称为N叉树。
很快,我也遇到了其中之一:从字符串中提取所有可用的IP地址(IPV4)。

IPv4地址可被写作任何表示一个32位整数值的形式,但为了方便人类阅读和分析,它通常被写作点分十进制的形式,即四个字节被分开用十进制写出,中间用点分隔。如图1所示:

在这里插入图片描述

其中:IPV4 长度为 32 位(4 个字节)。地址由网络和主机部分组成,这取决于地址类。根据地址的前几位,可定义各种地址类:A、B、C、D 或 E。IPv4 地址的总数为 4 294 967 296。

IPv4 地址的文本格式为 nnn.nnn.nnn.nnn,其中 0<=nnn<=255,而每个 n 都是十进制数。可省略前导零。

从IPV4的地址定义可知,IPV4共含四段地址,且每段地址范围为0-255
由此我们将该IP地址搜索转化为:三叉树的所有路径搜索问题。

假设由样例得到的字符串为:25525511135
那么先简单地列出部分路径,如图二所示:在这里插入图片描述

根据地址分配原则,
第一段地址可以分配为 2、25、255
那么由第一段地址2向下继续分配,地址段二又可以分配为 5、55、552。
根据地址段最大为255,将552舍弃。
则5下面的 第三段地址又可以分配为5、52、525(舍弃)。
55下面的则为: 55:2、25、255。

当我们准备继续向下搜索IP地址时,可以发现:
样例所示字符串长度为11,
第一层深度如果取长度为1的子串作为第一段地址,那么剩余字符串长度为10。很显然,这大于了3*3=9(其余三段地址最大长度)。
在尝试将2作为第一段地址时,就可以舍弃这种分配方案了,不需要向下再做多余的路径遍历。应当返回上一层深度,由25作为第一段地址向下扩展深度。

综上所述:不难发现,从样例字符串找出合理的IP地址至少需要满足两个条件:
1 深度与剩余子串最大长度满足特殊关系
2 地址段取值区间为[0,255]

此时计算条件1:

DepthMax length of the left str
012
19
26
33
40

根据上表所示,可以得到深度与所剩子串最大长度关系式为:
str_left.len > 12-(3 * Depth)

其实条件1、2又被称为:剪枝条件

由此可以将图二的路径优化为下图图三所示:在这里插入图片描述

层层递归,如果不满足条件1、2,那么返回上一层(Return);若满足,则继续进行下一层递归。
即在搜索其余的超链结果之前必须先完整地搜索单独的一条链。

同理:如果是“4叉树”,“5叉树”,“N叉树”,都可以用此方式进行搜索,从所有路径中选出可行路径,以此正确输出。

附录

代码如下

/* Name:	 RestoreIpAddresses(string s)
*  Function: Output all the valid examples for IP address
*  Example:  Input = 25525511135
*			 Output = "255.255.11.135", "255.255.111.35"
*  Return:	 vector<string>
*/
vector<string> RestoreIpAddresses(string s)
{
	vector<string> result;
	string tmp = "";
	Recursion(s, result, tmp, 0);
	return result;
}
/* Name:	 Recursion(string s, vector<string>&result, string tmp, int depth)
*  Function: Recursion the tree to find all the Ip address
*  Parament: string s ; vector<string>&result ; string tmp ; int depth ; 
*
*  Return:	 void
*/
void Recursion(string s, vector<string>&result, string tmp, int depth)
{
	
	if (s.size() > 12 - (3 * depth))
		return;
	if (depth == 4 && s.size() == 0)
	{
		tmp.pop_back();
		result.push_back(tmp);
		
	}

	for (int bit = 1; bit <= 3; bit++)
	{
		if (s.size() < bit)
			return;
		/*判断0-255*/
		int value = stoi(s.substr(0, bit));
		if (value > 255 || ( bit != 1 && s[0] == '0'))
			break;
		/*临时string = string[0]--string[bit]+ "." */
		tmp += s.substr(0, bit)+'.';	
		/*递归*/
		Recursion(s.substr(bit), result, tmp, depth+1);
		/*从上一层返回*/
		tmp = tmp.substr(0, tmp.size() - bit - 1);

	}
}
Recursion(s.substr(bit), result, tmp, depth+1);
		/*从上一层返回*/
		tmp = tmp.substr(0, tmp.size() - bit - 1);

	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值