图的邻接矩阵表示
A[i,j]为1表示节点i到j有变相连,0表示无边相连.
上图表示为:
如果边具有权则用权表示,无边相连可用无穷表示.i=j时用0表示.
无向图为对称矩阵.
邻接表表示
对于图中的每个顶点,把所有邻接于顶点的节点链成一个单链表.链表节点至少包含两个域:一个为邻接点域,指示在图中的位序,一个为链域,指示下一个节点.
用代码表示为:
LinkedList<Node> graph=new LinkedList<Node>();
Node v0=new Node(0, null),v1=new Node(1, null),v2=new Node(2, null),v3=new Node(3, null);
v0.next=v1;v1.next=v2;v2.next=v3;
graph.add(v0);
v0=new Node(0, null);v1=new Node(1, null);v2=new Node(2, null);
v1.next=v0;v1.next=v2;
graph.add(v1);
v0=new Node(0, null);v1=new Node(1, null);v2=new Node(2, null);v3=new Node(3, null);
v2.next=v0;v0.next=v1;v1.next=v3;
graph.add(v2);
v0=new Node(0, null);v2=new Node(2, null);v3=new Node(3, null);
v3.next=v0;v0.next=v2;
graph.add(v3);
class Node{
public Node(int val,Node next) {
this.val=val;
this.next=next;
}
int val;
Node next;
}
BFS
先访问父节点,再访问其所有子节点.
使用队列,节点入队,出队时将其所有子节点入队;用数组保存每个节点是否被访问过.
public class BFS {
public static void bfs(List<Node> graph) {//使用队列,节点入队,出队时将其所有子节点入队;用数组保存每个节点是否被访问过
if(graph==null||graph.size()==0) return;
boolean[] visited=new boolean[graph.size()];
Queue<Node> queue=new LinkedList<Node>();
queue.add(graph.get(0));
while (!queue.isEmpty()) {
Node t=queue.poll();
System.out.println(t.val);
visited[t.val]=true;
while (t.next!=null && !visited[t.next.val]) { //未访问过的子节点入队
queue.add(t.next);
visited[t.next.val]=true; //入队后相当于被访问过了,否则可能重复入队
t=t.next;
}
}
}
public static void main(String[] args) {
LinkedList<Node> graph=new LinkedList<Node>();
Node v0=new Node(0, null),v1=new Node(1, null),v2=new Node(2, null),v3=new Node(3, null);
v0.next=v1;v1.next=v2;v2.next=v3;
graph.add(v0);
v0=new Node(0, null);v1=new Node(1, null);v2=new Node(2, null);
v1.next=v0;v1.next=v2;
graph.add(v1);
v0=new Node(0, null);v1=new Node(1, null);v2=new Node(2, null);v3=new Node(3, null);
v2.next=v0;v0.next=v1;v1.next=v3;
graph.add(v2);
v0=new Node(0, null);v2=new Node(2, null);v3=new Node(3, null);
v3.next=v0;v0.next=v2;
graph.add(v3);
bfs(graph);
}
}
class Node{
public Node(int val,Node next) {
this.val=val;
this.next=next;
}
int val;
Node next;
}
DFS
先访问父节点,再访问其中一个子节点,再访问一个孙子节点……
使用回溯法,用数组记录节点是否被访问过。
public class DFS {
static boolean[] visited;
public static void dfs(List<Node> graph) {
if (graph==null||graph.size()==0) return;
visited=new boolean[graph.size()];
backtrap(graph, graph.get(0));
}
public static void backtrap(List<Node> graph,Node node) {
if(!visited[node.val]) {
System.out.println(node.val);
visited[node.val]=true;
}
while(node.next!=null) {
node=node.next;
if(!visited[node.val])
backtrap(graph, graph.get(node.val)); //递归地访问子节点
}
}
public static void main(String[] args) {
LinkedList<Node> graph=new LinkedList<Node>();
Node v0=new Node(0, null),v1=new Node(1, null),v2=new Node(2, null),v3=new Node(3, null);
v0.next=v1;v1.next=v2;v2.next=v3;
graph.add(v0);
v0=new Node(0, null);v1=new Node(1, null);v2=new Node(2, null);
v1.next=v0;v1.next=v2;
graph.add(v1);
v0=new Node(0, null);v1=new Node(1, null);v2=new Node(2, null);v3=new Node(3, null);
v2.next=v0;v0.next=v1;v1.next=v3;
graph.add(v2);
v0=new Node(0, null);v2=new Node(2, null);v3=new Node(3, null);
v3.next=v0;v0.next=v2;
graph.add(v3);
dfs(graph);
}
}
class Node{
public Node(int val,Node next) {
this.val=val;
this.next=next;
}
int val;
Node next;
}