Lecture 7: Linked Lists and Trees


I. Linked List Concept

Node

- data: Object
- next: Node

... <functions> ...

A linked list is a chain of nodes that are linked. Each node is consistent of a data portion and a reference to the next node. The linked list can be conceptualized like the following image:

Courtesy of http://www.csc.liv.ac.uk/~ped/teachadmin/COMP102/Lecture5.html

I like the German flavor to the words... Datum... which I believe is actually date in German, not sure... anyway, the list handler is always the node that you are currently hanging on to and you will have to access all elements using that one node.

This can be bad for access runtime... but boy is it better for adding and removing if you keep a reference to where you want things to go. Changing the size, as mentioned in Lecture 6b, is constant time... HUGE time improvement... but then you're stuck with a potentially linear time access time. The following are code segments that describe what we went over in class about how to play with a linked list.

II. Linked List Code

public class Node {
   
private Node next;
   
private Object data;
   
   
public Node getNext() {
       
return next;
   
}
   
public void setNext(Node next) {
       
this.next = next;
   
}
   
public Object getData() {
       
return data;
   
}
   
public void setData(Object data) {
       
this.data = data;
   
}
   
   
// reroute next to D after setting D's next to the current next
   
public void addNext(Node D) {
        D.setNext(next);
        next
= D;
   
}
   
// just reroute next to next's next... no clean up necessary in Java
   
public void removeNext() {
       
// if there is no next, do nothing
       
if (next == null)
           
return;
        next
= next.getNext();
   
}
   
// recursively adds up the count of objects in the list
   
public int size() {
       
// if last element, send back the size of one
       
if (next == null)
           
return 1;
       
// if not the last, just add one to whatever gets passed back
       
return 1 + next.size();
   
}
   
// recursively finds the n-th element, emulates walking towards a goal and counting down
   
public Node getItem(int index) {
       
if (index == 0)
           
return this;
       
return next.getItem(index - 1);
   
}
   
// finds the item to remove and removes it
   
public void removeItem(int index) throws IndexOutOfBoundsException {
       
// if what you are trying to find is out of bounds, throw some exception
       
if ( (index > 0) && (next == null) )
           
throw new IndexOutOfBoundsException("Trying to remove an element that's out of bound");
       
       
// you are one before what you want to get rid of, reroute next to the one right after what you want to get rid of
       
if (index == 1)
            next
= next.getNext();
       
// else, just keep passing it down the chain
       
else
            next.removeItem(index
- 1);
   
}
   
/*
    * Alternatively... you can do it the really easy way (Randy way) for removeItem and do this
    * Node parent = getItem(index-1);
    * parent.removeNext();
    */
   
   
// goes back and finds the last element and adds one to the back of it
   
public void push_back(Node D) {
       
if (next == null)
            next
= D;
       
else
            push_back(D);
   
}
}

III. Tree Concept

TreeNode

- data: Object
- children: ArrayList<TreeNode>

... <functions> ...

A tree is basically a spanning linked list. It can have multiple "next" nodes. You treat it slightly different in that you need to recursively apply everything to all the nexts, not just one. There are also ideas like height and such behind it too...

Courtesy of http://courses.washington.edu/hypertxt/cgi-bin/12.228.185.206/html/maps/maps.html

One of the interesting things to note about a tree is that it is inductively a tree. What that means is that a tree is a tree at a node if all the children under it are also trees, called subtrees. Even if it is just a leaf, it is still a tree because of the definition.

Do note that a tree doesn't have loops... if it does it becomes a graph. A child may have more than one parent but a child can't be the parent of its parent (definition of a loop).

IV. Tree Code

import java.util.ArrayList;


public class TreeNode {
    private ArrayList<TreeNode> children;
    private Object data;


    public ArrayList<TreeNode> getChildren() {
        return children;
    }

    public void setChildren(ArrayList<TreeNode> children) {
        this.children = children;
    }
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }

   
    // inductively finds the size of the tree
    public int size() {
        // this insures that the size is at least 1
        int s = 1;
        for (int i = 0; i<children.size(); i++)
            // adds all subsequent children's size onto itself... trees are inductively trees from subtrees,
            //  which are children
            s += children.get(i).size();
        return s;
    }
   
    // inductively finds the max height of the tree
    public int height() {
        // always starts with height of 0
        int maxH = 0;
       
        for (int i = 0; i<children.size(); i++)
            // finds the max height, which is the height of the children + 1,
            // since going down increments the height
            if (children.get(i).height()+1 > maxH)
                maxH = children.get(i).height()+1;
       
        return maxH;
    }
}