十字链表:十字链表(Orthogonal List)是有向图的另外一种链式存储结构。该结构能够当作是将有向图的邻接表和逆邻接表结合起来获得的
html
BFS算法之因此叫作广度优先搜索,是由于它始终将已发现的顶点和未发现的之间的边界,沿其广度方向向外扩展。亦即,算法首先会发现和s距离为k的全部顶点,而后才会发现和s距离为k+1的其余顶点。同深度优先搜索相反,BFS宽度优先搜索每次选择深度最浅的节点优先扩展。而且当问题有解时,宽度优先算法必定可以找到解,而且在单位耗散时间的状况下,能够保证找到最优解。java
图的最小生成树:个有n个结点的连通图的生成树是原图的极小连通子图,且包含原图中的全部n个结点,而且有保持图连通的权值和边最小git
问题1:如何用Java具体实现深度遍历算法
import java.util.Stack; public class Graph { //节点个数 private static int number = 8; //创立访问标志数组的布尔型数组 private boolean[] flag; //创立要遍历节点的数组 private int[] num= {1,2,3,4,5,6,7,8}; //创立这几个数字的邻接矩阵 private int[][] edges = { {0, 1, 1, 0, 0, 0, 0, 0}, {1, 0, 0, 1, 1, 0, 0, 0}, {1, 0, 0, 0, 0, 1, 1, 0}, {0, 1, 0, 0, 0, 0, 0, 1}, {0, 1, 0, 0, 0, 0, 0, 1}, {0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0}, }; void DFSTraverse() { //设置一个和数字个数同等大小的布尔数组 flag = new boolean[number] ; //从顶点开始,实现深度遍历 for (int i = 0; i < number; i++) { if (flag[i] == false) { // 若是当前顶点没有被访问,进入DFS DFS(i); } } } //完成一次遍历,直到后面无链接节点 void DFS(int i) { // 标记第num[i]个节点被访问 flag[i] = true; //将该节点打印 System.out.print(num[i] + " "); //寻找与num[i]节点相连的下一个访问节点 for (int j = 0; j < number; j++) { //从标志数组第0位开始顺序查找,若是这一点未被访问,且与第num[i]个节点相连 if (flag[j] == false && edges[i][j] == 1) { //递归 DFS(j); } } } void DFS_Map(){ flag = new boolean[number]; Stack<Integer> stack =new Stack<Integer>(); for(int i=0;i<number;i++){ if(flag[i]==false){ flag[i]=true; System.out.print(num[i]+" "); stack.push(i); } while(!stack.isEmpty()){ int k = stack.pop(); for(int j=0;j<number;j++){ if(edges[k][j]==1&&flag[j]==false){ flag[j]=true; System.out.print(num[j]+" "); stack.push(j); break; } } } } } //测试类 public static void main(String[] args) { Graph graph = new Graph(); System.out.println("DFS递归:"); graph.DFSTraverse(); System.out.println(); System.out.println("DFS非递归:"); graph.DFS_Map(); } }
public class GraphKruskal { //定义Edge型数组 private Edge[] edges; private int edgeSize; public GraphKruskal(int edgeSize) { //参数个数 this.edgeSize = edgeSize; edges = new Edge[edgeSize]; createEdgeKruskal(); } //建立边的集合,从小到大 private void createEdgeKruskal() { Edge edge0 = new Edge(1, 3, 1); Edge edge1 = new Edge(4, 6, 2); Edge edge2 = new Edge(2, 5, 3); Edge edge3 = new Edge(3, 6, 4); Edge edge4 = new Edge(2, 3, 5); Edge edge5 = new Edge(3, 4, 5); Edge edge6 = new Edge(1, 4, 5); Edge edge7 = new Edge(3, 5, 6); Edge edge8 = new Edge(1, 2, 6); Edge edge9 = new Edge(5, 6, 6); edges[0] = edge0; edges[1] = edge1; edges[2] = edge2; edges[3] = edge3; edges[4] = edge4; edges[5] = edge5; edges[6] = edge6; edges[7] = edge7; edges[8] = edge8; edges[9] = edge9; } //kruskal算法建立最小生成树 public void createMinSpanTreeKruskal() { // 定义一个一维数组,下标为连线的起点,值为连线的终点 int[] parent = new int[edgeSize]; for (int i = 0; i < edgeSize; i++) { parent[i] = 0; } int sum = 0; //将数组中每个元素都赋给左边 for (Edge edge : edges) { // 找到起点和终点在临时连线数组中的最后链接点,核心 int start = find(parent, edge.start); int end = find(parent, edge.end); // 经过起点和终点找到的最后链接点是否为同一个点,是则产生回环 if (start != end) { // 没有产生回环则将临时数组中,起点为下标,终点为值 parent[start] = end; System.out.println("访问到了节点:{" + start + "," + end + "},权值:" + edge.weight); sum += edge.weight; } } System.out.println("最小生成树的权值总和:" + sum); } // 获取集合的最后节点 private int find(int parent[], int index) { while (parent[index] > 0) { index = parent[index]; } return index; } //链接顶点的边 class Edge { private int start; private int end; private int weight; public Edge(int start, int end, int weight) { this.start = start; this.end = end; this.weight = weight; } } public static void main(String[] args) { GraphKruskal graphKruskal = new GraphKruskal(10); graphKruskal.createMinSpanTreeKruskal(); } }
public class Dijkstra { public static final int M = 10000; // 表明正无穷 public static void main(String[] args) { // 二维数组每一行分别是 A、B、C、D、E 各点到其他点的距离, // A -> A 距离为0, 常量M 为正无穷 int[][] weight1 = { {0, 13, 8, M, 30, M, 32}, {M, 0, M, M, M, 9, 7 }, {M, M, 0, 5, M, M , M}, {M, M, M, 0, 6, M , M}, {M, M, M, M, 0, 2 , M}, {M, M, M, M, M, 0 ,17}, {M, M, M, M, M, M , 0}, }; int start = 0; int[] shortPath = dijkstra(weight1, start); for (int i = 0; i < shortPath.length; i++) System.out.println("从" + start + "出发到" + i + "的最短距离为:" + shortPath[i]); } public static int[] dijkstra(int[][] weight, int start) { // 接受一个有向图的权重矩阵,和一个起点编号start(从0编号,顶点存在数组中) // 返回一个int[] 数组,表示从start到它的最短路径长度 int n = weight.length; // 顶点个数 int[] shortPath = new int[n]; // 保存start到其余各点的最短路径 String[] path = new String[n]; // 保存start到其余各点最短路径的字符串表示 for (int i = 0; i < n; i++) path[i] = new String(start + "-->" + i); int[] visited = new int[n]; // 标记当前该顶点的最短路径是否已经求出,1表示已求出 // 初始化,第一个顶点已经求出 shortPath[start] = 0; visited[start] = 1; for (int count = 1; count < n; count++) { // 要加入n-1个顶点 int k = -1; // 选出一个距离初始顶点start最近的未标记顶点 int dmin = Integer.MAX_VALUE; for (int i = 0; i < n; i++) { if (visited[i] == 0 && weight[start][i] < dmin) { dmin = weight[start][i]; k = i; } } // 将新选出的顶点标记为已求出最短路径,且到start的最短路径就是dmin shortPath[k] = dmin; visited[k] = 1; // 以k为中间点,修正从start到未访问各点的距离 for (int i = 0; i < n; i++) { //若是 '起始点到当前点距离' + '当前点到某点距离' < '起始点到某点距离', 则更新 if (visited[i] == 0 && weight[start][k] + weight[k][i] < weight[start][i]) { weight[start][i] = weight[start][k] + weight[k][i]; path[i] = path[k] + "-->" + i; } } } for (int i = 0; i < n; i++) { System.out.println("从" + start + "出发到" + i + "的最短路径为:" + path[i]); } System.out.println("====================================="); return shortPath; } }
(数组
)网络
教材学习中的问题和解决过程, 一个问题加1分数据结构
代码调试中的问题和解决过程, 一个问题加1分学习
基于评分标准,我给本博客打分:18分测试
参考示例this
数据结构学习也算到尾声了,图这一章算法比较丰富,须要咱们花费时间逐一认真理解,并落实到代码实现。只有这样,咱们对数据结构的理解才能真正融会贯通
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 | |
第五周 | 1600/2900 | 2/11 | 20/110 | |
第六周 | 981 /3881 | 2/12 | 25/135 | |
第七周 | 1700/5518 | 3/15 | 45/180 | |
第八周 | 700/6200 | 2/17 | 20/200 | |
第九周 | 4300/10500 | 2/19 | 30/230 | |
第十周 | 2064/12564 | 1/20 | 30/260 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进本身的计划能力。这个工做学习中很重要,也颇有用。
耗时估计的公式:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
计划学习时间:30小时
实际学习时间:30小时
改进状况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)