图论11-欧拉回路与欧拉路径+Hierholzer算法实现

文章目录

  • 1 欧拉回路的概念
  • 2 欧拉回路的算法实现
  • 3 Hierholzer算法详解
  • 4 Hierholzer算法实现
    • 4.1 修改Graph,增加API
    • 4.2 Graph.java
    • 4.3 联通分量类
    • 4.4 欧拉回路类

1 欧拉回路的概念

在这里插入图片描述

在这里插入图片描述

2 欧拉回路的算法实现

private boolean hasEulerLoop(){

    CC cc = new CC(G);
    if(cc.count() > 1) return false;

    for(int v = 0; v < G.V(); v ++)
        if(G.degree(v) % 2 == 1) return false;
    return true;
}

3 Hierholzer算法详解

在这里插入图片描述

public ArrayList<Integer> result(){

    ArrayList<Integer> res = new ArrayList<>();
    if(!hasEulerLoop()) return res;
    
    //根据小g进行删边
    Graph g = (Graph)G.clone();

    Stack<Integer> stack = new Stack<>();
    int curv = 0; //出发点
    stack.push(curv);
    while(!stack.isEmpty()){
        if(g.degree(curv) != 0){
            stack.push(curv);
            int w = g.adj(curv).iterator().next();
            g.removeEdge(curv, w);
            curv = w;
        }
        else{
            res.add(curv);
            curv = stack.pop();
        }
    }
    return res;
}

4 Hierholzer算法实现

4.1 修改Graph,增加API

//移除边
public void removeEdge(int v, int w){
    validateVertex(v);
    validateVertex(w);
    if(adj[v].contains(w)) E --;
    adj[v].remove(w);
    adj[w].remove(v);
}

//深拷贝
@Override
public Object clone(){

    try{
        Graph cloned = (Graph) super.clone();
        cloned.adj = new TreeSet[V];
        for(int v = 0; v < V; v ++){
            cloned.adj[v] = new TreeSet<Integer>();
            for(int w: adj[v])
                cloned.adj[v].add(w);
        }
        return cloned;
    }
    catch (CloneNotSupportedException e){
        e.printStackTrace();
    }
    return null;
}

4.2 Graph.java

package Chapter08_EulerLoop_And_EulerPath;

import java.io.File;
import java.io.IOException;
import java.util.TreeSet;
import java.util.Scanner;


/// 暂时只支持无向无权图
public class Graph implements Cloneable{

    private int V;
    private int E;
    private TreeSet<Integer>[] adj;

    public Graph(String filename){

        File file = new File(filename);

        try(Scanner scanner = new Scanner(file)){

            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new TreeSet[V];
            for(int i = 0; i < V; i ++)
                adj[i] = new TreeSet<Integer>();

            E = scanner.nextInt();
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            for(int i = 0; i < E; i ++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
                if(adj[a].contains(b)) throw new IllegalArgumentException("Parallel Edges are Detected!");

                adj[a].add(b);
                adj[b].add(a);
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    public void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].contains(w);
    }

    public Iterable<Integer> adj(int v){
        validateVertex(v);
        return adj[v];
    }

    public int degree(int v){
        validateVertex(v);
        return adj[v].size();
    }

    public void removeEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        if(adj[v].contains(w)) E --;
        adj[v].remove(w);
        adj[w].remove(v);
    }

    @Override
    public Object clone(){

        try{
            Graph cloned = (Graph) super.clone();
            cloned.adj = new TreeSet[V];
            for(int v = 0; v < V; v ++){
                cloned.adj[v] = new TreeSet<Integer>();
                for(int w: adj[v])
                    cloned.adj[v].add(w);
            }
            return cloned;
        }
        catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();

        sb.append(String.format("V = %d, E = %d\n", V, E));
        for(int v = 0; v < V; v ++){
            sb.append(String.format("%d : ", v));
            for(int w : adj[v])
                sb.append(String.format("%d ", w));
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){

        Graph g = new Graph("g.txt");
        System.out.print(g);
    }
}

4.3 联通分量类

package Chapter08_EulerLoop_And_EulerPath;

import java.util.ArrayList;

public class CC {

    private Graph G;
    private int[] visited;
    private int cccount = 0;

    public CC(Graph G){

        this.G = G;
        visited = new int[G.V()];
        for(int i = 0; i < visited.length; i ++)
            visited[i] = -1;

        for(int v = 0; v < G.V(); v ++)
            if(visited[v] == -1){
                dfs(v, cccount);
                cccount ++;
            }
    }

    private void dfs(int v, int ccid){

        visited[v] = ccid;
        for(int w: G.adj(v))
            if(visited[w] == -1)
                dfs(w, ccid);
    }

    public int count(){
        return cccount;
    }

    public boolean isConnected(int v, int w){
        G.validateVertex(v);
        G.validateVertex(w);
        return visited[v] == visited[w];
    }

    public ArrayList<Integer>[] components(){

        ArrayList<Integer>[] res = new ArrayList[cccount];
        for(int i = 0; i < cccount; i ++)
            res[i] = new ArrayList<Integer>();

        for(int v = 0; v < G.V(); v ++)
            res[visited[v]].add(v);
        return res;
    }

    public static void main(String[] args){

        Graph g = new Graph("g.txt");
        CC cc = new CC(g);
        System.out.println(cc.count());

        System.out.println(cc.isConnected(0, 6));
        System.out.println(cc.isConnected(5, 6));

        ArrayList<Integer>[] comp = cc.components();
        for(int ccid = 0; ccid < comp.length; ccid ++){
            System.out.print(ccid + " : ");
            for(int w: comp[ccid])
                System.out.print(w + " ");
            System.out.println();
        }
    }
}

4.4 欧拉回路类

package Chapter08_EulerLoop_And_EulerPath;

import java.util.ArrayList;
import java.util.Stack;

public class EulerLoop {

    private Graph G;

    public EulerLoop(Graph G){
        this.G = G;
    }

    private boolean hasEulerLoop(){

        CC cc = new CC(G);
        if(cc.count() > 1) return false;

        for(int v = 0; v < G.V(); v ++)
            if(G.degree(v) % 2 == 1) return false;
        return true;
    }

    public ArrayList<Integer> result(){

        ArrayList<Integer> res = new ArrayList<>();
        if(!hasEulerLoop()) return res;

        Graph g = (Graph)G.clone();

        Stack<Integer> stack = new Stack<>();
        int curv = 0;
        stack.push(curv);
        while(!stack.isEmpty()){
            if(g.degree(curv) != 0){
                stack.push(curv);
                int w = g.adj(curv).iterator().next();
                g.removeEdge(curv, w);
                curv = w;
            }
            else{
                res.add(curv);
                curv = stack.pop();
            }
        }
        return res;
    }

    public static void main(String[] args){

        Graph g = new Graph("g8.txt");
        EulerLoop el = new EulerLoop(g);
        System.out.println(el.result());

        Graph g2 = new Graph("g2.txt");
        EulerLoop el2 = new EulerLoop(g2);
        System.out.println(el2.result());
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/133046.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring】c命名和p命名空间注入

p命名空间注入 导入p名称空间 xmlns:p"http://www.springframework.org/schema/p"直接输入p就会有相关的属性弹出 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xml…

免费博客搭建笔记

title: 免费博客搭建笔记 tags: 博客搭建 本次是对自己在网上学习github搭建一个 &#x1f447;个人免费静态网站的总结当然不是很完美&#x1f447; Bow to the new king iYANG (yangsongl1n.github.io) 接着我会从我的写笔记的个人习惯来逐步介绍如何搭建这个网站 1.写笔…

函数的连续性

函数在某一点极限存在&#xff0c;不一定连续 函数的左极限 函数的右极限 函数在某点连续需要满足三个条件 1、左右极限存在 2、左右极限相等 3、函数在该点的极限值等于在该点的函数值 满足1、2两个条件函数在该点极限存在。

计算机网络期末复习-Part4

1、UDP和TCP的比较 TCP提供可靠传输&#xff1b;UDP提供不可靠传输。TCP有连接&#xff1b;UDP无连接&#xff08;减小时延&#xff09;。TCP提供流量控制&#xff1b;UDP不提供流量控制。TCP提供拥塞控制&#xff1b;UDP不提供拥塞控制&#xff08;传输快&#xff09;。TCP提…

【蓝桥杯软件赛 零基础备赛20周】第3周——填空题

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 文章目录 00. 2023年第14届参赛数据0. 上一周答疑1. 填空…

Practice01-Qt6.0设置文本颜色、格式等。

Qt6.0学习&#xff0c;在此做个记录&#xff0c;方便日后查找复习 本次项目用到的控件有&#xff1a;复选框&#xff0c;单选按钮。文本编辑框。 项目目录结构&#xff1a; 项目运行效果图&#xff1a; 实现的功能&#xff1a; 勾选Underline、Italic&#xff0c;Bold时&…

Git 进阶使用

一. Git图形化操作 1.1.什么是图形化管理工具 图形化管理工具是一种通过可视化界面来操作计算机系统或应用程序的软件工具。在软件开发中&#xff0c;它通常用于管理和操作版本控制系统&#xff08;如Git、SVN等&#xff09;以及代码开发环境&#xff08;如IDE&#xff09;。与…

Ruoyi框架开发项目(宝藏干货)

若依勾选框导出数据 效果图&#xff1a; package com.ruoyi.web.controller.school;import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.pag…

木板上的蚂蚁(c++题解)

题目描述 有一块木板&#xff0c;长度为 n 个 单位 。一些蚂蚁在木板上移动&#xff0c;每只蚂蚁都以 每秒一个单位 的速度移动。其中&#xff0c;一部分蚂蚁向 左 移动&#xff0c;其他蚂蚁向 右 移动。 当两只向 不同 方向移动的蚂蚁在某个点相遇时&#xff0c;它们会同时改…

【数据结构】深度剖析ArrayList

目录 ArrayLIst介绍 ArrayList实现的接口有哪些&#xff1f; ArrayList的序列化&#xff1a;实现Serializable接口 serialVersionUID 有什么用? 为什么一定要实现Serialzable才能被序列化&#xff1f; transient关键字 为什么ArrayList中的elementData会被transient修…

酷柚易汛ERP - 计量单位操作指南

1、应用场景 计量单位支持单单位和多单位管理&#xff0c;单位是开单时确定商品价格的主要计量维度。 2、主要操作 2.1 新增多单位 打开【资料】-【计量单位】点击新增 录入基本单位和副单位 ① 基本单位&#xff1a;最小单位 ② 副单位&#xff1a;多单位里的大单位 ③ …

【神经网络】GAN:生成对抗网络

GAN&#xff1a;生成对抗网络 Generator&#xff08;生成器&#xff09;概念 和传统的神经网络不同&#xff0c;Generator除了接受x的输入之外&#xff0c;还会接受一个简单的分布作为z进行输入&#xff0c;从而使得网络的输出也是一个复杂的分布 为什么输出需要时一个分布呢…

【华为HCIP | 华为数通工程师】IPV4与IPV6 高频题(1)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

jQuery实现二级菜单

jQuery怎么实现二级菜单呢&#xff1f;让我为大家演示一个例子&#xff01; 上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title><style>* {margin: 0;padding: …

耗时3年写了一本数据结构与算法pdf!开源了

前言 大家好&#xff0c;我是bigsai&#xff0c;很早就在写博客&#xff0c;我将csdn的文章整理成了一个pdf&#xff0c;并且开源到github上&#xff01; 自己写东西断断续续也不少时间了&#xff0c;也写了不少东西(虽然是偏向小白)&#xff0c;这个其实花费的时间还是比较多…

ENVI IDL:如何解析XML文件(以Landsat9-MTL.xml文件为例)

01 前言 我们原本是打算对Landsat9文件进行辐射定标&#xff0c;但是辐射定标的参数在MTL文件中&#xff0c;从文件中查看参数直接复制到IDL中固然可行&#xff0c;但是当我们对Landsat9文件进行批量辐射定标时&#xff0c;这种方法就将失效了。因此我们需要自动从MTL文件中读…

一个轻量级 Java 权限认证框架——Sa-Token

一、框架介绍 Sa-Token 是一个轻量级 Java 权限认证框架&#xff0c;主要解决&#xff1a;登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。 官网文档: https://sa-token.cc/doc.html 二、Spring Boot 集成Sa-Token 2.1、…

keil仿真错误:*** error 65: access violation at 0x40021000 : no ‘write‘ permission

按下图打开&#xff1a; 进行修改&#xff1a; 我用的芯片是:STM32F103C8T6 开始仿真&#xff1a; 成功解决不能仿真问题

mongodb导出聚合查询的数据

❗️❗️❗️在正文之前先要讲一个坑&#xff0c;就是mongoexport这个命令工具不支持导出聚合查询的数据&#xff0c;比如通过某某字段来分组 我查了一天关于mongoexport怎么来导出聚合查询的结果集&#xff0c;最终还是gpt给了我答案 &#x1f62d; 既然mongoexport不支持&…

1.微服务与SpringCloud

微服务和SpringCloud 文章目录 微服务和SpringCloud1.什么是微服务2.SpringCloud3. 微服务 VS SpringCloud4. SpringCloud 组件5.参考文档6.版本要求 1.什么是微服务 微服务是将一个大型的、单一的应用程序拆分成多个小型服务&#xff0c;每个服务实现特定的业务功能&#xff…