python查找函数路径_编写可在图形中查找汉密尔顿路径的Python函数

本文探讨了使用Python实现寻找图形中汉密尔顿路径的问题,其中涉及一个递归函数hampath_finder。作者在解决过程中遇到了回溯和效率问题,并逐步改进了代码。尽管找到了解决方案,但作者指出汉密尔顿路径问题属于NP完全问题,意味着在大型数据集上可能非常慢,建议考虑使用更高效的编程语言如C或C++进行优化。
摘要由CSDN通过智能技术生成

我正在尝试编写一个函数,该函数将正整数n作为输入,并将整数1到n按顺序排列,以使每个相邻数字的总和为一个完美的平方(如果存在这样的顺序)。我意识到,如果创建一个图形,其中顶点是数字,并且如果两个顶点的和是一个完美的正方形,则两个顶点之间会有一条边,那么这个问题就相当于试图在图形中找到一个哈密顿路径。因此,我试图编写一个函数,该函数将在给定图中查找汉密尔顿图(如果存在)。这是我的代码:

defhampath_finder(moves,start,path=None):ifpathisNone:path=[]iflen(path)==bound:returnpathifnotpath:path=path+[start]forcandidateinmoves[start]:ifcandidatenotinpath:path=path+[candidate]new_path=hampath_finder(moves,candidate,path)ifnew_path:returnnew_pathelse:continueelse:returnNonereturnNone

“ Moves”是图形的字典(已经使用了变量“ graph”,并且我不太擅长为变量命名),其中每个顶点都是一个键,每个键的值是一个列表,其中包含与该顶点相邻的其他顶点关键顶点。例如,当输入为15时,这是字典:

{1:[3,8,15],2:[7,14],3:[1,6,13],4:[5,12],5:[4,11],6:[3,10],7:[2,9],8:[1],9:[7],10:[6,15],11:[5,14],12:[4,13],13:[3,12],14:[2,11],15:[1,10]}

起点是哈密顿路径的起点。(我尝试编写此函数时没有起点,因此该函数本身会将每个点都作为起点,但是它变得很复杂。现在,我自己自己遍历所有顶点。)

我知道对于数字15,应该给我以下列表:

[9,7,2,14,11,5,4,12,13,3,6,10,15,1,8]

但是,它给了我这个列表:

[9,7,2,14,11,5,4,12,13,3,1,8,15,10,6]

考虑到该函数的工作方式,我意识到,一旦达到1,它将首先加8作为下一个数字。但是,8在除1之外的顶点之间没有任何边。老实说,我不知道接下来会做什么。我意识到,一旦没有可能的候选人可以尝试,就需要回溯并回到最后的正常位置。我不知道该如何实现。

我该如何解决这个问题?另外,如何改善我的代码?

我对Python还是很陌生,所以如果这个问题不重要或我的代码很糟糕,我深表歉意。

编辑:我想我已经解决了主要问题,它现在返回正确的列表。这是新的代码:

defhampath_finder(moves,start,path=None):ifpathisNone:path=[]iflen(path)==bound:returnpathifnotpath:path=path+[start]forcandidateinmoves[start]:ifcandidatenotinpath:new_path=hampath_finder(moves,candidate,path+[candidate])ifnew_path:returnnew_path

我认为问题在于,一旦我们走到了尽头,错误的路径已经被追加到列表中path,这就是为什么在先前代码的输出中有8的原因。

现在,问题在于该函数None在返回列表之后返回。因此,这是我为数字15运行此函数时的输出,即图形是我之前提到的字典:

[8,1,15,10,6,3,13,12,4,5,11,14,2,7,9]None

如何解决此问题,使其不返回None?顺便说一句,我仍然必须自己尝试每个数字作为起点。这是我的工作:

fornumberinrange(1,16):ifhampath_finder(moves,number):print(hampath_finder(moves,number))

换句话说,我必须手动尝试将每个数字作为路径的开头。如何调整原始功能,使其不需要起点,并尝试所有可能的数字?

此外,即使数量很少,此功能也要花费很长时间。如何提高效率?

编辑:我意识到,包括整个函数而不是仅包含汉密尔顿路径部分会更有帮助,因为否则某些变量是不确定的。

frommathimportsqrtdefadjacent_square(bound):defblueprint(bound):graph={}fornumberinrange(1,bound+1):pos_neighbours=[]forcandidateinrange(1,bound+1):ifsqrt(number+candidate)==int(sqrt(number+candidate))andnumber!=candidate:pos_neighbours.append(candidate)graph[number]=pos_neighboursreturngraph

graph=blueprint(bound)defhampath_finder(mapping,start,path=None):ifpathisNone:path=[]iflen(path)==bound:returnpathifnotpath:path=path+[start]forcandidateinmapping[start]:ifcandidatenotinpath:new_path=hampath_finder(mapping,candidate,path+[candidate])ifnew_path:returnnew_pathfornuminrange(1,bound+1):ifhampath_finder(graph,num):print(hampath_finder(graph,num))breakelse:print("No such order exists.")

该函数blueprint通过检查每个可能的对的总和来创建图形。我已经解释过了hampath_finder。之后,我尝试使用for循环将每个数字作为路径的起点。

解决方案

我认为您得到的原因None是因为在hampath_finder函数中您仅返回一个值if new_path:。如果没有新路径且函数返回,则Python将返回None。您可以通过以下示例看到这一点:

deftestfunct(test):iftest:returnTrueprint(testfunct(False))

>>>None

此外,您要计算两次hampath_finder。一次查看是否存在,然后再次打印。我将更改您的代码的这一部分:

fornuminrange(1,bound+1):ifhampath_finder(graph,num):print(hampath_finder(graph,num))break

要更像这样:

fornuminrange(1,bound+1):this_path=hampath_finder(graph,num)iflen(this_path)>0:print(this_path)break

这将有助于少量的速度。

However, a cursory look at the Hamiltonian Path Problem looks like it is an NP-Complete problem. So it is going to be very slow. There are some research papers that have faster implementations that are out of the scope of StackOverflow. Also, if speed is necessary, then you will probably want to switch the implementation to something like C or C++.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值