图的遍历总结模板
图的存储方式
邻接表
邻接矩阵
图的模板代码
package com.itcast.Graphy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class tu1 {
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;
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 Edge(int weight,Node from ,Node to){
this.weight=weight;
this.from=from;
this.to=to;
}
}
}
实例:
package com.itcast.Graphy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class tu2 {
public static class Graph{
//图是有点集和边集
public HashMap<Integer, Node> nodes;
public HashSet<Edge> edges;
public Graph(){
nodes=new HashMap<>();
edges=new HashSet<>();
}
}
public static class Node{
public int value;
public int in;
public int out;
public ArrayList<Node> nexts;
public ArrayList<Edge> edges;
public Node(int value){
this.value=value;
in=0;
out=0;
nexts=new ArrayList<>();
edges=new ArrayList<>();
}
}
public static class Edge{
public int weight;
public Node from;
public Node to;
public Edge(int weight, Node from , Node to){
this.weight=weight;
this.from=from;
this.to=to;
}
}
public static Graph creat(Integer [][] matrix){
Graph graph= new Graph();
for(int i=0;i<matrix.length;i++){
Integer from=matrix[0][0];
Integer to=matrix[0][1];
Integer weight=matrix[0][2];
if(!graph.nodes.containsKey(from)){
graph.nodes.put(from,new Node(from));
}
if(!graph.nodes.containsKey(to)){
graph.nodes.put(to,new Node(to));
}
Node fromNode=graph.nodes.get(from);
Node toNode=graph.nodes.get(to);
Edge newEdge=new Edge(weight,fromNode,toNode);
fromNode.nexts.add(toNode);
fromNode.out++;
toNode.in++;
fromNode.edges.add(newEdge);
graph.edges.add(newEdge);
}
return graph;
}
}
宽度优先遍历
思想:
- 利用队列实现
- 从源节点开始按照宽度进队列,然后弹出
- 每弹出一个点,把该节点所有没有进过队列的邻接点放入队列
- 直到队列变空
代码
package com.itcast.Graphy;
import java.util.*;
public class bfs {
public class Node{
public int value;
public int in;
public int out;
public ArrayList< Node> nexts;
public Node(int value){
this.value=value;
in=0;
out=0;
nexts=new ArrayList<>();
}
}
public static void BFS(Node node){
if(node==null){
return;
}
Queue<Node> queue=new LinkedList<>();
HashSet<Node> set=new HashSet<>();
queue.add(node);
set.add(node);
while(!queue.isEmpty()){
Node cur=queue.poll();
System.out.println(cur.value);
for(Node next:cur.nexts){
if(!set.contains(next)){
set.add(next);
queue.add(next);
}
}
}
}
}
广度优先遍历
思想:
- 利用栈实现
- 从源节点开始把节点按照深度放入栈,然后弹出
- 每弹出一个点,把该节点下一个没有进入过栈的邻接点放入栈
- 直到栈变空
package com.itcast.Graphy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Stack;
public class dfs {
public class Node{
public int value;
public int in;
public int out;
public ArrayList< Node> nexts;
public Node(int value){
this.value=value;
in=0;
out=0;
nexts=new ArrayList<>();
}
}
public static void DFS(Node node){
if(node==null){
return ;
}
Stack<Node> stack=new Stack<>();
HashSet<Node> set=new HashSet<>();
stack.add(node);
set.add(node);
System.out.println(node.value);
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);
System.out.println(next.value);
break;
}
}
}
}
}
拓扑排序算法
适用范围:要求有向图,且有入度为的节点,且没有环
排序结果:A,B,C,D
找到入度为0的节点,然后排好序,删除该节点对其它节点的影响,
package com.itcast.Graphy;
import java.util.*;
public class TopLogSort {
public static class Graph{
public HashMap<Integer,Node> nodes;
public HashSet<Edge> edges;
public Graph(){
nodes=new HashMap<Integer, Node>();
edges=new HashSet<Edge>();
}
}
public static class Node{
public int value;
public int in;
public int out;
public ArrayList<Node> nexts;
public ArrayList<Edge> edges;
public Node(int value){
this.value=value;
in=0;
out=0;
nexts=new ArrayList<>();
edges=new ArrayList<Edge>();
}
}
public static class Edge{
public int weight;
public Node from;
public Node to;
public Edge(int weight,Node from,Node to){
this.weight=weight;
this.from=from;
this.to=to;
}
}
public static List<Node> sort(Graph graph) {
//key:某一个node
//value:剩余的入度
HashMap<Node, Integer> inMAP = new HashMap<>();
//入度为0的节点才能进入队列
Queue<Node> zeroqueue=new LinkedList<>();
for(Node node:graph.nodes.values()){
inMAP.put(node,node.in);
if(node.in==0){
zeroqueue.add(node);
}
}
//拓扑排序结果,依次加入resul
List<Node> result=new ArrayList<>();
while(!zeroqueue.isEmpty()){
Node cur=zeroqueue.poll();
result.add(cur);
for(Node next:cur.nexts){
inMAP.put(next,inMAP.get(next)-1);
if(inMAP.get(next)==0){
zeroqueue.add(next);
}
}
}
return result;
}
}
Kruskal
适用范围:要求无向图
最小生成树:
从最小的边开始考虑,如果加上没环,就要,有环就不要
package com.itcast.Graphy;
import java.util.*;
public class kruskal {
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;
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 Edge(int weight, Node from , Node to){
this.weight=weight;
this.from=from;
this.to=to;
}
}
public static class Mysets{
public HashMap<Node,List<Node>> setMap;
public Mysets(List<Node> nodes){
for(Node cur:nodes){
List<Node> set=new ArrayList<Node>();
set.add(cur);
setMap.put(cur,set);
}
}
public boolean ISame(Node from,Node to){
List<Node> fromSet=setMap.get(from);
List<Node> toSet=setMap.get(to);
return toSet==fromSet;//比较两个的内存地址,判断两个是不是同一个集合
}
public void union(Node from,Node to){
List<Node> fromSet=setMap.get(from);
List<Node> toSet=setMap.get(to);
for(Node toNode:toSet){
fromSet.add(toNode);
setMap.put(toNode,fromSet);
}
}
}
public static class Edgecomparator implements Comparator<Edge>{
@Override
public int compare(Edge o1, Edge o2) {
return o1.weight-o2.weight;
}
}
public static Set<Edge> kruskalprocess(Graph graph){
//伪码
Mysets mysets=new Mysets();
Mysets.Mysets(graph.nodes.values());
PriorityQueue<Edge> priorityQueue=new PriorityQueue<>(new Edgecomparator());
for(Edge edge:graph.edges){
priorityQueue.add(edge);
}
Set<Edge> result=new HashSet<>();
while(!priorityQueue.isEmpty()){
Edge cur=priorityQueue.poll();
//判断两个集合相同不,
//合并
}
}
}
prim算法:
要求:无向图
package com.itcast.Graphy;
import java.util.*;
public class Prim {
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;
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 Edge(int weight, Node from , Node to){
this.weight=weight;
this.from=from;
this.to=to;
}
}
public static class Edgecomparator implements Comparator< Edge> {
@Override
public int compare( Edge o1, Edge o2) {
return o1.weight-o2.weight;
}
}
public static Set<Edge> prim(Graph graph){
//解锁的边进入小根堆
PriorityQueue<Edge> priorityQueue=new PriorityQueue<>(new Edgecomparator());
HashSet<Node> set=new HashSet<>();
Set<Edge> result=new HashSet<>();//依次挑选的边放入result
for(Node node:graph.nodes.values()){
if(!set.contains(node)){
set.add(node);
for(Edge edge:node.edges){
priorityQueue.add(edge);//由一个点解所有相连的边
}
while(!priorityQueue.isEmpty()){
Edge edge=priorityQueue.poll();//弹出解锁边中,最小的边
Node toNode=edge.to;//可能的一个新的点
if(!set.contains(toNode)){//不含有的时候就是新的点
set.add(toNode);
result.add(edge);
for(Edge nextedge:toNode.edges){
priorityQueue.add(nextedge);
}
}
}
}
}
return result;
}
}
Dijkstra算法
适用发范围:没有权值为负数的边
package com.itcast.Graphy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
public class Dijkstra {
public static class Graph{
//图是有点集和边集
public HashMap<Integer, Node> nodes;
public HashSet< Edge> edges;
public Graph(){
nodes=new HashMap<>();
edges=new HashSet<>();
}
}
public static class Node{
public int value;
public int in;
public int out;
public ArrayList< Node> nexts;
public ArrayList< Edge> edges;
public Node(int value){
this.value=value;
in=0;
out=0;
nexts=new ArrayList<>();
edges=new ArrayList<>();
}
}
public static class Edge{
public int weight;
public Node from;
public Node to;
public Edge(int weight, Node from , Node to){
this.weight=weight;
this.from=from;
this.to=to;
}
}
//从某个点出发,到各点的最短距离
public static HashMap<Node,Integer> Dijkstra1(Node form){
//从from出发到所有点的最短距离
//key:从from出发到达可以
//value:从form出发到达key的最小距离
//如果表中没有T的记录,表示从form出发到达T的距离为正无穷
HashMap<Node, Integer> distanceMap=new HashMap<>();
distanceMap.put(form, 0);
//已经求过距离的点,存在selectedNodes中,再也不碰
HashSet<Node> selectedNodes=new HashSet<>();
//遍历distanceMap,把除去selectedNodes中,所有距离最小的点取出来。
Node miNode=getMinDistanceAndUnselectedNodes(distanceMap,selectedNodes);
while(miNode!=null){
int distance=distanceMap.get(miNode);
for(Edge edge:miNode.edges){
Node toNode=edge.to;
//如果表中没有这个结点,就添加结点和距离
//有,则更新结点最短距离
if (!distanceMap.containsKey(toNode)) {
distanceMap.put(toNode, distance+edge.weight);
}else {
distanceMap.put(toNode, Math.min(distanceMap.get(toNode), distance+edge.weight));
}
}
selectedNodes.add(miNode);
miNode=getMinDistanceAndUnselectedNodes(distanceMap, selectedNodes);
}
return distanceMap;
}
public static Node getMinDistanceAndUnselectedNodes(
HashMap<Node, Integer>distanceMap,
HashSet<Node>touchedNodes){//touchedNodes就是我们之前的selectedNodes
Node miNode=null;
int mindistance=Integer.MAX_VALUE;
for(Entry<Node, Integer> entry:distanceMap.entrySet()){
Node node=entry.getKey();
int distance=entry.getValue();
if(!touchedNodes.contains(node)&&distance<mindistance){
miNode=node;
mindistance=distance;
}
}
return miNode;
}
public static void main(String[] args) {
}
}