【CS 61b study notes 7】Graph & ShortPathProblem

Trees and Traversals

Tree Definition - A tree consist of :

  • A set of nodes
  • A set of edges that connect those nodes
    • Constrain : There is exactly one path between any two nodes. (No circle)

Rooted Trees Definition - A rooted tree is a tree where we have chosen one node as the root

  • Every node N except the root has exactly one parent, defined as the first node on the path from N to the root
  • A node with no child is called a leaf

Tree Traversal Orderings

Tree traversal

Level order

  • Visit top to bottom, left to right : DBFACEG

Depth First Traversals

  • PreOrder

    • Visit a node , then traverse its children.

    • KEY -> LEFT -> RIGHT: DBACFEG

      PreOrder(BSTNode x){
             
             
      	if (x == null) {
             
             return;}
      	print(x.key);
      	preOrder(x.left);
      	preOrder(x.right);
      }
      
  • InOrder

    • Traverse left child , visit, then traverse right child .
    • LEFT -> KEY -> RIGHT : ABCDEFG
      inOrder(BSTNode x){
             
             
      	if (x == null) {
             
             return;}
      	inOrder(x.left);
      	print(x.key);
      	inOrder(x.right);
      }
      
  • PostOrder

    • Traverse left, traverse right ,then visit
    • LEFT -> RIGHT -> KEY : ACBEGFD
      postOrder(BSTNode x){
             
             
      	if (x == null) {
             
             return;}
      	postOrder(x.left);
      	postOrder(x.right);
      	print(x.left);
      }
      

Graph

Graph definition - A graph consists of :

  • A set of nodes
  • A set of zero or more edges, each of which connects two nodes.

Simple Graph

  • No edges that connect a vertex to itself ,i.e. NO “loop”
  • No two edges that connect the same vertices ,i.e. NO “parallel edges”.

In cs61b , unless otherwise explicitly stated, all graphs will be simple

Graph types : Acyclic , cylic, directed ,undirected, with edges labels.
Some terminologies about Graph

  • Graph
    • Set of vertices, a.k.a. nodes
    • Set of edges: pairs of vertices
    • Vertices with an edge between are adjacent
    • Optional : Vertices or edges may have labels (or weights)
  • A path is s sequence of vertices connected by edges
    • A simple path is a path without repeated vertices
  • A cycle is a path whose first and last vertices are the same
    • A graph with a cycle is ‘cyclic’
  • Two vertices are connected if there is path between them.
  • If all vertices are connected , we say the graph is connected.

Depth-First Traversal

s-t Connectivity

Problem Description : Given source vertex s and a target vertex t , is there a path between s and t?
s-t problem

A recursive algorithm for connected(s,t) :

  • Mark s
  • Does s==t ? If so return true
  • Otherwise , if connected(v,t) for any unmarked neighbor v of s , return true
  • Return False
  • Note: Marking the node we have visited prevents us from a infinite loop*
  • When the marked vertex has many neighbors , we often choose the smallest item first.

Depth First Search

  • DFS Preorder (dfs calls)

    • Action is before DFS calls to neighbors
    • E.g.: edgeTo[1] was set before DFS calls to neighbor 2 and 4
    • One valid DFS preorder for this graph : 012543678
      • Equivalent to the order of dfs calls.
      • that is ,when we first mark the vertax , the vertax will be print
  • DFS Postorder (dfs returns)

    • Action is after DFS calls to neighbors
    • Example : dfs(s)
      • Mark(s)
      • For each unmarked neighbor n of s , dfs(n)
      • print(s)
    • Results for dfs(0) would be 347685210
    • Equivalent to the order of dfs returns.
  • BFS Order

    • Act in order of distance from s
    • Analogous to “level order”. Search is wide , not deep
    • 0 1 24 53 68 7
    • 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(addLast) and dequeue(removeFirst)
        • Let us call this 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 the end of queue

Graph API

To implement the graph algorithm like BFS and DFS , we need

  • An API (Application Programming Interface)
    • These are the Graph methods , including their signitures and behaviors
    • Define how Graph client programmers must think.
  • An underlying data structure to represent the graph
  • Need to consider
    • Runtime
    • Memory Usage
    • Difficulty of implementing various graph algorithm

Decision 1 # Integer Vertices

Common convention: Number nodes irrespective of “label” , and use number throughout the graph implementation. To lookup a vertex by label, we need to use a Map<Label,Integer>

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
	Interable<Integer> adj(int v); // vertices adjacent to v
	int V();
	int E();
	/** degree of vertex v in graph G ,degree = #edges*/
	public static int degree(Graph G, int v){
   
   
		int degree = 0;
		for (int w : G.adj(v)){
   
   
			degree += 1;
		}
		return degree;
	}
	/** print the edge*/
	public static void print(Graph G){
   
   
		for(int v = 0; v < G.V(); v++){
   
   
			for (int w : G.adj(v)){
   
   
				System.out.println(v+"-"+w);
			}
		}
	}

}

Graph Representations

Adjacency Matrix

sample graph

s/t directed 0 1 2
0 0 1 1
1 0 0 1
2 0 0 0
  • For the undirected graph, each edge is represented twice in the matrix. Simplicity at the expense of space.
v-w undirected 0 1 2 3
0 0 1 0 0
1 1 0 1 0
2 0 1 0 1
3 0 0 1 0
  • For the undirected example :

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

    for(int v = 0; v < G.V(); v+=1){
         
         
    	for(int w :G.adj(v){
         
         
    		System.out.println(v+'-'+w);
    	}
    }
    
    • To figure out the order of growth of the running time of the print client from before if the graph uses an adjacency-matrix representation, where V is the number of vertices , and E is the total number of edges
      • Θ ( N 2 ) \Theta(N^2) Θ(N2)
      • Runtime to iterate over v’neighbors
        • Θ ( N ) \Theta(N) Θ(N)
      • How many vertices do we consider?
        • V times

Edge sets : Collection of all edges

Consider the directed graph , we can use the HashSet<Edge> , where each Edge is a pair of ints.
{ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 2 ) } \{(0,1),(0,2),(1,2)\} {(0,1),(0,2),(1,2)}

Adjancency List

  • Common approach : Maintain array of lists indexed by vertex number

  • Most popular approach for representing graphs
    adj-list

  • Graph Pringting Runtime

    for(int v = 0; v < G.V(); v+=1){
         
         
    	for(int w :G.adj(v){
         
         
    		System.out.println(v+'-'+w);
    	}
    }
    
    • To figure out the order of growth of the running time of the print client from before if the graph uses an adjacency-list representation, where V is the number of vertices , and E is the total number of edges
      • Best case: Θ ( N ) \Theta(N) Θ(N) Worst case: Θ ( N 2 ) \Theta(N^2) Θ(N2)
      • Runtime to iterate over v’neighbors
        • Ω ( 1 ) \Omega(1) Ω(1) - O ( N ) O(N) O(N)
        • List can be between 1 and V items
      • How many vertices do we consider?
        • V times
      • All the case : Θ ( V + E ) \Theta(V+E) Θ(V+E)
        • Create V iterators
        • Print E times
        • V is the total number of vertices
        • E is total number of edges in the entire graph
      • No matter what shape of the increasingly complex graphs we generate , as V and E grow , the runtime will always grow exactly as Θ ( V + E ) \Theta(V+E) Θ(V+E)
        • Example Shape 1 : Very Sparse graph where E grows very slowly : every vertex is connected to its square : 2-4, 3-9, 4-16, etc.
          • E is Θ ( V ) \Theta(\sqrt V) Θ(V ) , runtime is Θ ( V + V ) \Theta(\sqrt V+V) Θ(V +V) , which is just Θ ( V ) \Theta(V) Θ(V)
        • Example Shape 2 : Very dense graph where E grows very quickly: every vertex is connected to every other
          • E is Θ ( V 2 ) \Theta(V^2) Θ(V2), runtime is Θ ( V 2 + V ) \Theta(V^2+V) Θ(V2+V) , which is just Θ ( V 2 ) \Theta(V^2) Θ(V2)

Summary

Type addEdge(s,t) for(w : adj(v)) print() hasEdge(s,t) space used
Adjacency Matrix Θ ( 1 ) \Theta(1) Θ(1) Θ ( V ) \Theta(V) Θ(V) Θ ( V 2 ) \Theta(V^2) Θ(V2) Θ ( 1 ) \Theta(1) Θ(1) Θ ( V 2 ) \Theta(V^2) Θ(V2)
Edges Set Θ ( 1 ) \Theta(1) Θ(1) Θ ( E ) \Theta(E) Θ(E) Θ ( E ) \Theta(E) Θ(E) Θ ( E ) \Theta(E) Θ(E) Θ ( E ) \Theta(E) Θ(E)
Adjacency List Θ ( 1 ) \Theta(1) Θ(1) Θ ( 1 ) \Theta(1) Θ(1) to Θ ( N ) \Theta(N) Θ(N) Θ ( V + E ) \Theta(V+E) Θ(V+E) Θ ( d e g r e e ( V ) ) \Theta(degree(V)) Θ(degree(V)) Θ ( E + V ) \Theta(E+V) Θ(E+V)

NOTES : print() and hasEdge(s,t) are not part of the Graph class’s API

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>[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值