CS201 - Spring 2014 - Class 33

  • 2D (and higher) arrays in java
       - Two approaches to creating:

          int[][] matrix = int[rows][cols];
       
       or

          int[][] matrix = int[row][];

          for( int i = 0; i < rows; i ++ ){
             matrix[i] = new int[cols];
          }
       
       - Why might we ever do the latter approach?
          - if you want to have different number of columns per row, you can create each row independently.

       - accessing elements works just like a normal array:
          
          matrix[0][0] // first row, first column

          matrix[1][4] // second row (at index 1), 5th column (at index 4)

       - In theory, there is NO limit to the number of dimensions you can have for an array in java
          - HOWEVER, most JVMs, limit it to 255, that is
          
          int[][][].....[] // 255 of '[]'

  • graph terminology clarified
       - path: a path is a list of vertices p_1, p_2, ..., p_k where there exists an edge (p_i, p_{i+1}) in E
       - simple path: a path where all vertices are unique, except possibly the start and end
       - cycle: a path where p_1 = p_k AND the edges are unique (this avoids the problem of calling A, B, A a cycle in an undirected graph)
          - note that in a directed graph A, B, A would be considered a cycle (if those edges existed) since they're separate edges (A->B and B->A)


  • finding cycles
       - given a connected, undirected graph, how can we determine if it has a cycle in it?
          - or, given a connected graph, determine that it is not a tree
       - what is the definition of a cycle?
          - a path, where the endpoints are the same
       - idea:
          - start at a node, go down a path
             - stop when either we find a vertex on the path that we've already seen
             - or when we hit a dead-end
          - if we hit a dead-end, backtrack and find another path
          - if we visit all of the nodes, without finding a repeat vertex, it's acyclic
       - does this sound like anything we've seen before?
          - depth first search!
       

  • depth first search
       - look at dfsRecursive method in GraphAlgorithms code
          - creates a set of the things that have been visited
          - then calls dfsHelper on the start node with the visited set
       - dfsHelper
          - add it to the set of visited things
          - for each neighbor:
             - if it hasn't been visited yet, call dfsHelper
       - what is the run-time of dfs on a graph?
          - how many times do we call dfsHelper?
             - one time for each vertex (assuming it's connected)
          - what is the cost of each call to dfsHelper?
             - depends on how the graph is stored!
             - adjacency matrix:
                - we need to traverse all V entries to get the neighbors
                   - O(|V|)
                - O(|V|^2) overall
          - adjacency list:
             - a little trickier
             - how many times do we process each edge?
                - once over the lifetime of the call of dfs
             - O(|V| + |E|), which for a connected graph is O(|E|)
       

  • finding cycles as dfs
       - what modifications need to be made?
          - if we visit a node that we've already visited, then we've found a cycle
          - what about where we just came from?
             - need to know where we came from so we can avoid calling that a cycle
          - want to return true if we find a cycle, false otherwise
          - look at hasCycle method in GraphAlgorithms code

       - observations:
          - what does it do?
             - runs depth first search
             - if it finds a visited node that was not it's parent (i.e. a cycle) returns true
             - otherwise, false
          - how is this different from DFS that we saw before?
             - we have the additional else if to see if we've found a cycle
             - why do we need the parent as a parameter?
                - so we can distinguish finding a visited node in a cycle vs. a visited node where we just came from
          - what does "foundCycle = foundCycle || dfsCycle(v, u)" do?
             - true if we find a cycle anywhere

       - walk through an example
       - what is the running time?
          - basically just DFS!
             - adjacency matrix: O(|V|^2)
             - adjacency list: O(|V| + |E|)