ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

手撕leetcode547题-省份数量(DFS)

2021-01-07 20:02:28  阅读:501  来源: 互联网

标签:leetcode547 cout int visit ++ DFS mGraph 省份


今天刷到了leetcode的547题也就是每日一题,昨天的除法真的好难,连续两天每日一题出了图论的题着实让我意外,图论的题首先就想DFS,BFS或者并查集(虽然我不咋会)。这个题不例外。
图片1
图片2
应该是找连通分量的意思,特点是一个独立的点也算一个连通分量。比如例1:1与2是相联的,算一个连通分量,点3是单独的算一个连通分量所以连通分量数为2,例2三个点均没有交点所以连通分量为3。再举一个例子:
如图:
图三
只有一个连通分量所以最后得到的输出为1。分析到此就很明显了其实就是一个DFS解决。
题外话总结一下DFS和BFS,DFS相当于树的前序遍历可以用递归实现当然非递归形式可以用栈实现,BFS相当于树的层次遍历,需要用到队列。同样的老规矩来个例子:
图四
如果从节点1出发使用DFS遍历(序列不唯一),可以为1->2->4->3->5,如果使用BFS(序列不唯一),可以为1->2->3->4->5。
接下来来具体实现一下(存储结构使用临接矩阵,当然也可以用临接表)。
以下均使用C++实现
建立一个头文件(Graph_Define_Matrix.h)里面给出图的定义

//临接矩阵定义
#pragma once
#ifndef _GRAPH_CREATE_
#define _GRAPH_CREATE
//顶点
typedef char VertexType;
//边
typedef float EdgeType;
//最大边数
#define MAXVEX 100
//没有连线
#define INFINITY 65535
//临接矩阵
typedef struct {
    //顶点表
    VertexType vertex[MAXVEX];
    //边表
    EdgeType edge[MAXVEX][MAXVEX];
    //边的数量和顶点的数量
    int  numVertex;
    int numEdge;
}MGraph;
#endif // !_GRAPH_CREATE_

再强调一下这个65535指的是两点间没距离。
以下为建立有向图的代码
引入头文件

#include<iostream>
#include"Graph_Define_Matrix.h"
#include<queue>
using namespace std;

然后建图:

//有向图
MGraph CreateGraph_Direction() {
    //cout << "请输入您要建立的图的边数和顶点数:" << endl;
    MGraph mGraph;
    cout << "请输入您要建立的图的顶点数:" << endl;
    cin >> mGraph.numVertex;
    cout << "请输入您要建立的图的边数:" << endl;
    cin >> mGraph.numEdge;
    cout << "请输入顶点:" << endl;
    //char
    VertexType vertex;
    for (int i = 0;i < mGraph.numVertex;i++) {
        cin >> vertex;
        mGraph.vertex[i] = vertex;
    }

    //初始化边表
    for (int i = 0;i < mGraph.numVertex;i++) {
        for (int j = 0;j < mGraph.numVertex;j++) {
            if (i == j) {
                mGraph.edge[i][j] = 0;
            }
            else
            {
                mGraph.edge[i][j] = INFINITY;
            }
        }
    }
    //char
    int vertex1, vertex2;
    //边的权值
    EdgeType weight;
    //输入边
    for (int i = 0;i < mGraph.numEdge;i++) {
        cout << "输入两个顶点及其权值:" << endl;
        cin >> vertex1 >> vertex2 >> weight;
        mGraph.edge[vertex1][vertex2] = weight;
    }
    return mGraph;
}

建立我刚刚举例子的那个图,如果有距离距离就设置为1,当然权值可以用户自定,先可以自己画出临接矩阵进行验证:
在这里插入图片描述
为了验证正确性,我们再写一个打印函数,来正确结果

void ReadGraph(MGraph mGraph) {
    cout << "输出图:" << endl;
    for (int i = 0;i < mGraph.numVertex;i++) {
        for (int j = 0;j < mGraph.numVertex;j++) {
            cout << "点" << mGraph.vertex[i] << "->点" << mGraph.vertex[j] << "距离为:" << mGraph.edge[i][j]<<endl;
        }
    }
}

主函数运行
在这里插入图片描述
运行结果如下:
在这里插入图片描述
以下为遍历操作:
1.BFS(广度优先遍历)
借助队列例子从1出发(那两根横线为队列):
第一步:
在这里插入图片描述
第二步:
在这里插入图片描述
1出队,与1相连的2和3入队
第三步:
在这里插入图片描述
2出队,与2相连的4入队
第四步:
在这里插入图片描述
3出队与3相连的5入队
第五步:
最后4,5出队
得到序列为1 2 3 4 5
具体代码如下(visit数组很重要)

//广度优先遍历--从a出发
void BFS(MGraph mGraph) {
    //判断是否被访问过
    bool visit[MAXVEX];
    for (int i = 0;i < mGraph.numVertex;i++) {
      //均初始置为未访问
        visit[i] = false;
    }
    cout << "使用广度优先遍历遍历此图得到的点的顺序为:" << endl;
    //初始化一个队列——BFS依赖于队列
    queue<VertexType>line;
    for (int i = 0;i < mGraph.numVertex;i++) {
        //从未访问过
        if (visit[i]==false) {
            //置为真
            visit[i] =true;
            cout << mGraph.vertex[i] << "->";
            line.push(mGraph.vertex[i]);
            //当队列不为空时
            while (!line.empty())
            {
                //得到对头元素
                VertexType note = line.front();
                line.pop();
                //有顶点和此顶点相连
                for (int j = 0;j < mGraph.numVertex;j++) {
                    //表示之间有边还要注意这个节点要没访问过
                    /*
                    重要的事说三遍没访问过没访问过没访问过
                    */
                    if (mGraph.edge[i][j] != 0 && mGraph.edge[i][j] != 65535&&visit[j]==false) {
                      //访问此节点
                        visit[j] = true;
                        cout << mGraph.vertex[j] << "->";
                        //入队
                        line.push(mGraph.vertex[j]);
                    }
                }
            }
        }
    }
}

运行代码得到的结果为:
在这里插入图片描述
2.DFS(深度优先遍历)
废话不多说,直接上代码:

bool visit1[MAXVEX];
//深度优先递归,可控制从第几个顶点开始
void DFS(MGraph mGraph,int begin) {
    //判断数组
    //bool visit[MAXVEX];
    visit1[begin] = true;
    //访问相邻节点
    int next;
    cout << mGraph.vertex[begin] << "->";
    //访问相邻节点
    /*
    重要的事说三遍这个节点没有被访问过
    */
    for (next = 0;next < mGraph.numVertex;next++) {
        if (mGraph.edge[begin][next] != 0 && mGraph.edge[begin][next] != 65535&&visit1[next]==false) {
            DFS(mGraph, next);
        }
    }
}

有递归知识的理解这个代码应该不难,我们控制从第一个顶点开始遍历
在这里插入图片描述
运行结果如下:
在这里插入图片描述

说了这么多再回到题目,其实就是一个DFS的问题,直接解决:

void DFS(vector<vector<int>>& isConnected, vector<int>& visit, int i) {
        int Nums = isConnected.size();
        //vector<int>visit(Nums);
        for (int j = 0;j < Nums;j++) {
            if (isConnected[i][j] == 1 && !visit[j]) {
                //置为访问过
                visit[j] = 1;
                DFS(isConnected, visit, j);
            }
        }
    }
    //DFS
    int findCircleNum(vector<vector<int>>& isConnected) {
        int Num = isConnected.size();
        //Num个0
        vector<int>visit(Num);
        int count = 0;
        for (int i = 0;i < Num;i++) {
            if (!visit[i]) {
                DFS(isConnected, visit, i);
                count++;
            }
        }
        return count;
    }

这个题临接矩阵对角线元素为1,没有交点则为0。
以题中给的例子
在这里插入图片描述
主函数如下:
在这里插入图片描述
运行结果如下:
在这里插入图片描述
提交:
在这里插入图片描述
水平实在有限,希望大佬勿喷。
最后说明一下,我遇到的一个问题,在使用C++ STL库的vector时,当vector出现在函数的形参时一定要加&,比如
在这里插入图片描述
个人的理解是不加的话这个visit就是一个常量,再递归的时候每次调用DFS,这个visit数组是会变得而如果不加&就会使visit不变,得到的最后结果count就恒等于图的结点数。我也在这里纠结了很久。
以上只是个人观点,本人水平也有限,可能会有出错的地方,请大佬指正。

标签:leetcode547,cout,int,visit,++,DFS,mGraph,省份
来源: https://blog.csdn.net/weixin_44240981/article/details/112324332

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有