南京邮电大学离散数学实验四(图论)

一、 实验目的和要求

中文五号宋体,英文五号Times new roman字体,1.25倍行距
描述本次实验的目的和要求。

二、实验环境(实验设备)

中文五号宋体,英文五号Times new roman字体,1.25倍行距
硬件:微型计算机
软件:Windows 操作系统、Microsoft Visual C++6.0、Java等可视化编程语言

三、实验原理及内容

中文五号宋体,英文五号Times new roman字体,1.25倍行距
说明:这部分内容主要包括:
1、形式化描述实验中所使用的数据结构和存储结构,给出函数之间的调用关系和数据传递方式;
2、给出核心算法的C++或Java等语言的源代码,并加上详细注释,分析算法的时间复杂度;
3、给出测试数据及运行结果、实验相关结论等。

(一)数据结构和存储结构:主要是数组

EXP4 e = new EXP4(100); // 可达矩阵的最大节点数来构造
rand(); // 随机生成
printConnectedMatrix(); //打印邻接矩阵
getReachableMatrix(); //获取可达矩阵
unitization(); // 可达矩阵单位化
printReachableMatrix(); //打印可达矩阵
isReachable();
getDegrees(); //获取所有节点的度数
printEulerMap();
依次执行

(二)核心算法

public void getEulerMap(int currentIndex) {  // 传入参数为当前的欧拉路节点次序
	if (has == 1) return;  
	if (count == edge + 1) {  
		print();  // 打印欧拉路的节点
	    has = 1;  
     } 
     else {  
          for (int i = 0; i < n; i++) {  
             if (connectedMatrix[currentIndex][i] == 1 && vis[currentIndex][i] == 0) {  
				vis[i][currentIndex] = vis[currentIndex][i] = 1;  
				node[count++] = i;  
				getEulerMap(i);  
				count--;  
				vis[i][currentIndex] = vis[currentIndex][i] = 0;  
			}  
		}  
	}  
}  

递归法求欧拉路
时间复杂度为O( n ^ 2)

(三)测试数据及运行结果

测试一:
  1. num of node is: 6
  2. ConnectedMatrix
  3. 0 1 0 0 0 0
  4. 1 0 0 0 0 1
  5. 0 0 0 0 1 0
  6. 0 0 0 0 0 0
  7. 0 0 1 0 0 1
  8. 0 1 0 0 1 0
  9. ReachableMatrix
  10. 1 1 1 0 1 1
  11. 1 1 1 0 1 1
  12. 1 1 1 0 1 1
  13. 0 0 0 0 0 0
  14. 1 1 1 0 1 1
  15. 1 1 1 0 1 1
  16. isReachable? false
  17. Neither Euler road nor Euler circuit
测试二:
  1. num of node is: 7
  2. ConnectedMatrix
  3. 0 1 1 0 0 1 1
  4. 1 0 0 0 0 1 0
  5. 1 0 0 1 1 1 1
  6. 0 0 1 0 1 0 1
  7. 0 0 1 1 0 0 0
  8. 1 1 1 0 0 0 1
  9. 1 0 1 1 0 1 0
  10. ReachableMatrix
  11. 1 1 1 1 1 1 1
  12. 1 1 1 1 1 1 1
  13. 1 1 1 1 1 1 1
  14. 1 1 1 1 1 1 1
  15. 1 1 1 1 1 1 1
  16. 1 1 1 1 1 1 1
  17. 1 1 1 1 1 1 1
  18. isReachable? true
  19. Euler road
  20. 2->0->1->5->0->6->2->3->4->2->5->6->3
测试三:
  1. num of node is: 5
  2. ConnectedMatrix
  3. 0 0 0 1 1
  4. 0 0 1 1 1
  5. 0 1 0 0 1
  6. 1 1 0 0 0
  7. 1 1 1 0 0
  8. ReachableMatrix
  9. 1 1 1 1 1
  10. 1 1 1 1 1
  11. 1 1 1 1 1
  12. 1 1 1 1 1
  13. 1 1 1 1 1
  14. isReachable? true
  15. Euler road
  16. 1->2->4->0->3->1->4
测试四:
  1. num of node is: 8
  2. ConnectedMatrix
  3. 0 0 0 0 0 1 1 1
  4. 0 0 0 0 1 0 0 0
  5. 0 0 0 0 0 0 0 1
  6. 0 0 0 0 1 1 0 1
  7. 0 1 0 1 0 1 1 0
  8. 1 0 0 1 1 0 1 1
  9. 1 0 0 0 1 1 0 1
  10. 1 0 1 1 0 1 1 0
  11. ReachableMatrix
  12. 1 1 1 1 1 1 1 1
  13. 1 1 1 1 1 1 1 1
  14. 1 1 1 1 1 1 1 1
  15. 1 1 1 1 1 1 1 1
  16. 1 1 1 1 1 1 1 1
  17. 1 1 1 1 1 1 1 1
  18. 1 1 1 1 1 1 1 1
  19. 1 1 1 1 1 1 1 1
  20. isReachable? true
  21. Neither Euler road nor Euler circuit
测试五:
  1. num of node is: 5
  2. ConnectedMatrix
  3. 0 1 1 1 1
  4. 1 0 1 1 1
  5. 1 1 0 1 1
  6. 1 1 1 0 1
  7. 1 1 1 1 0
  8. ReachableMatrix
  9. 1 1 1 1 1
  10. 1 1 1 1 1
  11. 1 1 1 1 1
  12. 1 1 1 1 1
  13. 1 1 1 1 1
  14. isReachable? true
  15. Euler circuit
  16. 0->1->2->0->3->1->4->2->3->4->0
测试六:
  1. num of node is: 10
  2. ConnectedMatrix
  3. 0 1 1 1 1 1 1 1 1 1
  4. 1 0 1 1 1 1 1 1 0 1
  5. 1 1 0 1 1 1 1 1 1 1
  6. 1 1 1 0 1 1 1 1 1 1
  7. 1 1 1 1 0 1 1 1 1 1
  8. 1 1 1 1 1 0 1 1 1 1
  9. 1 1 1 1 1 1 0 1 1 1
  10. 1 1 1 1 1 1 1 0 1 1
  11. 1 0 1 1 1 1 1 1 0 1
  12. 1 1 1 1 1 1 1 1 1 0
  13. ReachableMatrix
  14. 1 1 1 1 1 1 1 1 1 1
  15. 1 1 1 1 1 1 1 1 1 1
  16. 1 1 1 1 1 1 1 1 1 1
  17. 1 1 1 1 1 1 1 1 1 1
  18. 1 1 1 1 1 1 1 1 1 1
  19. 1 1 1 1 1 1 1 1 1 1
  20. 1 1 1 1 1 1 1 1 1 1
  21. 1 1 1 1 1 1 1 1 1 1
  22. 1 1 1 1 1 1 1 1 1 1
  23. 1 1 1 1 1 1 1 1 1 1
  24. isReachable? true
  25. Neither Euler road nor Euler circuit

四、实验小结(包括问题和解决方法、心得体会、意见与建议等)

中文五号宋体,英文五号Times new roman字体,1.25倍行距
说明:这部分内容主要包括:在编程、调试或测试过程中遇到的问题及解决方法、本次实验的心得体会、进一步改进的设想等。

(一)实验中遇到的主要问题及解决方法

  1. 在利用函数isEulerMap()判断是否是孤立节点时,发现单个节点的图经函数判断后是EulerMap,改正后,即将孤立节点考虑后,函数功能正确。
  2. 在编写如何求路径的时候,查找了多种算法说明,最终选择一种进行代码实现。

(二)实验心得

对如何利用计算机求欧拉图有了深刻的认识,对离散数学中的相关图论的概念有了更深的理解。

(三)意见与建议(没有可省略)

五、全部源代码(Java)

(一)(半)欧拉图的判定,求欧拉(回)路

import java.lang.Math;
import java.util.Random;

public class EXP4 {
    private int[][] graph;              // 随机生成的原始矩阵
    private int[][] connectedMatrix;    // 邻接矩阵
    private int[][] reachableMatrix;    // 可达矩阵
    private int[] degrees;              // 度数数组
    private int n;                      // 总节点数
    private int edge;                   // 边
    private int sumDegrees;             // 总节点数
    private int has;                    // 标志符
    private int[][] vis;                // 临时数组
    private int[] node;                 // 存放欧拉路的节点的数组
    private int count;                  // 已找到的欧拉路的节点个数

    // 构造函数
    public EXP4(int size) {
        this.graph = new int[size][size];
        this.connectedMatrix = new int[size][size];
        this.reachableMatrix = new int[size][size];
        this.degrees = new int[size];
        this.vis = new int[size][size];
        this.node = new int[size];
    }


    // 随机生成邻接矩阵
    public void rand() {
        // 随机数生成器
        Random rand = new Random();
        // 随机生成 10 个以内的节点
        n = rand.nextInt(10) + 1;
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                // 控制产生 1 和 0 的概率 为 1:1
                graph[i][j] = Math.random() > 0.5 ? 0 : 1;
                graph[j][i] = graph[i][j];
                if (i == j) {
                    graph[i][j] = 0;
                }
            }
        }
        connectedMatrix = graph;
        System.out.println("num of node is: " + n);
        System.out.println();
    }


    // 矩阵加法
    public int[][] addition(int[][] m1, int[][] m2) {
        int[][] tmp = new int[100][100];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                tmp[i][j] = m1[i][j] + m2[i][j];
            }
        }
        return tmp;
    }

    // 矩阵乘法
    public int[][] multiplication(int[][] m1, int[][] m2) {
        int[][] tmp = new int[100][100];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    tmp[i][j] += m1[i][k] * m2[k][j];
                }
            }
        }
        return tmp;
    }

    // 求可达矩阵
    public void getReachableMatrix() {
        reachableMatrix = graph;
        for (int i = 0; i < n - 1; i++) {
            graph = multiplication(graph, connectedMatrix);      // 求矩阵的幂
            reachableMatrix = addition(graph, reachableMatrix);  // 求矩阵幂的和
        }
    }

    // 判断是否是可达
    public boolean isReachable() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {   // 如果有为零的,返回 false
                if (reachableMatrix[i][j] == 0) {
                    return false;
                }
            }
        }
        return true;
    }

    // 可达矩阵单位化
    public void unitization() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (reachableMatrix[i][j] != 0) {
                    reachableMatrix[i][j] = 1;
                }
            }
        }
    }

    // 是否是(半)欧拉图
    public int isEulerMap() {
        // 如果是孤立节点返回 0
        if (n == 0) {
            return 0;
        }
        // 记录奇数的节点的个数
        int num = 0;
        // 如果不可达 返回 0
        if (isReachable() == false) {
            return 0;
        }
        // 计算度数为奇数的节点的个数
        for (int i = 0; i < n; i++) {
            if (degrees[i] % 2 == 1) {
                num++;
            }
        }
        // 如果度数为奇数的节点的个数为 0, 返回 1 (半欧拉图)
        if (num == 2) {
            return 1;
        }
        // 如果度数为奇数的节点的个数为 0, 返回 2 (欧拉图)
        if (num == 0) {
            return 2;
        }
        System.out.println();
        // 其他情况, 返回 0
        return 0;
    }

    // 计算所有节点的度数
    public void getDegrees() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (connectedMatrix[i][j] != 0) {
                    degrees[i]++;
                }
            }
        }
        for (int i = 0; i < n; i++) {
            sumDegrees += degrees[i];
        }
        // 利用度数之和等于边数的二倍求边数
        edge = sumDegrees / 2;
    }

    // 打印各个节点的度数
    public void printDegrees() {
        for (int i = 0; i < n; i++) {
            System.out.print(degrees[i] + " ");
        }
    }

    // 打印可达矩阵
    public void printReachableMatrix() {
        System.out.println("ReachableMatrix");
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(reachableMatrix[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }

    // 打印邻接矩阵
    public void printConnectedMatrix() {
        System.out.println("ConnectedMatrix");
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(connectedMatrix[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }

    // 欧拉路计算(核心算法)
    public void getEulerMap(int currentIndex) {
        if (has == 1) return;
        if (count == edge + 1) {
            for (int i = 0; i < count; i++) {
                if (i == 0) {
                    System.out.print(node[i]);
                } else {
                    System.out.print("->" + node[i]);
                }
            }
            System.out.println();
            has = 1;
        } else {
            for (int i = 0; i < n; i++) {
                if (connectedMatrix[currentIndex][i] == 1 && vis[currentIndex][i] == 0) {
                    vis[i][currentIndex] = vis[currentIndex][i] = 1;
                    node[count++] = i;
                    getEulerMap(i);
                    count--;
                    vis[i][currentIndex] = vis[currentIndex][i] = 0;
                }
            }
        }
    }

    // 打印欧拉路
    public void printEulerMap() {
        int result = isEulerMap();
        if (result == 1) {
            System.out.println("Euler road");
            for (int i = 0; i < n; i++) {
                int t = 0;
                for (int j = 0; j < n; j++) {
                    if (connectedMatrix[i][j] == 1) {
                        t++;
                    }
                }
                if (t % 2 == 1) {
                    node[count++] = i;
                    getEulerMap(i);
                    count--;
                    break;
                }
            }
            return;
        } else if (result == 2) {
            System.out.println("Euler circuit");
            node[count++] = 0;
            getEulerMap(0);  //找出回路
            count--;
        } else {
            System.out.println("Neither Euler road nor Euler circuit");
        }
    }

    // 主函数
    public static void main(String[] args) {
        EXP4 e = new EXP4(100);        // 可达矩阵的最大节点数来构造
        e.rand();                           // 随机生成
        e.printConnectedMatrix();           //打印邻接矩阵
        e.getReachableMatrix();             //获取可达矩阵
        e.unitization();                    // 可达矩阵单位化
        e.printReachableMatrix();           //打印可达矩阵
        System.out.println("isReachable? " + e.isReachable());
        e.getDegrees();                     //获取所有节点的度数
        e.printEulerMap();                  //打印欧拉路
    }
}




  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亦是远方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值