A逐点循环递归法求哈密顿回路

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

逐点循环递归法求哈密顿回路
王彦祺
(石家庄经济学院信息工程系,河北石家庄 050031)
摘要:本文给出求解任意图的所有哈密顿回路算法,即“逐点循环递归算法”,用于处理复杂的“旅行商问题”,证明一个图是否是哈密顿图等。

在算法中,给出一个“结点标号数组”,用于存储一个回路;还给出一个无向图的正向表,用于存储初始图。

关键词:哈密顿回路,算法,无向图正向表,结点标号数组, 递归。

An Algorithm of Cycle and Recursion by Every Vertex
for Getting Hamilton Cycle
Wang Yanqi
(Department of Information Engineering, Shijiazhuang University of Economics,Shijiazhuang,Hebei 050031)
Abstract: This paper gives out an algorithm of getting all Hamilton cycle from a common graph,that is "an algorithm of cycle and recursion by every vertex", which can solve complex "travelling salesman problem ",prove that a graph is Hamilton graph or not, and so on. In algorithm, I give out a "array of signed vertex ",for storing a cycle, and a "positive direction table for non-directed graph ",for storing a given graph.
Key Words: Hamilton cycle, algorithm, array of signed vertex, positive direction table for non-directed graph, recursion.
1.问题的提出
1)任给定一个无向图,如何求无向图的哈密顿图的回路,首先必须判断该图是否是哈密顿图。

如果图很复杂又有哈密顿图回路,用手工是很难找到的,该算法很容易找到任何图的所有哈密顿回路,如果一条也找不到,即证明了该图不是哈密顿图。

2) 在求解“旅行商问题”时,考虑的是带权完全无向图,“分支定界法”只是求出最小的哈密顿回路,对于任意图是不可行的。

3) 在求解“旅行商问题”时,有时只求出路径最小的哈密顿回路不一定是最佳的哈密
顿回路。

因为在旅行时,所考虑的不仅仅是费用或旅程,比如,有的路线虽短,但路线人员拥挤,如果单纯按最小的哈密顿回路旅行是不现实的,反而费用更高。

此时求出若干最小的哈密顿回路,甚至求出所有的哈密顿回路,才能正确的决策旅行路线。

4)如果按边的组合方法,则运算次数将是极大的,本文给出求解一般图的所有哈密顿回路的“按结点循环递归算法”。

5)本文约定,H代表哈密顿,hn代表图的结点数,hm代表图的边数。

2.算法的依据.
2.1 有关的定理
定理 1. H回路中的每一个结点的度数d H(v)必是2 ,反之不成立。

证明:H回路的结点度数必是2。

反之不成立,如图 1所示, 共7个结点,7个边,每个结点的度数为2,但不是H回路。

当回路的边数不到结点数,我们称为“局部回路”。

当回路的边数等于结点数hn,即为“哈密顿回路”。

v3 v4
图 1
定理2. 任何无向图的回路,如果结点号和数组下标一一对应,可采用一维数组存储,结
点标号为数组下标号,也是边的起点, 该下标的数组元素的值是边的终点标号,也是下一个
边的起点下标。

(本文称为“结点标号数组”)。

证明:(构造法)首先将无向图的结点按连续的自然数编号,使结点号和数组下标号是一一
对应;因为是回路,每一个结点号在回路中必出现两次,且保证回路中的边的第一个结点的
标号(下标)不重复及第二个结点的标号(数组元素值)不重复。

因为是简单图,下标号和
该下标的数组元素值一定是不同的,下标号为边的起点,该下标号下的数组元素值是该边的
终点,又是下一个边的起点下标。

不妨令回路的结点数为4,其中一个H 回路的边为 {(1,2),(2,4),(4,3),(3,1)}, 即1---2---4---3---1,请看表1。

结点下标数组存储H 回
路的优点是即节省空间,又便于边的连接,特别是更易于编程。

如果结点下标数组包含图的
所有结点,则该回路为哈密顿回路。

表 1
定理3. 如果图G=(V,E)有n 个结点(m>=n),有n 条不同的边的组合,且结点的度数均为
2,如果按定理2的方法存储,从数组下标1开始,,将下标1的数组元素值作为下一个下标,,
再取元素值,直至元素值为1止。

如果此时边计数k 等于n,则该k 条边的组合,即是一条H
回路;否则,该k 条边是个“局部回路”。

证明:显然。

证明略。

请看图1。

2..2 存储结构
1) 初始图的存储结构. 首先将图的结点按度数由大到小重新编号为1,2,3…,即最小号,度数最大,采用无向图的正向表存储。

既结点i 的后继结点(终点号)只能是大于i,从而保证边的不重复。

特点是,第一个结点的后继必然大于等于2,最后一个结点的后继必然为0,而其它结点的后继必然大于等于1(如果为0,将出现割点,不可能有H 回路)。

第一个结点的度数最大是必须的,因为循环递归从第一个结点(标号为1)开始,作为第一个起始标号,必
须在终点数组中至少存在两个终点,组合构成两个边。

而其它起始标号,边的构成复杂,首
先必须逐一的按一个结点构成一条边加入HC 回路数组。

如果将结点度数大的放在中间,将
大大增加循环递归次数。

如图2 所示,是一个无向图,有6个结点,11条边,按无向图的
正向表的存储结构,请看表 2。

一个边的起点一维数组A ,下标和结点号一一对应。

每一个
下标的元素值是边的该起点的后继(第一个终点)在终点一维数组B 的地址(下标号)。


后一个结点的元素值是m+1;该图为12(不作为地址,只用于计算上一个结点的终点数)。


个边的终点一维数组B ,下标只是起地址作用,下标的元素值是边的终点标号。

表 2
1 2
6 3
5 4
图 2
2)输出H回路的存储结构:H回路数组HC[1..hn],采用结点标号数组存储回路。

(请看定理2)。

3)结点度计数数组:结点度计数数组CT[1..hn],用于向H回路数组中加边时的度数判断,如果计数大于2,则该边不可加入。

如果HC[1..hn]中的边加到hn,且CT[1..hn]全为2,则加边结束;如果HC[1..hn]中无局部回路,则HC[1..hn]的回路是H回路。

3.算法的基本思想
按起点(结点号)与它的若干终点组成不同的边进行循环,满足向HC回路数组中加边条件,则起点加1,进行递归,HC回路数组的边数达到结点数且满足H回路条件,输出一条H回路。

递归返回时,本次边从HC回路数组中清除,对应的结点度计数数组减1。

3.1循环递归的向回路数组加边:
从起点数组A的第一个下标(边的起点)开始循环,以该下标的元素值(地址)到终点数组B中找该起点的终点构成边,由于采用无向图正向表方法,第1个起点无条件必取两个终点,构成两个边,加入到HC回路数组中。

如令终点数为k,则有C k2个组合。

其余起点,可取的终点数为0-2个,根据前面结点满足条件的情况(既结点的度数是否已为2)。

由该结点构成的边可加入HC回路数组中的条件是:(1)起点和终点,在HC回路数组,即可起点作为下标,终点作为该下标的元素值,又可终点作为下标,起点作为该下标的元素值。

两种情况是不一样的,将影响下面结点的边组合。

不论如何,当HC回路数组的该下标的元素值非0时,此边不能加入到HC回路数组中。

如果上面的元素值为0,即可加入该边。

(2)如果边可以加入到HC回路数组中,加入后,对应该边的两点值作为度计数数组下标,对度计数数组进行计数,如果出现度数大于2,则该边不满足条件,不能进行递归,取下一组边组合进行判断,如果无或满足条件,则进行下一个结点的递归。

递归返回,必须将该次循环的边从HC回路数组中删除,且将对应的度计数数组CT计数减1。

如何加入边有4种情况:
(1)如果起点和终点的度数有一个为2,则由该起点构成的边不能加入到HC回路数组。

不进行下一个起点的递归
(2)将起点和每一个终点构成一条边,如果满足条件,将该边加入到HC回路数组,进行下一个起点的递归。

(3)将起点和每两个终点(终点数大于1)构成两条边,如果两个边均满足条件,将该边加入到HC回路数组,进行下一个起点的递归。

(4)不加入任何边,进行下一个起点的递归。

(空递归)
3.2 H回路检测条件:
在循环递归中,当HC回路数组加入的边数达到hn个,检测HC回路数组是否有局部回路,如果无,则找到一条H回路,输出到屏幕,文件或打印。

因为HC回路数组是结点下标数组,检测是否有局部回路,是很简单的。

方法是:从下标1开始,取下标的元素值,作为下标,计数加1,如果元素值不为1,则继续,再取下标的元素值,作为下标,计数加1;如果元素值为1,则该回路结束;如果结点计数为结点数hn,该回路是H回路,如果计数小于结点数hn,该回路是局部回路。

注意:(1)每构成一条边,它的起点和终点作为CT的下标计数到CT度计数数组中,用于控制加边的条件。

(2)递归前将满足条件的边加入到HC回路数组中,递归后将满足条件的边从HC数组中清除掉(即数组元素值为0,同时将对应的结点度计数数组CT的元素值减1,为下一次循环递归作准备。

4.算法描述 (只给出关键函数,循环递归函数逻辑图)
4.1初始化:(定义数组)(均为整型,int)
(1)起点数组A[1..hn]和终点数组数组B[1..hm]按实际图赋值。

(2)H回路数组HC[1..hn]和结点度计数数组CT[1..hn] 全部清0
4.2 主要函数
(1)H回路判别函数 int hcp()。

当回路数组边计数达到hn时,调用该函数。

如果不是局部回路,即为H回路,返回1;否则,不是,返回0。

(2)HC回路数组输出函数 pt()。

当构成一条H回路,调该函数,最好使用文件存储。

(3)HC回路数组加边的循环递归函数 search( int n)。

当结点数hn>2时,调该函数,
n=1 ; search( int n)
4.3循环递归函数search( int n)逻辑图
只给出一个起点和一个终点的循环递归逻辑图,逻辑图如图3。

图 3
4.4实例(图2)的运算结果
共有四个H回路。

no= 1,[1,2][2,3][3,4] [4,6] [5,1] [6,5]
no= 2,[1,2][2,3][3,4] [4,5] [5,6] [6,1]
no= 3,[1,3 ][2,4 ][3,2] [4,6] [5,1] [6,5]
no= 4,[1,3 ][2,4 ][3,2] [4,5] [5,6] [6,1]
当no= 1时HC回路数组的值为{2,3,4,6,1,5},其他类似。

4.5算法的复杂度
该算法复杂度比较难于估计,只对一个起点的情况进行估计,令一个起点的对应终点数为k,则有C k2+ C k1+1个组合。

复杂度最坏为O(C k2+ C k1+1)。

5.结语:
此求解一般图的所有哈密顿回路算法,适合于任何边数的图,但随着边数的增加,循环的次数增加很大。

但边数少的图,是非常快的,非常有效的。

如果,将边加上权,将HC 回路数组加上一维,用于存放权值,将无向图正向表,加入权值,加入求解最大值或排序算法,即可解决任何图的“旅行商问题”。

参考文献:[1] 戴一奇,胡冠章,陈卫“图论与代数结构”,清华大学出版社,1995
[2] [美] J.A.Bondy and U.S.R.Murty “图论及其应用”,科技出版社,1984
[3] 尹宝林,何自强等著,“离散数学”,高等教育出版社,1998
[4]李盘林,李丽双等著,“离散数学”,高等教育出版社,1999。

相关文档
最新文档