我,算法渣渣,打钱。
停了好长一段时间算法学习了,上个学期学完数据结构以后,学的时候还是清晰的,写也会写一点,但是现在,连图的基本构造我都忘得一干二净了。今天又开始看视频,算法的学习是打算视频讲一个点,我听完之后找一些题目做来加固训练这样子。今天看的是关于图的基本构造,以及深度和广度优先搜索算法和拓扑排序。
这是我根据视频写(按照记忆记下来)的算法,我觉得还是要记录一下,才能加深我的印象。
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;
}
}