【复习笔记】手敲经常忘记的关于图的几个算法

来源:互联网 发布:mac 更改用户文件夹 编辑:程序博客网 时间:2024/05/01 05:01

BFS 

类似于树的层次遍历,用队列依次存储节点的孩子节点然后做出队操作。

唯一不同的是树不存在环,但图存在环,所以遍历图的时候需要设置一个访问矩阵,来记录一个节点是否已经被遍历过。

public static void BFS(int [][] graph, int sx){int dim = graph.length;boolean [] visited = new boolean [dim];LinkedList<Integer> queue = new LinkedList<Integer>();for(int i = 0; i < dim; ++i)visited[i] = false;queue.add(sx);while(!queue.isEmpty()){int node = queue.remove(0);if(!visited[node])System.out.print(node + 1 + " ");visited[node] = true;for(int i = 0; i < dim; ++i){if(graph[node][i] == 1 && !visited[i])queue.add(i);}}}

测试数据:邻接矩阵

int [][] graph ={{0,1,0,0,0,0,0,0},{1,0,1,1,0,0,0,0},{0,1,0,0,1,1,0,0},{0,1,0,0,1,0,1,0},{0,0,1,1,0,0,0,1},{0,0,1,0,0,0,1,0},{0,0,0,1,0,1,0,0},{0,0,0,0,1,0,0,0}};

求以节点1为起点的遍历结果:1 2 3 4 5 6 7 8


DFS 

类似于二叉树的前序遍历,一直递归到某一节点立即进行遍历,然后选一个孩子继续递归。

DFS的遍历结果不是唯一的。同样需要一个记录矩阵。

public static void DFS(int [][] graph, int sx){int dim = graph.length;boolean [] visited = new boolean [dim];for(int i = 0; i < dim; ++i)visited[i] = false;System.out.print(sx + 1 + " ");visited[sx] = true;for(int i = 0; i < dim; ++i){if(!visited[i] && graph[sx][i] == 1){DFSnode(graph, i, visited);}}}public static void DFSnode(int [][] graph, int node, boolean [] visited){int dim = graph.length;System.out.print(node + 1 + " ");visited[node] = true;for(int i = 0; i < dim; ++i){if(!visited[i] && graph[node][i] == 1){DFSnode(graph, i, visited);}}}


测试数据同BSF,测试以1为起点的遍历结果:1 2 3 5 4 7 6 8 

迪杰斯特拉算法

痛心疾首,华为FX计划有一道编程题考点就是dijstra思想,但是忘记了,着重复习一下:


1首先取一个起点,设置一个数组dist,记录起点到各个节点的距离,无法到达的设置为maxint。

2然后选一个dist里面的最小值,把这个节点标记为已选(加入已选节点集合),然后重新计算dist:

3如果其他节点的dist能因为加入此次的已选节点变小,则更新dist(以此次已选节点为辅助节点,曲线救国)

4再次从dist数组里挑选最小值,回到第二步。


public static void dijstra(int [][] gweight, int start, int end){int dim = gweight.length;int [] father = new int [dim];int [] dist = new int [dim];HashSet<Integer> hash = new HashSet<Integer>();int maxint = Integer.MAX_VALUE;for(int i = 0; i < dim; ++i)dist[i] = maxint;int pickVer = start;int min = 0;hash.add(pickVer);while(pickVer != end){for(int i = 0; i < dim; ++i){if(gweight[pickVer][i] + min < dist[i] &&gweight[pickVer][i] != 0 &&!hash.contains(i)){dist[i] = gweight[pickVer][i] + min;father[i] = pickVer;}}int temp = maxint; int minindex = 0;for(int i = 0; i < dim; ++i){if(dist[i] < temp && !hash.contains(i)){temp = dist[i];minindex = i;}}min = temp;pickVer = minindex;hash.add(pickVer);}System.out.println("由节点 " + (start + 1) + " 至节点 " + (end + 1) + " 的最短路径长:"+dist[end]);System.out.print("节点路径为:" + (end + 1));for(int i = end; i != start;){System.out.print("<-" + (father[i] + 1));i = father[i];}}


测试数据:

int [][] weight ={{0,3,0,0,0,0,0,0},{3,0,4,7,0,0,0,0},{0,4,0,0,6,1,0,0},{0,7,0,0,1,0,5,0},{0,0,6,1,0,0,0,2},{0,0,1,0,0,0,8,0},{0,0,0,5,0,8,0,0},{0,0,0,0,2,0,0,0}};

结果:由节点 1 至节点 7 的最短路径长:15
   节点路径为:7<-4<-2<-1

代码中father数组记录了每个节点的上一个节点,用来记录最短路经过的节点路径。

原创粉丝点击