内容:编程随即生成n个极点的无向图并能进行(半)欧拉图的判定,若是则给出欧拉(回)路。
要求:对给定n个结点,随即生成邻接矩阵以确定某无向简单图并进行欧拉图和半欧拉图的判定,若符合则给出至少一条欧拉回路或欧拉路。
import java.util.Scanner;
import java.util.Stack;
public class Graphtheory {
public static int spots = 0;
public static int edges= 0;
public static int[][] Gate; //表示图的邻接矩阵
public static int[] visted; //记录点是否被访问0未访问,1已访问
public static int begin; //判断是否为联通图,begin为查询时的起点
public static int degree; //顶点的度
public static int num = 0; //奇度顶点的个数
public static int start = 0; //欧拉路的起点
public static Stack stack;
public static int[] ans; //记录欧拉路的路径
public static int count = 0; //记录路径数
public static int maxEdge;
//随即生成图并输出
public static void Generate() {
int cnt = 0;
while (cnt < edges) {
int x = (int) (Math.random()*spots); //生成范围是0到n的随机数
int y = (int) (Math.random()*spots);
if (x != y && Gate[x][y] == 0) {
Gate[x][y] = 1;
Gate[y][x] = 1;
cnt++;
begin = x;
}
}
if (spots <= 20) {
System.out.println("图的邻接矩阵为:");
for (int i = 0; i < spots; i++) {
for (int j = 0; j < spots; j++) {
System.out.print(" " + Gate[i][j]);
}
System.out.println();
}
System.out.println();
}
}
//深度遍历
private static void DFS(int x) {
visted[x] = 1;
for (int i = 0; i < spots; i++) {
if (visted[i] == 0 && Gate[x][i] == 1) {
DFS(i);
}
}
}
//判断是否是连通的
private static boolean Judge() {
DFS(begin);
for (int i = 0; i < spots; i++) {
if (visted[i] == 0) {
return false;
}
}
return true;
}
public static void DFSGraph(int x) {
stack.push(x);
for (int i = 0; i < spots; i++) {
if (Gate[i][x] == 1) {
Gate[i][x] = 0; //删除该边
Gate[x][i] = 0;
DFSGraph(i);
break;
}
}
}
//Fleury算法
public static void Fleury(int x) {
int flag;
ans = new int[100];
stack = new Stack();
stack.push(x);
while (!stack.isEmpty()) {
flag = 0;
for (int i = 0; i < spots; i++) {
if (Gate[(int) stack.peek()][i] == 1) {
flag = 1;
break;
}
}
if (flag == 0) {
//如果没有可扩展的点,则记录下该点并将其出栈
ans[count] = 1 + (int)(stack.pop());
count++;
}else {
int n = (int) stack.pop();
DFSGraph(n);
}
}
}
public static void main(String[] args) {
do{
Scanner sc = new Scanner(System.in);
System.out.println("请输入无向图顶点的个数(大于0且不超过20的整数)");
int n = sc.nextInt();
spots = n;
System.out.println("请输入边的个数");
int s = sc.nextInt();
edges = s;
maxEdge = n*(n-1)/2;
if (s > maxEdge) {
System.out.println("有"+ n + "个点的无向图最多有" + maxEdge+"条边");
}
}while (edges > maxEdge);
Gate = new int[spots][spots];
visted = new int[spots];
for (int i = 0; i < spots; i++) {
visted[i] = 0;
for (int j = 0; j < spots; j++) {
Gate[i][j] = 0;
}
}
Generate();
if (!Judge()) {
System.out.println("不是连通图");
}else {
//如果存在奇度顶点,则从奇度顶点出发,否则从0出发
for (int i = 0; i < spots; i++) {
degree = 0;
for (int j = 0; j < spots; j++) {
degree += Gate[i][j];
}
if (degree % 2 == 1) {
start = i;
num++;
}
}
//无向图具有一条欧拉路,当且仅当G是连通的,且有0个或2个奇数度结点
if (num == 0 || num == 2) {
// System.out.println("起点为:" + start);
Fleury(start);
//欧拉路径的头和尾相等,则说明欧拉路是回路
if (ans[0] == ans[count - 1]) {
System.out.println("是欧拉图,欧拉回路为:");
}else {
System.out.println("是半欧拉图,欧拉路径为:");
}
for (int i = 0; i < count; i++) {
System.out.print(ans[i]+" ");
}
}else {
System.out.println("不是欧拉图或者半欧拉图");
}
}
}
}
测试结果: