图的遍历与输出 (邻接矩阵和邻接表)

#include <iostream>
#include <cstdio>
#include "graph.h"
using namespace std;


int main()
{
    freopen("data.in" , "r" , stdin);

//    cout << "\n ** 生成邻接矩阵图,并进行DFS遍历输出: "<< endl;
//    MGraph mg  ;
//    createMGraph(mg);
//    DFSTraverse(mg) ;

    cout << "\n ** 生成邻接表图,并进行DFS遍历输出: "<< endl;
    ALGraph alg ;
    createAdjList(alg);

    DFSTraverse(alg) ;

    cout << "\n ** BFS遍历输出: "<< endl;
    BFSTraverse(alg);

    cout << "\n ** From NO.1 To No.4: " <<endl;
    if( !GetOnePath(alg, 1, 4))
        cout << " NO Path " << endl;

    cout << endl;
    return 0 ;
}


#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED

#define N 20


typedef enum{UDG = 0,DG = 1} GraphKind ; // 图类型:UDG无向图,DG有向图
typedef  char T ;
/***************************邻接矩阵 ****************************/

typedef struct{
    T   vexs[N];      // 顶点向量
    int arcs[N][N];   // 邻接矩阵
    int vexnum, arcnum; //顶点数,边数
    GraphKind kind ;    // 图类型
}MGraph ;


/**********************邻接表****************************/
/** 弧结点类型 */
typedef struct ArcNode
{
	int      adjvex;
	ArcNode  *nextArc;
}ArcNode ;

/** 头结点VNode,头结点向量AdjList类型*/
typedef struct VNode
{
	T         data ;
	ArcNode * firstarc ;
}AdjList[N] ;

//VNode,
/** 邻接图类型*/
typedef struct {
	AdjList vertices;  //头结点向量
	int vexnum, arcnum;
	GraphKind kind;    // UDG无向图 ; DG有向图
}ALGraph;

/**************************基本操作 *******************************/
void createAdjList( ALGraph &g);
void createMGraph( MGraph &g);

void DFS( ALGraph g , int v );
void DFS( MGraph g , int v );

void DFSTraverse( MGraph g );
void DFSTraverse( ALGraph g );

bool GetOnePath( ALGraph g , int v ,int d );

/**输出邻接表图中第v个顶点*/
inline void PrintNode(ALGraph g, int v);


void BFSTraverse(ALGraph g);


#endif // GRAPH_H_INCLUDED

/**
  createGraph.cpp
  读入数据,分别建立图的两种存储"邻接矩阵"和"邻接表"
  操作简单但繁琐,能用它们建立图相应存储结构,非重点
*/

#include "iostream"
#include "graph.h"
using namespace std ;

/* 建立图的 邻接表结构g */
void createAdjList( ALGraph &g)
{
    int i ;

    cin >>(int&)g.kind;
    cin >> g.vexnum ; // 输入顶点数
    cin >> g.arcnum ; // 输入弧数

    /* 输入结点数据,建立头结点向量*/
    for ( i = 1 ; i <= g.vexnum ; i++ )
    {
        cin >> g.vertices[i].data ;
        g.vertices[i].firstarc = NULL ;
    }

    /*输入弧(头,尾),建立邻接表*/
    for ( i= 0 ; i < g.arcnum ; i++ )
    {
        int head , tail ;
        cin >> head >> tail ;

        //生成边结点
        ArcNode * p = new ArcNode ;
        p->adjvex = tail ;

        //头插
        p->nextArc = g.vertices[head].firstarc ;
        g.vertices[head].firstarc = p ;

        if ( g.kind == UDG )  //无向图,还需在尾结点的边链表中插入结点
        {
            ArcNode * p = new ArcNode ;
            p->adjvex = head ;
            p->nextArc = g.vertices[tail].firstarc ;
            g.vertices[tail].firstarc = p ;
        }
    }
}

/* 建立图的 邻接矩阵结构g */
void createMGraph( MGraph &g)
{
    int i , j;

    cin >> (int&)g.kind;
    cin >> g.vexnum; // 输入顶点数
    cin >> g.arcnum; // 输入弧数

    /* 输入结点数据,建立顶点向量*/
    for ( i = 1 ; i <= g.vexnum ; i++ )
    {
        cin >> g.vexs[i];
    }

    /*输入弧(头,尾),建立邻接表*/
    for (i = 1 ; i <= g.vexnum ; i++)
        for (j = 1 ; j <= g.vexnum ; j++)
           g.arcs[i][j] = 0 ;

    for ( i= 1 ; i <= g.arcnum ; i++ )
    {
        int head , tail ;
        cin >> head >> tail ;
        g.arcs[head][tail] = 1 ;

        if ( g.kind == UDG ) // 无向图为对称阵
        {
             g.arcs[tail][head] = 1 ;
        }
    }
}

/**
 traverse.cpp
 邻接矩阵图和邻接表图的 深度优先搜索(遍历)
 邻接表图广度优先搜索(遍历)
 邻接表图的指定起点和终点的路径搜索
 (有路则向前探索,无路则回溯.即为迷宫问题)*/

#include "iostream"
#include "graph.h"
#include <queue>

using namespace std ;

bool VISITED[N]; //访问标志向量

/**访问标志数组全部初始化为“未访问” */
inline void InitVisited( )
{
    for(int i=0; i<N; i++)
        VISITED[i] = false;
}

/**从某顶点出发,深度优先搜索“邻接矩阵”存储的图
 *@g 邻接矩阵
 *@v 出发顶点编号 */
void DFS( MGraph g , int v )
{
    VISITED[v] = true ;
    cout << g.vexs[v] << "  " ;

    for ( int w = 1 ; w <= g.vexnum ; w++ )
    {
        if ( g.arcs[v][w] && !VISITED[w] )
            DFS( g , w ) ;
    }
}


/** 深度优先搜索遍历,"邻接矩阵”图
 * @g 邻接矩阵 */
void DFSTraverse( MGraph g )
{
    int v ;

    InitVisited();//标志数组初始化为false

    for ( v = 1 ; v <= g.vexnum ; v++)
        if ( !VISITED[v] ) DFS(g,v) ;
}


/************* 以下为邻接表图的操作**************

/**输出邻接表图中第v个顶点*/
inline void PrintNode(ALGraph g, int v)
{
    cout << g.vertices[v].data << " " ;
}


/**从某顶点出发,深度搜索”邻接表“存储的图
 * @g 邻接表
 * @v 出发顶点编号*/
void DFS( ALGraph g , int v )
{
    ArcNode * p ;

    VISITED[v] = true ;
    PrintNode(g,v) ;  //输出第v个顶点
    for ( p = g.vertices[v].firstarc ; p ; p = p->nextArc )
    {
        int w  = p->adjvex ;
        if ( !VISITED[w] )
            DFS( g , w ) ;
    }
}


/** 深度优先搜索遍历,"邻接表”表示的图
 * @g 邻接表*/
void DFSTraverse( ALGraph g )
{
    int v ;

    InitVisited();//标志数组初始化为false

    for ( v = 1 ; v <= g.vexnum ; v++)
        if ( !VISITED[v] )
            DFS(g,v);
}


/**BFS 广度优先遍历图 (需使用队列,这里使用STL的queue)
 *@g 邻接表图
 */
void BFSTraverse(ALGraph g)
{
    int v,w;
    queue<int> q;

    InitVisited();//标志数组初始化为false

    for(v=1; v<=g.vexnum; v++)
    {
        if( !VISITED[v])
        {
            VISITED[v] = true;
            PrintNode(g,v) ;  //输出第v个顶点
            q.push(v);
            while(q.size()!=0)
            {
                w = q.front();
                q.pop();
                for(ArcNode *p=g.vertices[w].firstarc; p; p=p->nextArc)
                {
                    w = p->adjvex;
                    if(!VISITED[w])
                    {
                        VISITED[w] = true;
                        PrintNode(g,w) ;  //输出第w个顶点
                        q.push(w);
                    }
                }//for
            }//while
        }
    }
}


int PATH[100] ;// 存储路径
/** 基于DFS,输出从v号到d号顶点的一条路径 (即为迷宫问题)
 * @g 邻接表存储的图
 * @v 起点编号
 * @d 终点编号
 * @len 从len开始存储,即起点距当前顶点的距离
 * @return 存在v到s路径true,否则false */
bool GetOnePath( ALGraph g, int s, int d, int len )
{
    ArcNode * p ;

    //到达终点,则输出路径并返回
    if ( d == s )
    {
        PATH[len] = s ;
        for (int i = 1 ; i <= len ; i++)
            PrintNode(g,PATH[i]) ;
        return true;
    }
    //访问(记入路径)并标记
    VISITED[s] = true ;
    PATH[len] = s ;

    for ( p = g.vertices[s].firstarc ; p ; p = p->nextArc )
    {
        // 从v的各个尚未访问的邻接点w出发 搜索d
        int nextNode  = p->adjvex ;
        if ( !VISITED[nextNode] )
            if( GetOnePath(g, nextNode, d, len+1) )
                return true ;
    }
    return false; //从起点s的各邻接点出发(各方向)均无路可达,则无路
}

/** 寻路径的包装函数*/
bool GetOnePath( ALGraph g, int s, int d )
{
     InitVisited();
     return GetOnePath(g,s,d,1);
}


0 8 9
A B C D E F G H
1 2
1 3
2 4
2 5
3 6
3 7
4 8
5 8
6 7



1 4  4
A B C D
1 2
1 3
3 4
4 1


    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/s2637281620/article/details/53468016
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞