• 对图的广度优先遍历BFS和深度优先遍历DFS的应用——基于LeetCode133 克隆图


    对于图的广度优先遍历的基本形式

    这个基本大家都是了解的,基于队列,每一次出队列一个节点,把相关的没有进入队列的节点加入队列,循环执行操作即可实现对图的BFS了。但是如果BFS+其他知识点,可能就有些令人不好下手了。比如说这道克隆的题目(虽然python3 里面已经提供了真·深拷贝,节省了不少功夫,不过我们为了锻炼code能力,还是自己做一下比较好),对我个人来说,就加深了我对于内存空间和map的理解和熟练掌握的程度。

    对于图的深度优先遍历DFS的基本形式

    相较于BFS,DFS就更加的多样一些了,主要是实现形式的多样化,我们可以利用递归的方法来实现我们的目标(这个也是大多数DFS问题的解决方式),不过如果我们有特殊需求,不想系统给我们压栈的话,我们也可以自己搞一个栈出来,一样可以做到,不过这道题也没有什么要求,我图一个省事,就用的递归的形式来做,如果之后有需要自己设置堆栈的题目,我会特别单写一个博客的。

    题目内容

    给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

    图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。

    class Node {
    public int val;
    public List neighbors;
    }

    测试用例格式:

    简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。

    邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。

    给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。

    来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/clone-graph
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    测试样例

    输入:adjList = [[2,4],[1,3],[2,4],[1,3]]
    输出:[[2,4],[1,3],[2,4],[1,3]]
    解释:
    图中有 4 个节点。
    节点 1 的值是 1,它有两个邻居:节点 2 和 4 。
    节点 2 的值是 2,它有两个邻居:节点 1 和 3 。
    节点 3 的值是 3,它有两个邻居:节点 2 和 4 。
    节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
    ————————————————————————————
    输入:adjList = [[]]
    输出:[[]]
    解释:输入包含一个空列表。该图仅仅只有一个值为 1 的节点,它没有任何邻居。
    ————————————————————————————
    输入:adjList = []
    输出:[]
    解释:这个图是空的,它不含任何节点。
    ————————————————————————————
    输入:adjList = [[2],[1]]
    输出:[[2],[1]]

    解题思路

    这道题要做的其实还是很明确的,就是要我们遍历一遍这个图,然后把每一个点的内容都去copy一份,这里我使用的还是比较习惯用的BFS,但是在执行的过程中遇到了一些问题。
    代码的目的是比较清楚的,一个队列用来实现BFS,一个map是为了防止图中的环的情况导致一些节点一直被copy陷入循环。对于初始情况完成了入队列和新旧节点的设置之后,开始进入BFS的循环,其中只要是遇到了新的节点,就是生成新的,进入map,同时节点进队列,继续BFS。
    但是我遇到的一个主要的问题在于我希望可以所有地方都是用new NODE来生成新的,不过现在想一下,这样一来1-3边和2-3边同样是3号节点就会有多个不同的节点地址了,的确是有问题的。
    在使用BFS完成之后,我们可以再延伸一下,使用相对我不是那么熟练的DFS来完成一下,DFS的话相较于BFS,可以理解为一条路走到死之后才考虑回头,这样的方式的话,递归自然是最好的选择了,我们可以设定这个结点已经copy过,或者是走到头了,这个点没有neighbor了作为终点,而在补充邻居那里使用的就是邻居的clone函数,就可以实现递归了,虽然遍历图的手段不同,但是copy和map的核心内容还是一样的。

    BFS具体代码

    /*
    // Definition for a Node.
    class Node {
    public:
        int val;
        vector neighbors;
        Node() {
            val = 0;
            neighbors = vector();
        }
        Node(int _val) {
            val = _val;
            neighbors = vector();
        }
        Node(int _val, vector _neighbors) {
            val = _val;
            neighbors = _neighbors;
        }
    };
    */
    
    class Solution {
    public:
        Node* cloneGraph(Node* node) {
            if(node==NULL){
                return node;
            }
            queue<Node*> link;
            map<Node*,Node*> jihe;
            link.push(node);
            jihe.insert(pair<Node*,Node*>(node,new Node(node->val)));
            while(!link.empty()){
                Node* biao=link.front();
                link.pop();
                for(vector<Node*> ::iterator it=biao->neighbors.begin();it!=biao->neighbors.end();it++){
                    if(jihe.find(*it)==jihe.end()){
                        // jihe[*it]=new Node(*it->val);                
                        jihe.insert(pair<Node*,Node*>(*it,new Node((*it)->val)));
                        // jihe[biao]->neighbors.push_back(new Node((*it)->val));
                        link.push(*it);
                    }
                    // jihe[biao]->neighbors.push_back(new Node((*it)->val));
                    jihe[biao]->neighbors.push_back(jihe[*it]);
                }
            }
            return jihe[node];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    DFS的具体代码(看起来短一些,毕竟递归嘛)

    /*
    // Definition for a Node.
    class Node {
    public:
        int val;
        vector neighbors;
        Node() {
            val = 0;
            neighbors = vector();
        }
        Node(int _val) {
            val = _val;
            neighbors = vector();
        }
        Node(int _val, vector _neighbors) {
            val = _val;
            neighbors = _neighbors;
        }
    };
    */
    
    class Solution {
    public:
        map<Node*,Node*> jihe; 
        Node* cloneGraph(Node* node) {
            if(node==NULL){
                return node;
            }   
            if(jihe.find(node)!=jihe.end()){
                return jihe[node];
            } 
    
            jihe.insert(pair<Node*,Node*>(node,new Node(node->val)));   
    
            for(vector<Node*>:: iterator it=node->neighbors.begin();it!=node->neighbors.end();it++){
                jihe[node]->neighbors.push_back(cloneGraph(*it));
            }
    
            return jihe[node];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
  • 相关阅读:
    Redis分布式锁剖析和几种客户端的实现
    【C语言】文件的操作与文件函数的使用(详细讲解)
    Gerrit的用法及与gitlab的区别
    07 数据库查询(1) | OushuDB 数据库使用入门
    中国电信天翼云进入4.0阶段,打造一朵无处不在的分布式云
    16.springmvc工作原理分析
    玄子Share-引导过程与服务控制
    购买阿里云服务器需要多少钱?活动价3000元-5000元的阿里云服务器汇总
    计算机毕业设计Java便捷式管理系统(源码+系统+mysql数据库+lw文档)
    计算机毕业设计ssm基于SSM框架的宿舍管控平台6z76b系统+程序+源码+lw+远程部署
  • 原文地址:https://blog.csdn.net/weixin_51529433/article/details/125895723