Lecture 24: Graphs II: Graph Traversal Implementations |cs61b 2019

Lecture 24: Graphs II: Graph Traversal Implementations

  1. BreadthFirstPaths
  2. Graph API
  3. Graph Representations and Graph Algorithm Runtimes
  4. Graph Traversal Runtimes
  5. Layers of Abstraction

Tree and Graph Traversals

Just as there are many tree traversals:

  • Preorder: DBACFEG
  • Inorder: ABCDEFG
  • Postorder: ACBEGFD
  • Level order: DBFACEG
    在这里插入图片描述

graph traversals, given some source:

  • DFS Preorder: 012543678 (dfs calls).
  • DFS Postorder: 347685210 (dfs returns).
  • BFS order: Act in order of distance from s.
  • BFS stands for “breadth first search”.
    • Analogous to “level order”. Search is wide, not deep.
      0 1 24 53 68 7
      在这里插入图片描述

Shortest Paths Challenge

Goal: Given the graph above, find the shortest path from s to all other vertices.

  • Give a general algorithm.
  • Hint: You’ll need to somehow visit vertices in BFS order.
  • Hint #2: You’ll need to use some kind of data structure.
  • Hint #3: Don’t use recursion.

BFS Answer

Breadth First Search.

  • Initialize a queue with a starting vertex s and mark that vertex.
    • A queue is a list that has two operations: enqueue (a.k.a. addLast) and dequeue (a.k.a. removeFirst).
    • Let’s call this the queue our fringe.
  • Repeat until queue is empty:
    • Remove vertex v from the front of the queue.
    • For each unmarked neighbor n of v:
      • Mark n.
      • Set edgeTo[n] = v (and/or distTo[n] = distTo[v] + 1).
      • Add n to end of queue.

A queue is the opposite of a stack. Stack has push (addFirst) and pop (removeFirst)

Do “distTo[n] = distTo[v] + 1” if you want to track distance value

Demo

Graph API und Graph Representations

To Implement our graph algorithms like BreadthFirstPaths and DepthFirstPaths, we need:

  • An API (Application Programming Interface) for graphs.
    • For our purposes today, these are our Graph methods, including their signatures and behaviors.
    • Defines how Graph client programmers must think.
  • An underlying data structure to represent our graphs.

Our choices can have profound implications on:

  • Runtime.
  • Memory usage.
  • Difficulty of implementing various graph algorithms.

Graph API Decision #1: Integer Vertices 给每个点标一个数字代表这个点

Graph API

public class Graph {
  public Graph(int V):               Create empty graph with v vertices
  public void addEdge(int v, int w): add an edge v-w
  Iterable<Integer> adj(int v):      vertices adjacent to v
  int V():                           number of vertices
  int E():                           number of edges

Some features:

  • Number of vertices must be specified in advance.
  • Does not support weights (labels) on nodes or edges.
  • Has no method for getting the number of edges for a vertex (i.e. its degree)

Example client:

/** degree of vertex v in graph G */
public static int degree(Graph G, int v) {
	int degree = 0;
	for (int w : G.adj(v)) {
    	    degree += 1;
    	}
	return degree; }

Print client:

public static void print(Graph G) {
	for (int v = 0; v < G.V(); v += 1) {
 	    for (int w : G.adj(v)) {
    	       System.out.println(v +-+ w);
    	     }
    }
}

Our choice of Graph API has deep implications on the implementation of DepthFirstPaths, BreadthFirstPaths, print, and other graph “clients”.

Graph Representation and Graph Algorithm Runtime

Graph Representations
Graph Representation 1: Adjacency Matrix.

在这里插入图片描述

  • G.adj(2) would return an iterator where we can call next() up to two times
    • next() returns 1
    • next() returns 3
  • Total runtime to iterate over all neighbors of v is Θ(V).
    • Underlying code has to iterate through entire array to handle next() and hasNext() calls.

在这里插入图片描述

在这里插入图片描述

Representation 2: Edge Sets: Collection of all edges.

在这里插入图片描述

Representation 3: Adjacency lists.

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

Runtime of some basic operations for each representation:

在这里插入图片描述

Bare-Bones Undirected Graph Implementation

public class Graph {
	private final int V;  private List<Integer>[] adj;
	
	public Graph(int V) {
    	    this.V = V;
    	    adj = (List<Integer>[]) new ArrayList[V];
    	    for (int v = 0; v < V; v++) {
             adj[v] = new ArrayList<Integer>();
         }
	} 

	public void addEdge(int v, int w) {
         adj[v].add(w);   adj[w].add(v);
	}

	public Iterable<Integer> adj(int v) {
        return adj[v];
	}
}

Graph Traversal Implementations and Runtime

Depth First Search Implementation

  • Common design pattern in graph algorithms: Decouple type from processing algorithm.
    • Create a graph object.
    • Pass the graph to a graph-processing method (or constructor) in a client class.
    • Query the client class for information.\

client class :

public class Paths {
    public Paths(Graph G, int s):    Find all paths from G
    boolean hasPathTo(int v):        is there a path from s to v?
    Iterable<Integer> pathTo(int v): path from s to v (if any)
}

在这里插入图片描述

DepthFirstPaths Demo

Goal: Find a path from s to every other reachable vertex, visiting each vertex at most once. dfs(v) is as follows:

  • Mark v.
  • For each unmarked adjacent vertex w:
    • set edgeTo[w] = v.
    • dfs(w)
code
 public class DepthFirstPaths {
  private boolean[] marked;
  private int[] edgeTo;
  private int s;
 	
  public DepthFirstPaths(Graph G, int s) {
      ...
      dfs(G, s);
  }
  private void dfs(Graph G, int v) {
    marked[v] = true;
    for (int w : G.adj(v)) {
      if (!marked[w]) {
        edgeTo[w] = v;
        dfs(G, w);
      }        	
    } 
  }

  public Iterable<Integer> pathTo(int v) {
    if (!hasPathTo(v)) return null;
    List<Integer> path = new ArrayList<>();
    for (int x = v; x != s; x = edgeTo[x]) {
      path.add(x);
    }
    path.add(s);
    Collections.reverse(path);
    return path;
  }

  public boolean hasPathTo(int v) {
    return marked[v];
  }

    ...
}

marked[v] is true iff v connected to s
edgeTo[v] is previous vertex on path from s to v

java.util.Collections.reverse() method is a java.util.Collections class method. It reverses the order of elements in a list passed as an argument.

Runtime for DepthFirstPaths

在这里插入图片描述

Graph ProblemsGraph Problems

BreadthFirstPaths Implementation

Code:
public class BreadthFirstPaths {
  private boolean[] marked;
  private int[] edgeTo;
  ...
	
  private void bfs(Graph G, int s) {
  Queue<Integer> fringe = 
          new Queue<Integer>();
  fringe.enqueue(s);
  marked[s] = true;
  while (!fringe.isEmpty()) {
    int v = fringe.dequeue();
    for (int w : G.adj(v)) {
      if (!marked[w]) {
        fringe.enqueue(w);
        marked[w] = true;
        edgeTo[w] = v;
      }
    }
  }
}

在这里插入图片描述

Graph Problems
s-t paths
  • Find a path from s to every reachable vertex.

  • Solution:

    • Goal: Find a path from s to every other reachable vertex, visiting each vertex at most once. dfs(v) is as follows:
      • Mark v.
      • For each unmarked adjacent vertex w:
        • set edgeTo[w] = v.
        • dfs(w)

+Efficiency (adj. list): O(V+E) time ,Θ(V) space

s-t shortest paths
  • Find a shortest path from s to every reachable vertex.

  • Solution:
    在这里插入图片描述

  • Efficiency (adj. list): O(V+E) time, Θ(V) space

Layers of Abstraction

Our choice of how to implement the Graph API has profound implications on runtime.(如何设计API严重影响runtime,即用什么方式记录该点的邻居节点,我们介绍了三种方式,矩阵,hashset,以及一个存储list的数组,最后一个效率最高,因为没有冗余,即只用记录真实的邻居,不用向矩阵一样每个节点都必须记录其与所有其他节点的关系)

Summary

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值