我,算法渣渣,打钱。
停了好长一段时间算法学习了,上个学期学完数据结构以后,学的时候还是清晰的,写也会写一点,但是现在,连图的基本构造我都忘得一干二净了。今天又开始看视频,算法的学习是打算视频讲一个点,我听完之后找一些题目做来加固训练这样子。今天看的是关于图的基本构造,以及深度和广度优先搜索算法和拓扑排序。
这是我根据视频写(按照记忆记下来)的算法,我觉得还是要记录一下,才能加深我的印象。
1.首先是图的基本结构,点,边。
ackage graph; import java.util.ArrayList; public class Node { public int value;//权值 public int in;//入度 public int out;//出度 public ArrayList<Node> nodes;//点集 public ArrayList<Edge> edges;//边集 public Node(){ this.value = 0; this.in = 0; this.out = 0; this.nodes = new ArrayList<>(); this.edges = new ArrayList<>(); } }
public class Edge {//边 public Node from;//起点 public Node to;//终点 public int weight;//权值 public Edge(Node from,Node to,int weight){ this.from = from; this.to = to; this.weight = weight; } public Edge(){ this.from = new Node(); this.to = new Node(); this.weight = 0; } }
public class Graph {//图 public HashMap<Integer, Node> nodes;//图的点集 public HashSet<Edge> edges;//图的边集 public Graph(){ this.nodes = new HashMap<>(); this.edges = new HashSet<>(); } }
以上是图的全部结构,下面是广度和深度优先遍历算法
广度优先遍历:①从图中v0点开始遍历 ②依次遍历与v0相邻的未访问的节点 ③重复步骤2,直到所有节点被访问
public class BFS { public void bfs(graph.Node node){ if(node == null){ return; } Queue<Node> queue = new LinkedList<>(); HashSet<Node> map = new HashSet<>();//此map用来记录已经访问过的节点,避免重复访问 // for(graph.Node node2 : node.nodes){ // if(!map.contains(node2)){ // map.add(node2); // queue.add(node2); // System.out.println(node2.value); // } // queue.add(node); map.add(node); while(!queue.isEmpty()){ Node get = queue.poll(); System.out.println(get.value); for(Node node2 : get.nodes){ if(!map.contains(node2)){ map.add(node2); queue.add(node2); } } } } }
深度优先遍历:①以v0节点开始遍历 ②从v0中选取一个与其相连的点v1进行访问,并从v1中选取一个与v1相连的点进行访问,一直下去直到此路径没有节点可以访问,再退回到v0选取另外与其相连的点。③重复②步骤,直到所有的点都被访问。
public class DFS { public void dfs(Node node){ if(node == null){ return; } Stack<Node> stack = new Stack<>(); HashSet<Node> set = new HashSet<>();//同样是为了标识已访问的节点,防止重复访问 stack.add(node); set.add(node); while(!stack.isEmpty()){ Node cur = stack.pop(); for(Node next : cur.nodes){ if(!set.contains(next)){ stack.push(cur);//重复插入,确保这个节点的其他岔路可以走,直到没有岔路才拿出来 stack.push(next); set.add(next); System.out.println(next.value); break; } } } } }
拓扑排序:适用于有向无环图
public List<Node> topoSort(Graph graph){ //1.把所有入度点情况存到map //2.把所有入度点为0的node存到queue //3.从入度点为0的node出发,依次把点放入result。 //4.当node被选取,则与其相连的点的入度都要-1,此时继续重复步骤2,3,4。 Map<Node,Integer> inMap = new HashMap<Node, Integer>(); Queue<Node> zeroInNode = new LinkedList<Node>(); List<Node> result = new ArrayList<Node>(); for(Node node : graph.nodes.values()){//这里要取values(),因为这个nodes()是一个hashMap,我们要取得是它里面存放的value,即node inMap.put(node, node.in); if(node.in == 0){ zeroInNode.add(node); } } while(!zeroInNode.isEmpty()){ Node cur = zeroInNode.poll(); result.add(cur); for(Node next : cur.nodes){ inMap.put(next,inMap.get(next)-1);//注意这里不是next.in-1,不可以改变next if(inMap.get(next) == 0){ zeroInNode.add(next); } } } return result; } }