《数据结构与面向对象程序设计》实验9报告

学号 20182329 2019-2020-1 《数据结构与面向对象程序设计》实验9报告

  • 课程:《程序设计与数据结构》
  • 班级: 1823
  • 姓名: 李一卓
  • 学号:20182329
  • 实验教师:王志强
  • 实验日期:2019年12月3日
  • 必修/选修: 必修

1.实验内容

  • 实现二叉排序树,并学会编写删除、添加、插入,还有二叉排序树的遍历
  • 学习图的有关知识,了解有向图和无向图的区别,
  • 学习带权图,学会计算带权图的算法,最佳的算法。
  • 学习图的各种遍历,比如深度优先遍历和广度优先遍历。
  • 学习生成最小树的方法
  • 学会生成图的邻接矩阵的方法,还有计算每个节点的出度入度方法实现
  • 学会每个图的计算度的方法,还有不通过遍历进行的。
  • 完成有向图的单源最短路径求解(迪杰斯特拉算法)。

2. 实验过程及结果

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

初始化:

 public Graph(List<Vertex> vertexs, int[][] edges) {
            this.vertexs = vertexs;
            this.topVertexs=new ArrayList<GRAPGAPI.Vertex>();
            this.edges = edges;
            this.minTree=new int[this.vertexs.size()][this.vertexs.size()];
            initUnVisited();
        }

首先得初始化图,获得定点代码

public List<Vertex> getNeighbors(Vertex v) {
            //参数检测
            if(!isInGraph(v)){
                System.out.println("当前节点不在图中");
                return null;
            }
            List<Vertex> neighbors = new ArrayList<Vertex>();
            int position = vertexs.indexOf(v);
            Vertex neighbor = null;
            int distance;
            for (int i = 0; i < vertexs.size(); i++) {
                if (i == position) {
                    //顶点本身,跳过
                    continue;
                }
                distance = edges[position][i];    //到所有顶点的距离
                if (distance < Integer.MAX_VALUE) {
                    //是邻居(有路径可达)
                    neighbor = getVertex(i);
                    if (!neighbor.isMarked()) {
                        //如果邻居没有访问过,则加入list;
                        neighbors.add(neighbor);
                    }
                }
            }
            return neighbors;
        }
  • 完成有向图和无向图的遍历(深度和广度优先遍历),无向图与有向图相同。
//深度优先
 public void  DFS(String vertexName){
            int id=getIdOfVertexName(vertexName);
            if(id==-1)return;
            vertexs.get(id).setMarked(true);
            System.out.println("遍历到"+vertexs.get(id).getName());
            List<Vertex> neighbors = getNeighbors(vertexs.get(id));
            for(int i=0;i<neighbors.size();i++){
                if(!neighbors.get(i).isMarked()){
                    DFS(neighbors.get(i).getName());
                }
            }
        }
//广度优先
public void BFS(String vertexName){
            int startID=getIdOfVertexName(vertexName);
            if(startID==-1) return;
            List<Vertex> q=new ArrayList<Vertex>();
            q.add(vertexs.get(startID));
            vertexs.get(startID).setMarked(true);
            while(!q.isEmpty()){
                Vertex curVertex=q.get(0);
                q.remove(0);
                System.out.println("遍历到"+curVertex.getName());
                List<Vertex> neighbors = getNeighbors(curVertex);
                for(int i=0;i<neighbors.size();i++){
                    if(!neighbors.get(i).isMarked()){
                        neighbors.get(i).setMarked(true);
                        q.add(neighbors.get(i));
                    }
                }

            }

        }
  • 首先进行拓扑排序的时候,无向图是不能进行的,只有有向图可以进行。用邻接矩阵进行拓扑,MAX_VALUE表0.
public void topSort(){
            int[][] tmpEdges=edges;
            int IDofNullPreVertex=getNullPreVertexID(tmpEdges);//获得当前图中无前驱的节点
            while(IDofNullPreVertex!=-1){
                vertexs.get(IDofNullPreVertex).setMarked(true);
                topVertexs.add(vertexs.get(IDofNullPreVertex));//拓扑序列增加
                //边销毁
                for(int j=0;j<this.vertexs.size();j++){
                    if(tmpEdges[IDofNullPreVertex][j]!=Integer.MAX_VALUE){
                        tmpEdges[IDofNullPreVertex][j]=Integer.MAX_VALUE;
                    }
                }
                IDofNullPreVertex=getNullPreVertexID(tmpEdges);
            }

        }
  • 完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出
    而且可以进行无向图的最小生成树的更新。
public int[][] getMinTree(){
            initMinTree();//初始化最小生成树
            while(!allVisited()){
                Vertex vertex = vertexs.get(getNotMarkedMinVertex());//设置处理节点
                System.out.println("处理:节点"+vertex.getName());
                //顶点已经计算出最短路径,设置为"已访问"
                vertex.setMarked(true);
                //获取所有"未访问"的邻居
                List<Vertex> neighbors = getNeighbors(vertex);
                System.out.println("邻居个数为:"+neighbors.size());
                //更新最小生成树
                updateMinEdge(vertex, neighbors);
            }
            System.out.println("search over");
            setMinTree();

            return minTree;
        }

根据图的变化可以进行最小生成树的更新

 public void  updateMinEdge(Vertex vertex, List<Vertex> neighbors){
            //参数检测
            if(!isInGraph(vertex)){
                System.out.println("当前节点不在图中");
                return ;
            }

            for(Vertex neighbor: neighbors){
                int distance = edges[getIdOfVertexName(neighbor.getName())][getIdOfVertexName(vertex.getName())];
                if(neighbor.getAnotherIDinminEdge()==-1){
                    neighbor.setAnotherIDinminEdge(getIdOfVertexName(vertex.getName()));
                    System.out.println(neighbor.getName()+" setEdge To"+vertex.getName()+edges[neighbor.getAnotherIDinminEdge()][getIdOfVertexName(neighbor.getName())]);
                }
                else if(distance <  edges[getIdOfVertexName(neighbor.getName())][neighbor.getAnotherIDinminEdge()]){
                    neighbor.setAnotherIDinminEdge(getIdOfVertexName(vertex.getName()));
                    System.out.println(neighbor.getName()+" setEdge To"+vertex.getName()+edges[neighbor.getAnotherIDinminEdge()][getIdOfVertexName(neighbor.getName())]);
                }
            }
        }
  • 最后进行最短路径的生成

首先进行寻找定点的最短路径

public void search(){
            while(!unVisited.isEmpty()){
                Vertex vertex = unVisited.element();
                //顶点已经计算出最短路径,设置为"已访问"
                vertex.setMarked(true);
                List<Vertex> neighbors = getNeighbors(vertex);
                //更新邻居的最短路径
                updatesDistance(vertex, neighbors);
                pop();
            }
            System.out.println("最短路径");
        }

然后根据邻居最短路径的更新,进行的输出

 public List<Vertex> getNeighbors(Vertex v) {
            //参数检测
            if(!isInGraph(v)){
                System.out.println("当前节点不在图中");
                return null;
            }
            List<Vertex> neighbors = new ArrayList<Vertex>();
            int position = vertexs.indexOf(v);
            Vertex neighbor = null;
            int distance;
            for (int i = 0; i < vertexs.size(); i++) {
                if (i == position) {
                    //顶点本身,跳过
                    continue;
                }
                distance = edges[position][i];    //到所有顶点的距离
                if (distance < Integer.MAX_VALUE) {
                    //是邻居(有路径可达)
                    neighbor = getVertex(i);
                    if (!neighbor.isMarked()) {
                        //如果邻居没有访问过,则加入list;
                        neighbors.add(neighbor);
                    }
                }
            }
            return neighbors;
        }

3. 实验过程中遇到的问题和解决过程

  • 问题1:在进行生成图的时候,我选择以文件读写的方式写入图的数据

  • 问题1解决方法:是我在任务读写的方式有问题,我是双循环来进行文件输入图,,用行和“,”隔开,但是在输入“0”时,没有设置内循环的输出条件,所以在每一行走到“0”时就会无限循环。

  • 问题2:在进行输入图时,进行对节点的最短路径的处理,返现我卡在了第一个节点。

  • 问题2解决方法:邻接矩阵的输入方式存在敕位问题。

其他(感悟、思考等)

在进行运算生成图的时候,选择链表进行图的生成时,后续的排序会比较麻烦,而且在进行图的顶点的各种操作时(读取),顶点的入度出度会显示。关键在进行各种排序时,还是,还有需要报错程序,这样找不到顶点可以自动返回。

参考资料

posted @ 2019-12-06 11:41  李一卓  阅读(203)  评论(0编辑  收藏