课程:《程序设计与数据结构》
班级: 1823
姓名: 魏冰妍
学号:20182330
实验教师:王志强
实验日期:2019年12月2日
必修/选修: 必修html
完成图的综合实践
(1)初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图须要本身定义(顶点个数、边个数,建议先在草稿纸上画出图,而后再输入顶点和边数)
(2)图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)
(3)完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环
(4)完成无向图的最小生成树(Prim算法或Kruscal算法都可),并输出
(5)完成有向图的单源最短路径求解(迪杰斯特拉算法)java
1.初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图须要本身定义(顶点个数、边个数,建议先在草稿纸上画出图,而后再输入顶点和边数)node
public Sorting(char[] dingdian, EData[] bian) { int lenv = dingdian.length; int elen = bian.length; // 初始化顶点 mV= new N[lenv]; for (int i = 0; i < mV.length; i++) { mV[i] = new N(); mV[i].dingdian = dingdian[i]; mV[i].firstX = null; } // 初始化边 Enum = elen; for (int i = 0; i < elen; i++) { // 读取顶点 char c1 = bian[i].start; char c2 = bian[i].end; int weight = bian[i].weight; int p1 = gPs(c1); int p2 = gPs(c2); B node1 = new B (); node1.i = p2; node1.w = weight; //链接 if(mV[p1].firstX == null) mV[p1].firstX = node1; else Connect(mV[p1].firstX, node1); B node2 = new B (); node2.i = p1; node2.w = weight; //链接 if(mV[p2].firstX == null) mV[p2].firstX = node2; else Connect(mV[p2].firstX, node2); } }
2.图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)算法
private void DFS(int i, boolean[] BL) { B node; BL[i] = true; System.out.printf("%c ", mV[i].dingdian); node = mV[i].firstX; while (node != null) { if (!BL[node.i]) DFS(node.i, BL); node = node.nextX; } }
public void BFS() { int head = 0; int rear = 0; int[] queue = new int[mV.length]; // 辅组队列 boolean[] BL = new boolean[mV.length]; // 顶点访问标记 for (int i = 0; i < mV.length; i++) BL[i] = false; System.out.printf("广度优先遍历: "); for (int i = 0; i < mV.length; i++) { if (!BL[i]) { BL[i] = true; System.out.printf("%c ", mV[i].dingdian); queue[rear++] = i; // 入队列 } while (head != rear) { int j = queue[head++]; // 出队列 B node = mV[j].firstX; while (node != null) { int k = node.i; if (!BL[k]) { BL[k] = true; System.out.printf("%c ", mV[k].dingdian); queue[rear++] = k; } node = node.nextX; } } } System.out.printf("\n"); }
3.完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环数组
public int TpSort() { int index = 0; int num = mV.length; int[] ins; // 入度数组 char[] tops; Queue<Integer> queue; ins = new int[num]; tops = new char[num]; queue = new LinkedList<Integer>(); // 统计每一个顶点的入度数 for(int i = 0; i < num; i++) { B node = mV[i].firstX; while (node != null) { ins[node.i]++; node = node.nextX; } } // 将全部入度为0的顶点入队列 for(int i = 0; i < num; i ++) if(ins[i] == 0) queue.offer(i); // 入队列 while (!queue.isEmpty()) { // 队列非空 int j = queue.poll().intValue(); // 出队列。j是顶点的序号 tops[index++] = mV[j].dingdian; B node = mV[j].firstX; while(node != null) { // 入度减1。 ins[node.i]--; // 若入度为0,则入队列 if( ins[node.i] == 0) queue.offer(node.i); // 入队列 node = node.nextX; } } if(index != num) { System.out.printf("有向有环图\n"); return 1; } // 打印拓扑排序结果 System.out.printf("拓扑排序: "); for(int i = 0; i < num; i ++) System.out.printf("%c ", tops[i]); System.out.printf("\n"); return 0; }
public void kruskal() { int index = 0; int[] v = new int[Enum]; // 保存终点。 EData[] rets = new EData[Enum]; // 暂存结果数组 EData[] e; // 对应的全部边 e = getEdges(); // 将边按权排序 sortEdges(e, Enum); for (int i=0; i<Enum; i++) { int p1 = gPs(e[i].start); int p2 = gPs(e[i].end); int m = getEnd(v, p1); int n = getEnd(v, p2); // 若是m!=n,则没有造成环路 if (m != n) { v[m] = n; rets[index++] = e[i]; } } }
5.完成有向图的单源最短路径求解(迪杰斯特拉算法)数据结构
public void dijkstra(int s, int[] q, int[] t) { // flag[i]=true表示最短路径已成功获取。 boolean[] flag = new boolean[mV.length]; // 初始化 for (int i = 0; i < mV.length; i++) { flag[i] = false; q[i] = 0; // 顶点i的前驱顶点为0。 t[i] = getWeight(s, i); } // 初始化 flag[s] = true; t[s] = 0; int k = 0; for (int i = 1; i < mV.length; i++) { // 寻找当前最小的路径; // 寻找当前最小的路径; // 寻找当前最小的路径; int min = INF; for (int j = 0; j < mV.length; j++) { if (flag[j]==false && t[j]<min) { min = t[j]; k = j; } } // 获取到最短路径 flag[k] = true; for (int j = 0; j < mV.length; j++) { int tmp = getWeight(k, j); tmp = (tmp==INF ? INF : (min + tmp)); // 防止溢出 if (flag[j]==false && (tmp<t[j]) ) { t[j] = tmp; q[j] = k; } } }
问题1:try异常致使程序锁死。app
问题1解决方案:解决时发现不止我一我的有这个问题。参照博客发现是e.printStackTrace()
。因而删掉 e.printStackTrace() ,异常处理。学习
短期内大量请求访问此接口 -> 代码自己有问题,不少状况下抛异常 -> e.printStackTrace() 来打印异常到控制台 -> 产生错误堆栈字符串到字符串池内存空间 -> 此内存空间一会儿被占满了 -> 开始在此内存空间产出字符串的线程还没彻底生产完整,就没空间了 -> 大量线程产出字符串产出到一半,等在这儿(等有内存了继续搞啊)-> 相互等待,等内存,锁死了,整个应用挂掉了。.net
最后一个小实验,我的认为图的理解比树简单一点,而且能够利用到离散中学过的知识。java结课意味着接下来能够安心复习期末和准备app了。线程