Java教程

20202320 实验九《数据结构与面向对象程序设计——图》实验报告

本文主要是介绍20202320 实验九《数据结构与面向对象程序设计——图》实验报告,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

课程:《程序设计与数据结构》
班级: 2023
姓名: 陈欢
学号:20202320
实验教师:王志强
实验日期:2021年12月23日
必修/选修: 必修

##1.实验内容

  (1) 初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)(2分)
  (2) 图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)(4分)
  (3) 完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环(3分)
  (4) 完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出(3分)
  (5) 完成有向图的单源最短路径求解(迪杰斯特拉算法)(3分)

##2.实验过程及结果

  (1)初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)(2分)

  

 

   (2) 图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)(4分)

   如上图所示:其中邻接矩阵表示的有向图是(由于作图原因,其中顶点0直接与顶点5相连通):

    无向图的遍历:

  完整代码如下:

public void Depth(int i){
    //标记第i个节点以遍历
    visited[i]=true;
    //打印当前已经遍历的节点
    visit(i);
    //遍历邻接矩阵中第i个节点的直接连通节点
    for(int j=0;j<nodenum;j++){
        if(Adjacency[i][j]==1&&visited[j]==false){
            Depth(j);
        }
    }
}
//深度优先遍历
public void dfs(){
    //初始化节点访问标记
    for(int i=0;i<visited.length;i++){
        visited[i]=false;
    }
    //从没有被遍历的节点开始深度优先遍历
    for(int i=0;i<nodenum;i++){
        if(visited[i]==false){
            Depth(i);
        }
    }
    System.out.println();
}
//广度遍历
public void bfs(){
    //初始化节点访问标记
    for(int i=0;i<visited.length;i++){
        visited[i]=false;
    }
    Queue<Integer> queue=new LinkedList<Integer>();
    for(int i=0;i<nodenum;i++){
        if(visited[i]==false){
            visited[i]=true;
            //打印当前已经遍历的节点
            visit(i);
            //添加到队列里
            queue.add(i);
            //只要队列不为空
            while(!queue.isEmpty()){
                //出队节点,也就是这一层的节点
                int k=queue.poll();
                //遍历所有未被访问的邻接节点,放入队列
                for(int j=0;j<nodenum;j++){
                    //也就是访问这一层剩下的未被访问的节点
                    if(Adjacency[k][j]==1&&visited[j]==false){
                        visited[j]=true;
                        visit(j);
                        queue.add(j);
                    }
                }
            }
        }
    }
    System.out.println();
}

  (3)完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环(3分)

    有向图的拓扑排序如实验内容(1)所示。

    完整代码如下:

    public void Topo(int i){    int sum=0;

    public void Topo(int i){
  itn sum=0;
  for(int j=0;j<nodenum;j++){
        sum=sum+rear[j][i];//行
    }
    if(sum==0){//第i个节点没有前驱
        visited[i]=true;
        visit(i);
        for(int k=0;k<nodenum;k++){
            rear[i][k]=0;//列
        }
    }

}
public void Topological(){
    for(int i=0;i<visited.length;i++){
        visited[i]=false;
    }
    int sum0=0;
    do {
        int i;
        for (i = 0; i < nodenum; i++) {
            if (visited[i] == false) {
                Topo(i);
            }
        }
        if(i==nodenum&&visited[i-1]==false) {
            System.out.println("该图存在环!");
            sum0=nodenum;
        }else {
            for (int j = 0; j < nodenum; j++) {//判断是否全部遍历
                if (visited[j] == true) {
                    sum0++;
                } else {
                    sum0 = 0;
                    break;
                }
            }
        }
    }while(sum0!=nodenum);
    System.out.println();
}

(4) 完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出(3分)

 使用的是Prime 算法,完整代码如下:

public void Prime(){
    for(int i=0;i<nodenum;i++){
        visited[i]=false;
    }
    for(int i=0;i<nodenum;i++){
        if(visited[i]==false){
            Primehelp(i);
        }
    }
    rear=Adjacency;
}//生成最小生成树
public void Primehelp(int i) {//无向图使用
    int key = 0;
    int a = 0, b = 0;
    if (visited[i] == false) {
        for (int j = 0; j < nodenum; j++) {
            if (rear[i][j] > key)
                key = rear[i][j];//第i行的最大值
        }
            for (int j = 0; j < nodenum; j++) {
                if (rear[i][j] < key && rear[i][j] != 0) {
                    key = rear[i][j];//第i行的最小值
                    a = i;
                    b = j;
                }
            }
            for (int num = 0; num < nodenum; num++) {
                if (visited[num] == true) {
                    for (int p = 0; p < nodenum; p++) {
                        if (rear[num][p] < key && rear[num][p] != 0) {
                            key = rear[num][p];
                            a = num;
                            b = p;
                        }
                    }
                }
            }
        }
        if (visited[b] == false) {
            rear[a][b] = 0;
            rear[b][a] = 0;
            visited[i] = true;
            visit(i);
            System.out.print("(" + key + ")");
            Primehelp(b);
        } else {
            rear[a][b] = 0;
            rear[b][a] = 0;
            int sum = 0;
            for (int ni = 0; ni < nodenum; ni++) {
                if (visited[ni] == true) {
                    sum++;
                }
            }
            if (sum != nodenum)
                if (sum == nodenum - 1) {
                    for (int ni = 0; ni < nodenum; ni++) {
                        if (visited[ni] == false)
                            System.out.println(vertices[ni]);
                    }
                } else
                    Primehelp(i);
    }
}
(5) 完成有向图的单源最短路径求解(迪杰斯特拉算法)(3分)
暂未完成

##3.实验中遇到的问题和解决方法
--问题一:进行拓扑排序时总是不能够在最后输出正确的邻接矩阵。
--解决方法:给邻接矩阵做一个“分身”,在进行拓扑排序时,只对“分身”进行操作,而要输出的邻接矩阵并不做改变。
      同时该“分身”不能够定义为rear=Adjacency,因为这样定义出的“分身”矩阵和Adjacency矩阵是同一个“存储空间”(应该是这么叫吧)。
--问题二:递归是难以退出。
--解决方法:通过调试,找出能够退出的唯一条件,这个条件需要做到所谓“当且仅当”(maybe)。
##4.实验心得与体会
  首先是后悔没有早点动手,到了考试周才匆匆忙忙的做。
  其次是递归的运用,在这次的实验中,递归的重要作用比之前的更加突出,递归非常考验人的逻辑(我觉得)。
  最后,最后一次实验值得好好……
##5.参考资料
--数据结构和算法动态可视化 (Chinese) - VisuAlgo
--(3条消息) JAVA实现图的深度优先遍历._今天又是充满希望的一天-CSDN博客_java实现深度优先搜索
--《Java程序设计教程(第九版)》
--《Java软件结构与数据结构(第四版)》


 

 

 

 

 

 

 

这篇关于20202320 实验九《数据结构与面向对象程序设计——图》实验报告的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!