超级容易理解的图的遍历和拓扑排序

之前我们使用了对象结点的方式表达了树的模型,在接下来图的的学习中,我们有非常多的不同的方式来表达图的模型,比如邻接表,邻接矩阵,十字链表,邻接多重表等等。为了方便学习图的思想,我们统一使用一种方式来对图进行表达,在以后遇到不同的表达方式时直接转换即可。

public class Graph{
public HashMap <Integer,Node>nodes;
public HashSet <Edge>edges;
public Graph (){
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
public class Node{
int in;
int out;
int value;
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 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();
sout(cur.value);
for(Node next:cur.nexts){
if(!set.contains(nexts)){
set.add(next);
queue.add(next);}}}}

图的深度优先遍历

利用stack实现。从原点开始,把结点按照深度放入栈,然后弹出;每弹出一个点把该点下一个未进栈的邻接点入栈,往下直到栈空。

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);
sout(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);
sout(next.value);
break;
}
}
}
}

拓扑排序

在一个有向图中,首先弹出没有入度的点,并减去该点对图的影响,再弹出下一个没有入度的点,循环往复。

public static List<Node> sortedToplogy(Graph graph){
HashMap<Node,Integer> inMap=new HashMap<>();//某个结点的剩余入读
Queue<Node> zeroInQueue = new LinkedList<>();//入度为零才能进这个队
for(Node node:graph.nodes.values()){//将原始图数据存进inMap,同时让in=0的直接入队
inMap.put(node,node.in);
if(node.in==0)zetoInQueue.add(node);
}
List<Node> result=new ArrayList<>();
while(!zeroInQueue.isEmpty()){
Node cur = zeroInQueue.poll();
result.add(cur);
for(Node next:cur.nexts){
inMap.put(next,inMap.get(next)-1);
if(inMap.get(next)==0)zeroInQueue.add(next)
}
}
return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值