CompSci-61B Lecture Topic 9
Trees and Graphs

Instructor: Prof. Robert Burns

Ref: Carrano ch. 25, 27, 29, and 30

Generalizations Of Lists
trees: multiple links, unique paths
graphs: multiple links, multiple paths

Issues
data storage: values and links
traversal concepts and iteration

Tree Styles
organization (hierarchical): multiple links
binary: two links
decision: ordered links

Tree Terminology
root, nodes, and leaves
parent-child relationships
  "parent" = "root" = "vertex"
  "child" = "node" = "leaf"
level (from top vs bottom, 0-based vs 1-based)
height (0-based vs 1-based)
sub-trees

Tree Operations
add(parent, child-node {,order})
duplicates: okay or not

Binary Tree Traversal
all recursive:
"Preorder": vertex, left child, right-child (VLR)
"Inorder": left child, vertex, right-child (LVR)
"Postorder": left child, right-child, vertex (LRV)

public void inorderPrint(Node root)
{
  inorderPrint(root.leftChild)
  System.out.println(root.value)
  inorderPrint(root.rightChild)
}
...see implementations below...

Binary Search Trees (BST)
balance issues
full trees: 1 3 7 15...
complete trees
balanced trees
"horizontal ordering"
add(value)
"inorder" traversal
  ordered traversal

Heaps And Heapsort
another O(n log n) sort method
build complete binary tree (not BST)
  by adding to bottom
  promoting upwards...
  ...by swapping
then remove from root w/promotion

BST Removals
maintain "horizontal ordering"
"seek & swap" algorithm
issue: go left or right?
  by height...
  at random...
  alternating

Balancing Methods For Binary Trees
AVL Rotations
2-3 and 2-4 trees
Red-Blank trees
  java.util.TreeMap
  Map<K,V> a = new TreeMap<K,V>();
B-trees

Graphs
Generalization of linked list concept
nodes can link to any other node
  ...including self
applications:
  route maps
  project charts
  mazes

Graph Terminology
"vertex" (like a linked list node)
"edge" (like a linked list link)
"digraph" -- directed links (one-way links)

Representing Vertices

  private class Vertex
  {
    private String name; // name of the vertex
    private boolean isVisited; // for use in tracing
    private void reset(){isVisited = false;}
  }
...more will be added later...

Storing Vertices
use any list
  but can store link information separately
  (unlike "next" and "prev" in nodes)
"adjacency matrix": 2D table
  row for each "from" vertex
  column for each "to" vertex
  stored separate from vertices
mark cell with "X" to indicate connectivity
"adjacency list": lists of downstream vertices
  stored with OR separate from vertices

Representing Edges

  private class Edge
  {
    private String fromVertexName; // matching Vertex.name
    private String toVertexName; // matching Vertex.name
  }
...more will be added later...

An Adjacency Matrix Implementation
using a Java "HashMap" of Edges
Map<Edge,Edge> adjacencyMatrix = new TreeMap<Edge,Edge>();
key and value are the same -- for now
add these to the Edge class:

    public boolean equals(Object o) // for HashMap use
    {
      Edge e = (Edge)o;
      return fromName.equalsIgnoreCase(e.fromName)
        && toName.equalsIgnoreCase(e.toName);
    }

    public int hashCode() // for HashMap use
    {
      return fromName.hashCode() + toName.hashCode();
    }
Traveral Methods
"breadth first" -- start with any vertex
  traverse its adjacent vertices first
"depth first" -- start with any vertex
  traverse a complete path first
"shortest route" -- start vertex to end vertex
  find fewest #of links
"cheapest route" -- start vertex to end vertex
  find lowest "cost" path

Visiting Neighbors: Adjacency Matrix Method
using a hash table for the matrix...

Edge key = new Edge(); // for key comparing only
key.firstName = frontVertex.name;
for (Vertex neighbor: vertexes)
{
  key.secondName = neighbor.name;
  Edge edge = adjacencyTable.get(key);
  if (edge == null) continue; // no matching key
  ...if you get to here, "neighbor" is a neighbor...
other adjacency methods...

Tracing Shortest and Cheapest Routes
from one vertex to any other -- two user inputs
add to private class Vertex:
  private int cost; // or possibly "double"
  private Vertex prev; // a link
  modify reset() to include these
  ...for tracing operations
adjacency table interpretation change:
  key: Edge ignoring cost, for key matching
  value: Edge with cost

Additional For Tracing Cheapest Routes
store the "cost" of each edge
add to private class Edge:
  private int cost; // or possibly "double"
add a container class for vertices:

  private class VertexTemp
    implements Comparable<VertexTemp>
  {
    Vertex vertex;
    private Vertex prev; // candidate for vertex.prev
    private double cost; // candidate for vertex.prev

    public int compareTo(VertexTemp v)
    {
      return cost - v.cost;
    }
  }

All 3 Binary Tree Iterators
  /////////////////////////////////////////////////////////////////////
  private class MyPreorderIterator implements Iterator<T>
  {
    private Stack<Node> path;

    private MyPreorderIterator()
    {
      path = new Stack<Node>();

      if (MyBinaryTree.this.root != null)
        path.push(MyBinaryTree.this.root);
    }

    public boolean hasNext()
    {
      return !path.empty();
    }

    public T next()
    {
      Node p = path.peek();
      T value = p.value;

      if (p.left != null)
        path.push(p.left);
      else if (p.right != null)
        path.push(p.right);
      else
      {
        p = path.pop();
        assert p != null;
        if (!path.empty())
        {
          Node prev = path.peek(); // parent of p
          assert prev != null;
          if (prev.right == p) while (prev != null && prev.right == p && !path.empty())
          {
            p = path.pop();
            prev = path.peek();
          }
          else while (prev != null && prev.left == p && prev.right == null && !path.empty())
          {
            p = path.pop();
            prev = path.peek();
          }
          if (path.empty()){}
          else if (prev.right != null) path.push(prev.right);
          else while (!path.empty()) p = path.pop();
      } }
      return value;
    }

    public void remove()
    {
      throw new UnsupportedOperationException(getClass().getName() + ".MyPreorderIterator.remove is not supported");
    }
  }

  public Iterator<T> getPreorderIterator()
  {
    return new MyPreorderIterator();
  }

  /////////////////////////////////////////////////////////////////////
  private class MyInorderIterator implements Iterator<T>
  {
    private Stack<Node> path;

    private MyInorderIterator()
    {
      path = new Stack<Node>();

      Node p = MyBinaryTree.this.root;
      while (p != null)
      {
        path.push(p);
        p = p.left;
      }
    }

    public boolean hasNext()
    {
      return !path.empty();
    }

    public T next()
    {
      if (hasNext())
      {
        Node prev; // parent of p
        Node p = path.peek();

        T value = p.value;
        if (p.right != null) // go right, and as many lefts as it can go
        {
          p = p.right;
          path.push(p);
          while (p.left != null) path.push(p = p.left);
        }
        else do
        {
          p = path.pop();
          if (path.empty()) break;
          prev = path.peek();
        } while (prev.right == p);
        return value;
      }
      else
        throw new NoSuchElementException("illegal call to " + getClass().getName() + ".MyInorderIterator.next");
    }

    public void remove()
    {
      throw new UnsupportedOperationException(getClass().getName() + ".MyInorderIterator.remove is not supported");
    }
  }

  public Iterator<T> getInorderIterator()
  {
    return new MyInorderIterator();
  }

  /////////////////////////////////////////////////////////////////////
  private class MyPostorderIterator implements Iterator<T>
  {
    private Stack<Node> path;

    private MyPostorderIterator()
    {
      path = new Stack<Node>();

      Node p = MyBinaryTree.this.root;
      while (p != null)
      {
        path.push(p);
        p = p.left;
      }
    }

    public boolean hasNext()
    {
      return !path.empty();
    }

    public T next()
    {
      Node p = path.pop();
      T value = p.value;

      if (!path.empty())
      {
        Node prev = path.peek(); // parent of p
        if (prev.left == p)
        {
          path.push(p = prev.right);
          while (p.left == null && p.right != null) path.push(p = p.right);
          while (p.left != null) path.push(p = p.left);
      } }
      return value;
    }

    public void remove()
    {
      throw new UnsupportedOperationException(getClass().getName() + ".MyPostorderIterator.remove is not supported");
    }
  }

  public Iterator<T> getPostorderIterator()
  {
    return new MyPostorderIterator();
  }

[ Home | Contact Prof. Burns ]