图
存储方式:邻接矩阵、邻接表。(十字链表、邻接多重表,省空间但不常用)
类型:有向图、无向图
指定一种适合自己的存储方式,将各种表达方式转成自己熟悉的存储方式。
(如万物转邻接矩阵!)
下面是适用较广的模板
public class Graph{
public HashMap<Integer, Node>nodes; //点集 编号+实际结构
public HashSet<Edge> edges; //边集
public Graph(){
nodes=new HashMap<>();
edges=new HashSet<>();
}
}
public class Node{
public int value;
public int in;
public int out;
public ArrayList<Node> nexts; //直接邻居 edges连向的结点
public ArrayList<Edge> edges; //从当前结点出发的边
public Node(int value){
this.value=value;
in=0;
out=0;
nexts=new ArrayList<>();
edges=new ArrayList<>();
}
}
public class Edge{
public int weight;
public Node from;
public Node to;
public Node(int weight,Node from,Node to){
this.weight=weight;
this.from=from;
this.to=to;
}
}
BFS
队列+集合,队列实现BFS,集合实现不重复
public void BFS(Node node){
if(node==null) return ;
Queue<Node> queue=new LinkList<>();
HashSet<Node> set= new HashSet<>();
queue.add(node);
set.add(node);
while(!queue.IsEmpty()){
Node cur=queue.poll();
process(cur);
for(Node next:cur.nexts){
//直接邻居未被访问过
if(!set.contains(next)){
queue.add(next);
set.add(next);
}
}
}
}
DFS
public void DFS(Node node){
if(node==null) return ;
//路径在栈内,弹出访问下一结点后需要压回
Stack<Node> stack=new LinkList<>();
HashSet<Node> set= new HashSet<>();
stack.push(node);
set.add(node);
process(node); //处理头
while(!stack.IsEmpty()){
Node cur=stack.pop();
for(Node next:cur.nexts){
//直接邻居未被访问过
if(!set.contains(next)){
//先压自己再压邻居,注册邻居
stack.push(cur);
stack.push(next);
set.add(next);
process(next);//处理邻居
break;
}
}
}
}
拓扑排序
找入度(in)为0的点
public static List<Node> sort(Graph graph){
//key 某个node value剩余入度
HashMap<Node, Integer> inMap=new HashMap<>();
//入度为0进队列
Queue<Node> zeroInQueue =new LinkedList<>();
for(Node node:graph.nodes.values()){
//nodes为ArrayList,values()方法获取值便于遍历
inMap.put(node,node.in);
if(node.in==0){
zeroInQueue.add(node);
}
}
//res 收集排序结果
List<Node> res=new ArrayList<>();
while(!zeroInQueue.isEmpty()){
Node cur=zeroInQueue.poll();
res.add(cur);
//消除已排序点的影响
for(Node next: cur.nexts){
inMap.put(next,inMap.get(next)-1);
if(inMap.get(next)==0){
zeroInQueue.add(next);
}
}
}
return res;
}
k算法
无向图找最小生成树
边的角度出发,排序边,加入新边的时候判断是否成环(一群与一群)。
重点在于怎么判断成环,可用并查集
p算法
无向图找最小生成树
从点的角度出发,维护一个边集合(小根堆 ),每加入一个新结点,将新边加入集合,选出最小且不成环(哈希表即可,只涉及一个与一群)的边,加入再新结点,直至结点全部加入。
迪杰斯特拉
边无负权值 单源最短路径
维护一个数组,表示源点到其他点的最短路径,每次选中其中最短路径的点(选过不再选择),源点经过该选择点到其余未选择点是否存在更短的路径,有则更新。
可用小根堆优化找最短且方便更新堆,需要手写,因为更新路径时结点不一定是堆顶,需要map快速访问到结点在堆的位置。