▶ 书中第四章部分程序,包括在加上自己补充的代码,图中找欧拉路径

● 无向图中寻找欧拉路径,只注释了与欧拉环不同的地方

 package package01;

 import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.GraphGenerator;
import edu.princeton.cs.algs4.Graph;
import edu.princeton.cs.algs4.Stack;
import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.BreadthFirstPaths; public class class01
{
private Stack<Integer> cycle = new Stack<Integer>(); private static class Edge
{
private final int v;
private final int w;
private boolean isUsed; public Edge(int v, int w)
{
this.v = v;
this.w = w;
isUsed = false;
} public int other(int vertex)
{
if (vertex == v)
return w;
if (vertex == w)
return v;
throw new IllegalArgumentException("\n<other> No such vertex.\n");
}
} public class01(Graph G)
{
if (G.E() == 0)
return;
int oddDegreeVertices = 0; // 记录奇数度点的数量
int s = nonIsolatedVertex(G); // 选一个非孤立点为起点,有奇数度点的话要更换
if (G.E() == 0) // 认为无边的图也存在欧拉路径,这与欧拉环不同
s = 0;
else // 其他情况照常处理
{
for (int v = 0; v < G.V(); v++)
{
if (G.degree(v) % 2 != 0)
{
oddDegreeVertices++;
s = v;
}
}
if (oddDegreeVertices > 2) // 奇数度点多于 2,不存在欧拉路径
return;
Queue<Edge>[] adj = (Queue<Edge>[]) new Queue[G.V()];
for (int v = 0; v < G.V(); v++)
adj[v] = new Queue<Edge>();
for (int v = 0; v < G.V(); v++)
{
boolean selfEdge = false;
for (int w : G.adj(v))
{
if (v == w)
{
if (!selfEdge)
{
Edge e = new Edge(v, w);
adj[v].enqueue(e);
adj[w].enqueue(e);
}
selfEdge = !selfEdge;
}
else if (v < w)
{
Edge e = new Edge(v, w);
adj[v].enqueue(e);
adj[w].enqueue(e);
}
}
}
}
Stack<Integer> stack = new Stack<Integer>();
stack.push(s);
for (path = new Stack<Integer>(); !stack.isEmpty();)
{
int v = stack.pop();
for (; !adj[v].isEmpty();)
{
Edge edge = adj[v].dequeue();
if (edge.isUsed)
continue;
edge.isUsed = true;
stack.push(v);
v = edge.other(v);
}
path.push(v);
}
if (path.size() != G.E() + 1)
path = null;
} public Iterable<Integer> path()
{
return path;
} public boolean hasEulerianPath()
{
return path != null;
} private static int nonIsolatedVertex(Graph G)
{
for (int v = 0; v < G.V(); v++)
{
if (G.degree(v) > 0)
return v;
}
return -1;
} private static boolean satisfiesNecessaryAndSufficientConditions(Graph G)
{
if (G.E() == 0) // 认为没有变的图也有欧拉路径,统计奇数度的顶点
return true;
int oddDegreeVertices = 0;
for (int v = 0; v < G.V(); v++)
{
if (G.degree(v) % 2 != 0)
oddDegreeVertices++;
}
if (oddDegreeVertices > 2)
return false;
BreadthFirstPaths bfs = new BreadthFirstPaths(G, nonIsolatedVertex(G));
for (int v = 0; v < G.V(); v++)
{
if (G.degree(v) > 0 && !bfs.hasPathTo(v))
return false;
}
return true;
} private static void unitTest(Graph G, String description)
{
System.out.printf("\n%s--------------------------------\n", description);
StdOut.print(G);
class01 euler = new class01(G);
System.out.printf("Eulerian path: ");
if (euler.hasEulerianCycle())
{
for (int v : euler.cycle())
System.out.printf(" %d", v);
}
System.out.println();
} public static void main(String[] args)
{
int V = Integer.parseInt(args[0]);
int E = Integer.parseInt(args[1]); Graph G1 = GraphGenerator.eulerianCycle(V, E);
unitTest(G1, "Eulerian cycle"); Graph G2 = GraphGenerator.eulerianPath(V, E);
unitTest(G2, "Eulerian path"); Graph G3 = new Graph(G2);
G3.addEdge(StdRandom.uniform(V), StdRandom.uniform(V));
unitTest(G3, "one random edge added to Eulerian path"); Graph G4 = new Graph(V);
int v4 = StdRandom.uniform(V);
G4.addEdge(v4, v4);
unitTest(G4, "single self loop"); Graph G5 = new Graph(V);
G5.addEdge(StdRandom.uniform(V), StdRandom.uniform(V));
unitTest(G5, "single edge"); Graph G6 = new Graph(V);
unitTest(G6, "empty graph"); Graph G7 = GraphGenerator.simple(V, E);
unitTest(G7, "simple graph");
}
}

● 有向图中寻找欧拉路径,只注释了与欧拉环以及无向图欧拉路径不同的地方

 package package01;

 import java.util.Iterator;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.DigraphGenerator;
import edu.princeton.cs.algs4.Graph;
import edu.princeton.cs.algs4.Digraph;
import edu.princeton.cs.algs4.Stack;
import edu.princeton.cs.algs4.BreadthFirstPaths; public class class01
{
private Stack<Integer> path = null; public class01(Digraph G)
{
int s = nonIsolatedVertex(G);
if (s == -1) // 没有边
s = 0;
else
{
int deficit = 0; // 统计所有顶点总出度与总入度的差
for (int v = 0; v < G.V(); v++)
{
if (G.outdegree(v) > G.indegree(v)) // 计算 deficit 不能直接加总出度和入度的差
{ // 因为平行边不影响 G.outdegree(v) - G.indegree(v),但会导致不存在欧拉路径
deficit += (G.outdegree(v) - G.indegree(v));
s = v;
}
}
if (deficit > 1) // 差大于 1 则不存在欧拉路径
return;
}
path = new Stack<Integer>();
Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()];
for (int v = 0; v < G.V(); v++)
adj[v] = G.adj(v).iterator();
Stack<Integer> stack = new Stack<Integer>();
for (stack.push(s); !stack.isEmpty(); )
{
int v = stack.pop();
for (; adj[v].hasNext(); v = adj[v].next())
stack.push(v);
path.push(v);
}
if (path.size() != G.E() + 1)
path = null;
} public Iterable<Integer> path()
{
return path;
} public boolean hasEulerianPath()
{
return path != null;
} private static int nonIsolatedVertex(Digraph G)
{
for (int v = 0; v < G.V(); v++)
{
if (G.outdegree(v) > 0)
return v;
}
return -1;
} private static boolean satisfiesNecessaryAndSufficientConditions(Digraph G)
{
if (G.E() == 0)
return true;
int deficit = 0;
for (int v = 0; v < G.V(); v++)
{
if (G.outdegree(v) > G.indegree(v))
deficit += (G.outdegree(v) - G.indegree(v));
}
if (deficit > 1)
return false;
Graph H = new Graph(G.V());
for (int v = 0; v < G.V(); v++)
{
for (int w : G.adj(v))
H.addEdge(v, w);
}
BreadthFirstPaths bfs = new BreadthFirstPaths(H, nonIsolatedVertex(G));
for (int v = 0; v < G.V(); v++)
{
if (H.degree(v) > 0 && !bfs.hasPathTo(v))
return false;
}
return true;
} private static void unitTest(Digraph G, String description)
{
System.out.printf("\n%s--------------------------------\n", description);
StdOut.print(G);
class01 euler = new class01(G);
System.out.printf("Eulerian path: ");
if (euler.hasEulerianPath())
{
for (int v : euler.path())
System.out.printf(" %d", v);
}
StdOut.println();
} public static void main(String[] args)
{
int V = Integer.parseInt(args[0]);
int E = Integer.parseInt(args[1]); Digraph G1 = DigraphGenerator.eulerianCycle(V, E);
unitTest(G1, "Eulerian cycle"); Digraph G2 = DigraphGenerator.eulerianPath(V, E);
unitTest(G2, "Eulerian path"); Digraph G3 = new Digraph(G2);
G3.addEdge(StdRandom.uniform(V), StdRandom.uniform(V));
unitTest(G3, "one random edge added to Eulerian path"); Digraph G4 = new Digraph(V);
int v4 = StdRandom.uniform(V);
G4.addEdge(v4, v4);
unitTest(G4, "single self loop"); Digraph G5 = new Digraph(V);
G5.addEdge(StdRandom.uniform(V), StdRandom.uniform(V));
unitTest(G5, "single edge"); Digraph G6 = new Digraph(V);
unitTest(G6, "empty digraph"); Digraph G7 = DigraphGenerator.simple(V, E);
unitTest(G7, "simple digraph");
}
}

《算法》第四章部分程序 part 8的更多相关文章

  1. 《算法》第四章部分程序 part 19

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,有边权有向图的邻接矩阵,FloydWarshall 算法可能含负环的有边权有向图任意两点之间的最短路径 ● 有边权有向图的邻接矩阵 package p ...

  2. 《算法》第四章部分程序 part 18

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,在有权有向图中寻找环,Bellman - Ford 算法求最短路径,套汇算法 ● 在有权有向图中寻找环 package package01; impo ...

  3. 《算法》第四章部分程序 part 16

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,Dijkstra 算法求有向 / 无向图最短路径,以及所有顶点对之间的最短路径 ● Dijkstra 算法求有向图最短路径 package packa ...

  4. 《算法》第四章部分程序 part 15

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,Kruskal 算法和 Boruvka 算法求最小生成树 ● Kruskal 算法求最小生成树 package package01; import e ...

  5. 《算法》第四章部分程序 part 14

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,两种 Prim 算法求最小生成树 ● 简单 Prim 算法求最小生成树 package package01; import edu.princeton ...

  6. 《算法》第四章部分程序 part 10

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,包括无向图连通分量,Kosaraju - Sharir 算法.Tarjan 算法.Gabow 算法计算有向图的强连通分量 ● 无向图连通分量 pack ...

  7. 《算法》第四章部分程序 part 9

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,两种拓扑排序的方法 ● 拓扑排序 1 package package01; import edu.princeton.cs.algs4.Digraph ...

  8. 《算法》第四章部分程序 part 17

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,无环图最短 / 最长路径通用程序,关键路径方法(critical path method)解决任务调度问题 ● 无环图最短 / 最长路径通用程序 pa ...

  9. 《算法》第四章部分程序 part 13

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,图的前序.后序和逆后续遍历,以及传递闭包 ● 图的前序.后序和逆后续遍历 package package01; import edu.princeto ...

  10. 《算法》第四章部分程序 part 12

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,图的几种补充数据结构,包括无向 / 有向符号图,有权边结构,有边权有向图 ● 无向符号图 package package01; import edu. ...

随机推荐

  1. camera-arm-RPI

    这个属于先收藏着,知道有个开源的东西. luvcview是一个开源项目,专注于UVC摄像头的测试,只要您的摄像头支持UVC驱动,即可使用luvcview测试程序,如何知道自己的摄像头是不是支持UVC驱 ...

  2. Django-models-迁移错误

    错误表现:数据表二次迁移时:django.db.utils.InternalError: (1138, 'Invalid use of NULL value') 错误原因:是因为二次修改了null值属 ...

  3. PHP 中如何创建和修改数组?

    PHP中使用array来创建一个数组:array( key=>value , key=>value …… )用方括号的语法来修改数组:$arr[] = value 例如:$arr = ar ...

  4. C/C++基础----用于大型程序的工具(异常处理,命名空间,多重继承)

    独立开发的子系统间协同处理错误的能力 使用各种库(可能包含独立开发的库进行协同开发的能力) 对比复杂的应用概念建模的能力 异常处理 异常将问题的检测和解决过程分离开 当执行一个throw之后,程序控制 ...

  5. a message box to confirm the action

    当点击窗口的X按钮时,弹出确认退出消息框,继续点击Yes,退出.否则,窗口继续处于打开状态 代码: """ This program shows a confirmati ...

  6. Hadoop 管理工具HUE配置-filebrowser配置

    Hue提供了图形化截面管理HDFS数据,可谓之非常方便,但是在配置上,还是有点麻烦的. 1 /home/hadoop/software/cloud/hue/desktop/conf/pseudo-di ...

  7. Java-Runoob-高级教程-实例-数组:11. Java 实例 – 删除数组元素

    ylbtech-Java-Runoob-高级教程-实例-数组:11. Java 实例 – 删除数组元素 1.返回顶部 1. Java 实例 - 删除数组元素  Java 实例 以下实例演示了如何使用 ...

  8. 1121 Damn Single (25 分)

    1121 Damn Single (25 分) "Damn Single (单身狗)" is the Chinese nickname for someone who is bei ...

  9. 搭建好lamp,部署owncloud。

    先上传两个文件 上传到root目录 上传到opt目录下 #mkdir /opt/dvd1 #mount /dev/sr0 /opt/dvd1 #cd /etc/yum.repos.d/ #vi dvd ...

  10. Jmeter(三十五)聚合报告

    Jmeter的聚合报告是一个非常nice的listener,接口测试以及性能测试方面都会用到这个nice的监听器. 那么优秀在什么地方呢?上图 日常工作中可能只关注这部分内容: 可是这里边的指标真的都 ...