图的基本操作(基于邻接矩阵):图的构造,深搜(DFS),广搜(BFS)

Adjacency Matrix

邻接矩阵是表示一个图的常用存储表示。它用两个数组分别存储数据元素(顶点)的信息和数据元素之间的关系(边或弧)的信息。阶为n的图G的邻接矩阵A是n*n的。将G的顶点标签为v_1,v_2,...,v_n。若(v_i,v_j)
\in E(G),A_{ij}=1,否则A_{ij}=0。

Depth-First-Search

是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。

搜索结果:1 2 3 4 5 6 7 8 9 10 11 12

Breadth-First-Search

简称BFS,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。

搜索结果:1 2 3 4 5 6 7 8 9 10 11 12

Implementation

#include <iostream>
#include <string>
#include <queue>
using namespace std;  

#define MAXN 100  

struct Graph
{
    string vertex[MAXN];
    int matrix[MAXN][MAXN];
    int vertexNum;
    int arcNum;
};  

int Locate(Graph g,string str)
{
    for(int i =0;i<g.vertexNum;i++)
    {
        if(str == g.vertex[i])
            return i;
    }
    return -1;
}  

void CreateDUG(Graph &g) //构造无向图
{
    string start,end;
    cout << "请输入顶点和边数:"<<endl;
    cin>>g.vertexNum>>g.arcNum;  

    for(int i = 0;i<g.vertexNum;i++)
    {
        cout<<"请输入第"<<i<<"个顶点:"<<endl;
        cin>>g.vertex[i];
    }  

    for(int i = 0;i<g.vertexNum;i++)
    {
        for(int j = 0;j<g.vertexNum;j++)
        {
            g.matrix[i][j] = 0;
        }
    }  

    for(int i = 0;i <g.arcNum;i++)
    {
        cout<<"请输入第"<<i<<"条边的起始和结束顶点"<<endl;
        cin>>start>>end;  

        int m = Locate(g,start);
        int n = Locate(g,end);  

        g.matrix[m][n] = 1;
        g.matrix[n][m] = 1;
    }
}  

void CreateUDN(Graph &g) //构造无网
{
    string start,end;
    int w;
    cout << "请输入顶点和边数:"<<endl;
    cin>>g.vertexNum>>g.arcNum;  

    for(int i = 0;i<g.vertexNum;i++)
    {
        cout<<"请输入第"<<i<<"个顶点:"<<endl;
        cin>>g.vertex[i];
    }  

    for(int i = 0;i<g.vertexNum;i++)
    {
        for(int j = 0;j<g.vertexNum;j++)
        {
            g.matrix[i][j] = 0;
        }
    }  

    for(int i = 0;i <g.arcNum;i++)
    {
        cout<<"请输入第"<<i<<"条边的起始和结束顶点和权"<<endl;
        cin>>start>>end>>w;  

        int m = Locate(g,start);
        int n = Locate(g,end);  

        g.matrix[m][n] = w;
        g.matrix[n][m] = w;
    }
}  

void CreateDG(Graph &g) //构造有向图
{
    string start,end;
    cout << "请输入顶点和边数:"<<endl;
    cin>>g.vertexNum>>g.arcNum;  

    for(int i = 0;i<g.vertexNum;i++)
    {
        cout<<"请输入第"<<i<<"个顶点:"<<endl;
        cin>>g.vertex[i];
    }  

    for(int i = 0;i<g.vertexNum;i++)
    {
        for(int j = 0;j<g.vertexNum;j++)
        {
            g.matrix[i][j] = 0;
        }
    }  

    for(int i = 0;i <g.arcNum;i++)
    {
        cout<<"请输入第"<<i<<"条边的起始和结束顶点"<<endl;
        cin>>start>>end;  

        int m = Locate(g,start);
        int n = Locate(g,end);  

        g.matrix[m][n] = 1;
    }
}  

void CreateDN(Graph &g) //构造有向网
{
    string start,end;
    int w;
    cout << "请输入顶点和边数:"<<endl;
    cin>>g.vertexNum>>g.arcNum;  

    for(int i = 0;i<g.vertexNum;i++)
    {
        cout<<"请输入第"<<i<<"个顶点:"<<endl;
        cin>>g.vertex[i];
    }  

    for(int i = 0;i<g.vertexNum;i++)
    {
        for(int j = 0;j<g.vertexNum;j++)
        {
            g.matrix[i][j] = 0;
        }
    }  

    for(int i = 0;i <g.arcNum;i++)
    {
        cout<<"请输入第"<<i<<"条边的起始和结束顶点和权"<<endl;
        cin>>start>>end>>w;  

        int m = Locate(g,start);
        int n = Locate(g,end);  

        g.matrix[m][n] = w;
    }
}  

int FirstAdjVex(Graph g,int v)//返回v的第一个邻接顶点序号
{
    for(int i = 0;i<g.vertexNum;i++)
    {
        if(g.matrix[v][i] == 1)
            return i;
    }
    return -1;
}  

int NextAdjVex(Graph g,int v,int w)//返回顶点v相对于w的下一个邻接点序号
{
    for(int i = w+1;i<g.vertexNum;i++)
    {
        if(g.matrix[v][i] == 1)
            return i;
    }
    return -1;
}  

bool visted[MAXN];  

void DFS(Graph g,int i)
{
    cout <<g.vertex[i]<<" ";
    visted[i] = true;
    for(int w = FirstAdjVex(g,i);w>=0;w = NextAdjVex(g,i,w))
    {
        if(!visted[i])
            DFS(g,w);
    }
}  

void DFSTransfer(Graph g)
{
    for(int i =0;i<g.vertexNum;i++)
    {
        visted[i] = false;
    }  

    for(int i = 0;i<g.vertexNum;i++)
    {
        if(!visted[i])
            DFS(g,i);
    }
    cout << endl;
}  

void BFS(Graph g,int v)
{  

}  

void BFSTransfer(Graph g)
{
    for(int i =0;i<g.vertexNum;i++)
    {
        visted[i] = false;
    }  

    std::queue<int> que;
    for(int i = 0;i<g.vertexNum;i++)
    {
        if(!visted[i])
        {
            que.push(i);
            visted[i] = true;
            while(!que.empty())
            {
                int k = que.front();
                que.pop();
                cout <<g.vertex[k]<<" ";
                for(int i = FirstAdjVex(g,k);i>=0;i = NextAdjVex(g,k,i))
                {
                    if(!visted[i])
                    {
                        que.push(i);
                        visted[i] = true;
                    }
                }
            }
        }
    }
    cout <<endl;  

}  

int main()
{
    Graph g;
    CreateDUG(g);
    DFSTransfer(g);
    BFSTransfer(g);
    return 0;
}  

Reference

  1. 《算法导论》 第22章 图的基本算法P322
  2. http://en.wikipedia.org/wiki/Breadth-first_search
  3. http://en.wikipedia.org/wiki/Depth-first_search
时间: 2024-10-08 01:23:19

图的基本操作(基于邻接矩阵):图的构造,深搜(DFS),广搜(BFS)的相关文章

15 图-图的遍历-基于邻接矩阵实现的BFS与DFS算法

算法分析和具体步骤解说直接写在代码注释上了 TvT 没时间了等下还要去洗衣服 就先不赘述了 有不明白的欢迎留言交流!(估计是没人看的了) 直接上代码: 1 #include<stdio.h> 2 #include<queue> 3 #include<iostream> 4 using namespace std; 5 typedef struct{ 6 int Vex[10];//顶点表 7 int Edge[10][10]; 8 int vexnum,arcnum;

看数据结构写代码(39) 图的遍历(深搜和广搜)

图的遍历算法 有两种 :深度优先搜索遍历 和 广度 优先搜索遍历.深度优先搜索遍历类似与 树的 先序遍历.广度优先搜索遍历类似与树的层序遍历.只不过 图 可以有 不连通的 节点,所以 得 遍历 整个顶点数组. 深搜遍历 总是 先访问当前节点的邻接点,而 广搜算法 是 先访问顶点的邻接点 要 先于 后访问顶点的邻接点 被 访问. 具体遍历顺序如下: 以下代码 以 图的 邻接多重表 为 基本结构进行 遍历. 首先更改 上节 的 查找 邻接点 和 下一个邻接点的 返回值,以及 邻接点的 代码 有误,少

算法-图是否为树(并查集或深搜)

今天做了一道很有意思的一道题,这道题虽然难度只是中等,但是里面涉及到的东西却是不少.其中,我在里面学习到了并查集这个东西,虽然不是很深刻,至少有一个印象:还有深搜,一直以来,深搜和广搜都是我的弱项,本文的理解是基于别人的博客:lintcode178. graph valid tree 图是否是树.我们来看看题 题意: 给出 n 个节点,标号分别从 0 到 n - 1 并且给出一个 无向 边的列表 (给出每 条边的两个顶点), 写一个函数去判断这张`无向`图是否是一棵树 样例: 给出n = 5 并

算法学习笔记 二叉树和图遍历—深搜 DFS 与广搜 BFS

图的深搜与广搜 马上又要秋招了,赶紧复习下基础知识.这里复习下二叉树.图的深搜与广搜.从图的遍历说起,图的遍历方法有两种:深度优先遍历(Depth First Search), 广度优先遍历(Breadth First Search),其经典应用走迷宫.N皇后.二叉树遍历等.遍历即按某种顺序访问"图"中所有的节点,顺序分为: 深度优先(优先往深处走),用的数据结构是栈, 主要是递归实现: 广度优先(优先走最近的),用的数据结构是队列,主要是迭代实现: 对于深搜,由于递归往往可以方便的利

算法学习笔记(六) 二叉树和图遍历—深搜 DFS 与广搜 BFS

图的深搜与广搜 复习下二叉树.图的深搜与广搜. 从图的遍历说起.图的遍历方法有两种:深度优先遍历(Depth First Search), 广度优先遍历(Breadth First Search),其经典应用走迷宫.N皇后.二叉树遍历等.遍历即按某种顺序訪问"图"中全部的节点,顺序分为: 深度优先(优先往深处走),用的数据结构是栈, 主要是递归实现. 广度优先(优先走近期的).用的数据结构是队列.主要是迭代实现. 对于深搜.因为递归往往能够方便的利用系统栈,不须要自己维护栈.所以通常实

图的存储形式——邻接矩阵(数组)

邻接矩阵:用两个数组分别存储数据元素(顶点)的信息和数据元素之间的关系(边或弧)的信息. 比如考虑下面这个有向图: 如果用邻接矩阵存储可以表示为: 1.顶点数组: 2.邻接矩阵: 图的遍历: 深度优先(DFS): 深度优先搜索遍历类似于树的先根遍历,是树的先根遍历的推广.假设初始状态是图中所有顶点未曾访问过,则深度优先搜索可从图中的某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到:若此时图中还有顶点未访问,则另选图中未访问的

每日一题28:图的基本操作

本文记录了基于邻接表表示的有向有权图的基本操作.邻接表表示的图的结构就是用一个散列表存储图的节点,而每个节点后面跟着从节点出发的所有边的集合,这些边用链表连接起来,所以在这样的图中寻找一个节点发出的边是容易的,但是寻找进入一个节点的边是困难的,需要遍历所有的边.删除一条边也比较容易,删除一个节点则需要寻找与该节点相关的所有边,并将这些边也删除. #ifndef _NOWEIGHTGRAPH_H_ #define _NOWEIGHTGRAPH_H_ #include "../include/Vec

数据结构 【实验9 图的基本操作】

实验9  图的基本操作 实验目的 1.  掌握图的各种存储结构,特别要熟练掌握邻接矩阵和邻接表存储结构. 2.遍历是图各种应用的算法的基础,要熟练掌握图的深度优先遍历和广度优先遍历算法,复习栈和队列的应用. 实验内容 程序1 /* 定义邻接矩阵类型 */ typedef int  adjmatrix[n+1][n+1]; /* 建立图的邻接矩阵 */ void CreatMatrix(adjmatrix GA) /* 从初始点v出发深度优先遍历邻接矩阵GA表示的图 */ void DfsMatr

图的割点(邻接矩阵实现)

/* Name: 图的割点(邻接矩阵) Copyright: Author: 巧若拙 Date: 21-11-14 20:34 Description: 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合. 求割点与桥的算法是R.Tarjan发明的.对图深度优先搜索,定义DFS(u)为u在搜索树(以下简称为树)中被遍历到的次序号(等价于时间戳). 定义Low(u)为u或u的子树中能通过非父子边追溯到的最早的节

数据结构之---C语言实现图的数组(邻接矩阵)存储表示

//图的数组(邻接矩阵)存储表示 #include <stdio.h> #include <stdlib.h> #define MAX_VEX_NUM 50 typedef char VertexType; typedef enum { DG, UDG } GraphType; typedef struct { VertexType vexs[MAX_VEX_NUM]; int arcs[MAX_VEX_NUM][MAX_VEX_NUM]; int vexnum, arcnum;