杭电数据结构课程实践-哈密顿图的判断

哈密顿图的判断

      • 需求分析
      • 详细设计
      • 程序流程图

需求分析

  经过图中的每个顶点一次且仅一次的通路称为哈密顿通路,经过图中每个顶点一次且仅一次的回路称为哈密顿回路,具有哈密顿回路的图称为哈密顿图,具有哈密顿通路但不具有哈密顿回路的图称为半哈密顿图。哈密顿图是关于连通图的问题,在邮路问题、旅行问题、售货问题等都有较好的应用价值。
  判断哈密顿图的充要条件是图论中尚未解决的难题,但应用图的深度优先搜索策略却能描述一个判断哈密顿图是否存在的算法。借助辅助工作栈,初始所有顶点均设置为未被访问状态false,计数器count=0,且设u为源点,用深度优先搜索策略判断哈密顿图的递归算法大致如下:

  1. 从图中某个顶点u出发,该顶点入栈,设置该项点访问状态为true, count++。
  2. 依次从与u邻接且未被访问过的邻接点出发,在count小于图中的顶点数且栈不空时重复(1)、(2),递归地深度优先搜索图,直至当前顶点u的所有邻接点都已被访问。
  3. 若此时count小于图中的顶点数,则count–,设置当前顶点u的访问状态为false,退栈,回到步骤(2)。或count等于图中的顶点数但源点不是当前结点u的邻接点,该图至少是半哈密顿图,若要继续做哈密顿图的判断,则同样置当前顶点u的访问状态为false、退栈,回到步骤(2)。执行以上步骤,直至count等于图中的顶点数且源点是当前结点u的邻接点,则该图存在哈密顿回路,是哈密顿图;或栈空,则该图不是哈密顿图。

  应用图的深度优先搜索策略判断哈密顿图是否存在的算法是基于邻接点的搜索策略,由于图的邻接表表示法在取顶点的邻接点操作时因表中没有无效的邻接点信息而操作效率比数组表示法高,因此,本算法选用邻接表表示法作为图的存储结构,并在此基础上实现图的抽象数据类型及描述哈密顿图的判断算法。

详细设计

#include 
#include 
#include "图抽象类型的实现(邻接表).h"
using namespace std;
//访问函数实体 
void print( char *i )
{
     
    cout << setw( 3 ) << i;
}

typedef int SElemType; // 栈类型
#include"SqStack.h" 

// 从第v个顶点出发,深度优先方式(递归)搜索哈密顿路径
void HMDDFS( ALGraph G, int v, int &u, int &count, SqStack &S1, SqStack &S2, bool &tag1, bool &tag2 )
{
      
    visited[ v ] = true; // 设置访问标志为TRUE(已访问)
    PushSqStack( S1, v );
    if ( ! tag2 ) PushSqStack( S2, v ); 
        count++;
    ArcNode *p;
    if ( count < G.vexnum )
    {
      
        for ( p = G.vertices[ v ].firstarc; p && ! tag1; p = p->nextarc )   
            if ( ! visited[ p->adjvex ] )// 对v的尚未访问的邻接点w递归调用HMDDFS
                HMDDFS( G, p->adjvex, u, count, S1, S2,tag1, tag2 );
        if ( ! tag1 )
        {
     
            count--;
            PopSqStack( S1, v ); //回溯 
            if ( ! tag2 ) 
                PopSqStack( S2, v );
            visited[ v ] = false; 
        }
         
    }    
    else 
    {
     
        tag2 = true; //找到哈密顿通路 
        for ( p = G.vertices[ v ].firstarc; p; p = p->nextarc )   
            if ( p->adjvex == u )
            {
     
                tag1 = true;//找到哈密顿回路 
                PushSqStack( S1, u );
            }
        if( ! tag1 )
        {
     
            count--;
            PopSqStack( S1, v );//回溯 
            visited[ v ] = false; 
        }        
          
    }
}
// 对哈密顿图的判断
void HMDSearch( ALGraph G, void( *Visit )( char* ) )
{
      
    SqStack S1, S2, T;
    InitSqStack( S1, G.vexnum + 1 );//若图G为哈密顿图,栈s1 存放哈密顿回路 
    InitSqStack( S2, G.vexnum + 1 );//若图G为半哈密顿图,栈s2 存放哈密顿通路
    InitSqStack( T, G.vexnum + 1 );//T为辅助栈,用以输出 哈密顿回路或哈密顿通路 
    int v;
    for ( v = 0; v < G.vexnum; v++ )
        visited[ v ] = false; // 访问标志数组初始化; 
    v = 0; 
    int count = 0; 
     //若tag1为true,则图G是哈密顿图,若tag2为true则图G是半哈密顿图
    bool tag1 = false, tag2 = false; 
     // 具有哈密顿回路的图为哈密顿图,因此,v既是源点,也是终点 
    HMDDFS( G, v, v, count, S1, S2, tag1, tag2 );     
    if( tag1 )
    {
     
        cout << endl << "该图为哈密顿图,一条哈密顿回路为:" << endl; 
        while ( ! SqStackEmpty( S1 ) )
        {
     
            PopSqStack( S1, v );
            PushSqStack( T, v );        
        }
        while ( ! SqStackEmpty( T ) )
        {
     
            PopSqStack( T, v );
            Visit( G.vertices[ v ].data );
        }
    } 
    else
    {
      //在图G非哈密顿图的情况下,依次从每一顶点出发探测哈密顿通路          
        for ( v = 1; ! tag2 && v < G.vexnum; v++)
            HMDDFS(G, v, v, count, S1, S2, tag1, tag2); 
        if ( tag2 )
        {
     
            cout << endl << "该图为半哈密顿图,一条哈密顿通路为:" << endl; 
            while ( ! SqStackEmpty( S2 ) )
            {
     
                PopSqStack( S2, v );
                PushSqStack( T, v );        
            }
            while ( ! SqStackEmpty( T ) )
            {
     
                PopSqStack( T, v );
                Visit( G.vertices[ v ].data );
            }
        } 
        else
            cout << endl << "该图不是哈密顿图。" << endl;  
    }
    cout << endl;    
}
int main()
{
     
    ALGraph g;
    CreateGraph( g );
    Display( g );
    HMDSearch( g, print );
    cout << endl;
  
    return 0;
}

程序流程图

杭电数据结构课程实践-哈密顿图的判断_第1张图片

你可能感兴趣的:(杭电数据结构课程设计)