图的遍历与输出 (邻接矩阵和邻接表)_输出给定图的邻接矩阵和邻接表。-程序员宅基地

技术标签: 遍历  数据结构与算法    数据结构  

#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



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/S2637281620/article/details/53468016

智能推荐

JAVA文本域组件_public js(){setbounds(100,100,400,400);-程序员宅基地

文章浏览阅读1.1k次。文本域(JTextArea)这一组件,在程序中接受用户的多行文字输入。Swing中任何一个文本区域都是JTextArea类型的对象。JTextArea常用的构造方法如下:1. public JTextArea().2. public JTextArea(String text).3. public JTextArea(int rows,int columns).4. public J..._public js(){setbounds(100,100,400,400);

基因表达式编程gep_最具潜力的编程语言GO有新书啦-程序员宅基地

文章浏览阅读261次。互联网时代的来临,改变甚至颠覆了很多东西。从前,一台主机就能搞定一切;而在互联网时代,后台由大量分布式系统构成,任何单个后台服务器节点的故障都不会影响整个系统的正常运行。以七牛云、阿里云和腾讯云为代表的云厂商的出现和崛起,标志着云时代的到来。在云时代,掌握分布式编程已经成为软件工程师的基本技能,而基于Go语言构建的Docker、Kubernetes等系统正是将云时代推向顶峰的关键力量。今天,Go语..._gepgo

android:layout_above="@id/xxx"  --将控件置于给定ID控件之上android:layout_below="@id/xxx"  -_android layout 在之上-程序员宅基地

文章浏览阅读2.3k次。Android中RelativeLayout各个属性 android:layout_above="@id/xxx" --将控件置于给定ID控件之上android:layout_below="@id/xxx" --将控件置于给定ID控件之下android:layout_toLeftOf="@id/xxx" --将控件的右边缘和给定ID控件的左边缘对齐andr_android layout 在之上

C++语法篇之 Templates 模板_c++ templates-程序员宅基地

文章浏览阅读1.5k次。假如我们需要设计X和Y两个列表,这两个列表具有相似的代码唯一的不同是数据类型,则在C++中实现有如下的选择:共同的基类:在大多数场景并不适用,只是为了一个列表去提炼基类也没必要。 克隆代码:分别对X 和 Y 类型定义各自的列表,能够保证类型安全但是后期维护成本高。 空列表:定义一个没有类型的列表 (void(*))。缺点是类型不安全。除此之外,我们还可以用Template来实现,Template 既能保证重用代码,还能保证类型安全。那我们就来看看Template是如何施展魔法的。Templa._c++ templates

用SublimeText3开发微信小程序时,如何让代码高亮显示_sumlime text 微信小程序代码高亮-程序员宅基地

文章浏览阅读497次。打开.wxml文件的时候,选择右下角的“Open all with current extension as…”,然后再从弹出的列表中选择“HTML”打开.wxss文件的时候,选择右下角的“Open all with current extension as…”,然后再从弹出的列表中选择“css”..._sumlime text 微信小程序代码高亮

php7链接mysql8报错SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)_运行php项目sqlstate[hy000] [1045] access denied for us-程序员宅基地

文章浏览阅读7.1k次。使用环境:windows 7 下wampserver 3.2.0-64bitmysql版本8.0.18 端口号:3308php版本7.3.12测试的源码:<?php$servername = "localhost";$username = "root";$password = "root"; try { $conn = new PDO("mysql:host=..._运行php项目sqlstate[hy000] [1045] access denied for user ''@'localhost' (usi

随便推点

联网后只能登录QQ浏览器不能联网-程序员宅基地

文章浏览阅读382次,点赞9次,收藏5次。可以百度查一下,如广州DNS地址,填入,即可上网。更改DNS服务器地址,

用Maven构建Hadoop项目-程序员宅基地

文章浏览阅读444次。主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeeper, Avro, Ambari, Chukwa,新增加的项目包括,YARN, Hcatalog, Oozie, Cassandra, Hama, Whirr, Flume, Bigtop, Crunch, Hue等。从2011年开始,中国进入大数据风起云

Python中遍历同类型文件的方法!-程序员宅基地

文章浏览阅读133次。在Python中,想要遍历同类型的文件可使用的方法有很多,比如:使用OS模块、使用glob模块、使用pathlib模块等,接下来是具体方法介绍。可以使用os模块中的listdir方法获取文件夹下所有的文件和子文件夹。然后通过遍历获取到的文件和文件夹列表,筛选出符合条件的文件。glob模块可以根据指定的通配符搜索匹配的文件路径,这样可以更方便地获取指定类型的文件路径。Pathlib模块可以方便地进行文件路径的操作,包括遍历、过滤和获取文件类型等。3、使用Pathlib模块。2、使用glob模块。

android5.0以上实现录屏功能,并将录屏内容在相册中显示!(unity调用android方法)-程序员宅基地

文章浏览阅读5.6k次。package com.Xreal.TJYH;import android.Manifest;import android.content.ContentValues;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import

WebPack-Loader-程序员宅基地

文章浏览阅读81次。WebPack-Loader Loaders鼎鼎大名的Loaders登场了!1、什么是loaders  Loaders是webpack中最让人激动人心的功能之一了。通过使用不同的loader,webpack通过调用外部的脚本或工具可以对各种各样的格式的文件进行处理,  比如说分析JSON文件并把它转换为JavaScript文件,或者..._webpack_loader怎么装

个性化推荐中的多目标优化:业务与技术平衡-程序员宅基地

文章浏览阅读692次,点赞17次,收藏6次。1.背景介绍个性化推荐系统是现代互联网企业的核心业务之一,它通过分析用户行为、内容特征等多种信息,为每个用户推荐最合适的内容。在实际应用中,个性化推荐系统需要在满足用户需求的同时,也要考虑到业务需求,例如提高用户活跃度、增加用户 stickiness 等。因此,个性化推荐系统中的优化目标往往是多目标的,需要在多个目标之间进行权衡。在这篇文章中,我们将从以下几个方面进行深入探讨:背景介...

推荐文章

热门文章

相关标签