<图>广度优先遍历matrix

文章介绍了图的两种遍历方法:广度优先搜索(BFS)和深度优先搜索(DFS),并以有向图为例,展示了邻接矩阵在广度优先遍历中的应用。BFS利用队列实现,DFS借助栈进行,同时提供了伪代码来说明这两种遍历的实现过程。
摘要由CSDN通过智能技术生成
图的遍历的两种方法
  广度优先(Breadth First Search)
    像水波一样一层一层由内到外扩散访问
    核心思想:先被访问的顶点,其邻接点也先被访问
    队列的思想:先进先出 notice: 「出队列的过程」 == 「广度优先遍历的过程」
  深度优先(DFS)
    一条路走到黑,如果走不通就返回一开始的位置走下一条路,
    如果走得通就走出去了,其他的路也不管了
    核心思想:后被访问的顶点,其第一个邻接点先被访问
    栈的思想:后进先出 notice: 「入栈的过程」 == 「深度优先遍历的过程」

有向图eg:
     b
   ↗   ↘
  a  →  c  5个顶点,7条边
  ↓  ↙  ↓
  e  ←  d
  Vex[] = a b c d e    a:0 b:1 c:2 d:3 e:4

                a b c d e 
 Egde[i][j] = a 0 1 1 0 1
              b 0 0 1 0 0
              c 0 0 0 1 1
              d 0 0 0 0 1
              e 0 0 0 0 0 

邻接矩阵的广度优先算法:
  1.初始化一个空队列[      ]
  2.顶点a入队列[a|      ],标记visited[0] = 1
  3.a出队列,找a的邻接点,且未被访问过的,发现有b、c、e, notice: 相当于走ab ac ae
  4.邻接点入队列[b|c|e    ],标记visited[1]、[2]、[4] = 1
  5.b出队列,找b的邻接点,且未被访问过的,发现无,剩余:[c|e    ]
  6.c出队列,找c的邻接点,且未被访问过的,发现有d
  7.邻接点d入队列:[e|d     ],标记visited[3] = 1
  8.e出队列,找e的邻接点,且未被访问过的,发现无,剩余:[d|     ]
  9.d出队列,找d的邻接点,且未被访问过的,发现无,剩余:[       ]

  综上:notice: 所有头指针指向的内容「出列队的过程」 == 「广度优先遍历的过程」
  真正入队列的时候,abcde入队列太麻烦,让其下标入队列
  判断某个顶点是否有邻接点是,只需判断矩阵某行某列[i][j]是否等于1

  伪代码
    1.创建一个数组用于表示顶点是否被访问过,visited[n],初始化为0,代表所有顶点未被访问
    2.创建空队列,用于存放顶点下标
    3.从图的起点(下标为0)出发,标记访问过,将顶点入队列
    4.判断如果队列是否为空,若不为空则继续访问,否则结束
    5.顶点(头部)出队列后,依次访问该顶点 [未被访问过的][所有邻接点],标记并入队列
    6.返回4

输入:
    ab ac ae bc cd ce de
输出:
    a b c e d
#include <iostream>
#include "directed_mat.h"
using namespace std;

int main()
{
    // 无向图的改为un_graph即可
	struct AMG_Graph* d_graph;

	d_graph = Create_AMG_Graph();

    Show_AMG_Graph(d_graph);

    cout << "使用广度优先遍历这张图:" << endl;
    BFS_AMG(d_graph);

    return 0;
}

directed_mat.cpp




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

using namespace std;

struct AMG_Graph* Create_AMG_Graph()
{
	int i, j;
    char u, v;
	struct AMG_Graph* graph;

	// 申请内存空间,结构体多大申请多大,强制类型转换
	graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));

	cout << "请输入顶点的个数: ";
	cin >> graph->vex_num;

	cout << "请输入边的个数: ";
	cin >> graph->edge_num;

	cout << "请输入顶点信息: " << endl;
	for(i = 0; i < graph->vex_num; i++)
	{
		// getchar会捕获回车
		cin >> graph->Vex[i];

	}

    for(i = 0; i < graph->vex_num; i++)
    {
        for(j = 0; j < graph->vex_num; j++)
        {
            // 初始化为0
            graph->Edge[i][j] = 0;
        }
    }

    while(graph->edge_num--)
    {
        cout << "请输入通过边连接起来的顶点:" << endl;
        cin >> u;
        cin >> v;
        // 到graph中找到字符u,所对应的索引
        i = search_vex(graph, u);
        j = search_vex(graph, v);
        
        if(i != -1 && j != -1)
            // 有向图:
            graph->Edge[i][j]  = 1;
            // 无向图:
            //graph->Edge[i][j] = graph->Edge[j][i] = 1;
        else
        {
            cout << "你输入的顶点信息是错的,请再次输入" << endl;
            graph->edge_num++;
        }
    }
	return graph;

}

void Show_AMG_Graph(struct AMG_Graph * graph)
{
    int i,j;
    cout << "显示顶点信息:"<< endl;
    for(i = 0; i < graph->vex_num; i++)
        cout << graph->Vex[i] << "\t";
    cout << endl;

    cout << "显示邻接矩阵:" << endl;
    for(i = 0; i < graph->vex_num; i++)
    {
        for(j = 0; j < graph->vex_num; j++)
        {
           cout <<  graph->Edge[i][j] << "\t";
        }
        cout << endl;
    }

}


int search_vex(struct AMG_Graph* graph, char c)
{
    int i;
    for(i = 0; i < graph->vex_num; i++)
    {
        if(c == graph->Vex[i])
            return i;
    }
    return -1;
}

// 广度优先遍历邻接矩阵
void BFS_AMG(struct AMG_Graph* graph)
{
    // 出队列的下标
    int u;

    // step1 创建一个数组用于表示顶点是否被访问过
    int visited[MAX] = {0};

    // step3 从图的起点(下标为0)出发,标记访问过,将顶点(下标)入队列
    visited[0] = 1;
    inqueue(0);

    // step4 判断如果队列是否为空,若不为空则继续访问,否则结束 o(n²)
    while(!isempty())
    {
        // step5 顶点(头部)出队列后,依次访问该顶点[未被访问过的][所有邻接点],标记并入队列
        u = outqueue();

        // notice: 出队列的过程 == 广度优先遍历的过程
        cout << graph->Vex[u] << " ";

        // 遍历当前出队列节点所在的二维矩阵的行
        for(int i = 0; i < graph->vex_num; i++)
        {
            // notice: ①如果有邻接点 并且 ②没有被标记
            if( (graph->Edge[u][i]==1) && (visited[i] == 0) )
            {
                // 标记为访问过,防止节点重复添加到队列中
                visited[i] = 1;
                // 邻接点下标入队列
                inqueue(i);
            }
        }
    }
    cout << endl;
}

directed_mat.h

#ifndef __directed_mat_h__
#define __directed_mat_h__


#define MAX 100

// 图
struct AMG_Graph
{
	// 顶点的个数,边的个数
	int vex_num, edge_num;
	// 储存顶点的信息,一维顶点数组
	char Vex[MAX];
	// 储存顶点和顶点之间的邻接关系,二维邻接矩阵
	int Edge[MAX][MAX];
};


struct AMG_Graph* Create_AMG_Graph(void);
void Show_AMG_Graph(struct AMG_Graph * graph);
int search_vex(struct AMG_Graph* graph, char c);
int search_vex(struct AMG_Graph* graph, char c);
void BFS_AMG(struct AMG_Graph* graph);




#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值