20182310 2019-2020 《数据结构与面向对象程序设计》实验九 图报告
课程:《程序设计与数据结构》
班级: 1823
姓名: 周烔
学号:20182310
实验教师:王志强
实验日期:2019年11月11日
必修/选修: 必修
1.实验内容
完成图的综合实践
(1)初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)(2分)
(2)图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)(4分)
(3)完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环(3分)
(4)完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出(3分)
(5)完成有向图的单源最短路径求解(迪杰斯特拉算法)(3分)
2.实验过程及结果
- 实验一创建图,初始化无向图和有向图
见之前课堂实践的代码即可 - 实验二图的遍历:完成有向图和无向图的遍历
见之前课堂实践的代码即可 - 实验3完成拓扑排序
private class Vertex{ private String vertexLabel; private List<Edge> adjEdges; private int inDegree; public Vertex(String verTtexLabel) { this.vertexLabel = verTtexLabel; inDegree = 0; adjEdges = new LinkedList<Edge>(); } } private class Edge { private Vertex endVertex; public Edge(Vertex endVertex) { this.endVertex = endVertex; } } private Map<String, Vertex> directedGraph; public DirectedGraph() { directedGraph = new LinkedHashMap<String, DirectedGraph.Vertex>(); buildGraph(); } private void buildGraph(){ Vertex startNode, endNode; String startNodeLabel, endNodeLabel; Edge e; Scanner scan = new Scanner(System.in); System.out.println("输入边数:"); int m = scan.nextInt(); for (int i = 0; i <m; i++) { System.out.println("输入每条边的顶点边数: "); startNodeLabel = scan.next(); endNodeLabel = scan.next(); startNode = directedGraph.get(startNodeLabel); if (startNode == null) { startNode = new Vertex(startNodeLabel); directedGraph.put(startNodeLabel, startNode); } endNode = directedGraph.get(endNodeLabel); if (endNode == null) { endNode = new Vertex(endNodeLabel); directedGraph.put(endNodeLabel, endNode); } e = new Edge(endNode); startNode.adjEdges.add(e); endNode.inDegree++; } } public void topoSort() throws Exception{ int count = 0; Queue<Vertex> queue = new LinkedList<>(); Collection<Vertex> vertexs = directedGraph.values(); for (Vertex vertex : vertexs) if(vertex.inDegree == 0) queue.offer(vertex); while(!queue.isEmpty()){ Vertex v = queue.poll(); System.out.print(v.vertexLabel + " "); count++; for (Edge e : v.adjEdges) if(--e.endVertex.inDegree == 0) queue.offer(e.endVertex); } if(count != directedGraph.size()){ throw new Exception("该图存在环"); } }
- 实验4用Kruscal算法完成最小生成树
- 实验五用迪杰斯特拉算法算出最短路径
3. 实验过程中遇到的问题和解决过程
- 问题1:在输出图的列表时,未能进行排列
- 问题1解决方法:数组定义的问题,修改后即可
- 问题2:关于迪杰斯特拉算法怎么实现
- 问题2解决方法:1)判断是否达到终止条件,如果达到终止条件,结束本次算法,如果没有达到,执行下一步;(终止条件:下一次需要计算的节点队列没有数据或已经计算过的节点数等于节点总数)
2)获取下一次计算的节点A;
3)从起点到各节点之间的最短距离map中获取到达A点的最小距离L;
4)获取A节点的可达节点B,计算从起点先到A再到B是否优于已有的其他方式到B,如果优于,则更新B节点,否则不更新;
5)判断B是否是已经移除的节点,如果不是移除的节点,把B添加到下一次需要计算的节点队列中,否则不做操作;
6)判断A节点是否还有除B以外的其他节点,如果有,执行第4)步,否则执行下一步;
7)将A节点从下一次需要计算的节点中移除添加到已经计算过的节点中;
其他(感悟、思考等)
图这一章不太好学,课堂实践也很多,很多算法实现都没见过,需要好好理解消化。有些逻辑也较为复杂,需要潜心判断和思考。在做实验的过程中编写代码也有些困难。