Comparing changes

2.0.0 3.0.0
92 commits 29 files changed

Commits

44f9921 Add link to README mo khan 2020-09-27 19:14:36
fc3968b docs: document each function mo khan 2020-09-27 19:11:12
1fdac31 docs: Add documentation for AVL tree mo khan 2020-09-27 18:38:47
cf2dec1 style: run cclang formatter mo khan 2020-09-27 02:10:19
bd7fc9d docs: small formatting updates mo khan 2020-09-27 02:02:34
dd6410a docs: add headings to assignment 3 mo khan 2020-09-27 01:58:57
c930208 Merge 02 -> README mo khan 2020-09-27 01:42:02
bfcc2fa 01 -> README mo khan 2020-09-27 01:41:17
b1efa9c feat: build a meldable heap mo khan 2020-09-27 00:53:30
6b0b895 Split diagrams up mo khan 2020-09-26 23:38:24
0c74c26 docs: add visualization of dfs mo khan 2020-09-26 19:15:39
2b73696 docs: add visual for each AVL rotation mo khan 2020-09-21 01:33:31
a240eea docs: print output of merge/quick sort mo khan 2020-09-21 00:58:13
8678b27 refactor: make private function static mo khan 2020-09-21 00:31:11
aaf96ed docs: complete question 3 mo khan 2020-09-21 00:27:57
317ccdf test: convert large avl tree to rb tree mo khan 2020-09-20 23:57:35
57de152 refactor: change colouring algorithm mo khan 2020-09-20 23:41:28
2a9f5f3 test: ensure rb node parents are equal mo khan 2020-09-20 23:06:55
e1466ec feat: print rb node parent in #inspect mo khan 2020-09-20 22:58:16
6d195cd refactor: rename connected to has_edge mo khan 2020-09-08 16:52:44
373fbfd refactor: inline variable declarations mo khan 2020-09-08 00:51:54
007076e feat: record edges in graph mo khan 2020-09-08 00:49:24
642c56d docs: add notes on binary trie mo khan 2020-09-08 00:36:31
78f5d8b docs: add notes on graphs mo khan 2020-09-08 00:13:22
c942a50 feat: add vertex to graph mo khan 2020-09-07 21:20:53
8737272 feat: add function to init vertex mo khan 2020-09-07 19:55:54
5aaa100 test: add graph_tests to suite mo khan 2020-09-07 19:50:13
7565e1a feat: implement quick sort mo khan 2020-09-07 19:35:42
fae9911 compare head of two lists to merge mo khan 2020-09-07 01:12:23
f8e6343 Add merge sort tests mo khan 2020-09-05 21:48:40
79e375f test: start to work on sorting tests mo khan 2020-08-31 20:59:23
5748e87 fix: root of red/black tree is black mo khan 2020-09-02 23:57:45
29cb2db fix: assign colour based on height mo khan 2020-08-31 17:56:48
02f04d0 fix: ensure equals checks for colour mo khan 2020-08-31 17:35:13
fb0f63d feat: add rb_tree_equals function mo khan 2020-08-30 19:18:27
ab994a8 refactor: extract method to find root mo khan 2020-08-30 00:56:19
c898a2b style: remove debug code mo khan 2020-08-30 00:30:26
176006d fix: repaint colour when unbalanced mo khan 2020-08-30 00:28:19
3bfe570 test: Add to left/right subtree mo khan 2020-08-29 20:08:16
fc294bf feat: insert into red/black tree mo khan 2020-08-29 19:29:48
2c5a1f4 create initializer for red/black tree mo khan 2020-08-28 20:24:45
cfca07a Start to build a red black tree mo khan 2020-08-28 20:16:06
9746986 Rename node to tree mo khan 2020-08-28 20:10:00
39859c6 Add more test cases mo khan 2020-08-28 19:50:18
401cf13 Handle left right rotation after delete mo khan 2020-08-28 17:15:23
4d37cc0 Perform left left rotate after deletion mo khan 2020-08-28 17:04:23
bb5614b Implement a right rotation mo khan 2020-08-27 20:25:24
e040e02 Add link to lecture video mo khan 2020-08-27 19:19:36
74a52d2 Insert into root of tree mo khan 2020-08-27 19:17:17
b7d1b01 Start to create an AVL tree mo khan 2020-08-27 19:06:52
7082bf3 Add notes on AVL tree mo khan 2020-08-27 18:57:32
6e52068 Add notes on Binary Heap mo khan 2020-08-27 18:23:30
67a2c78 Add notes mo khan 2020-08-27 18:05:33
b8f3a0b Add notes on red-black tree mo khan 2020-08-27 17:37:28
5d9ebbb Draw graph mo khan 2020-08-26 21:47:12
e3d7861 Add assignment 3 questions mo khan 2020-08-26 21:40:40
doc/unit/09/README.md
@@ -0,0 +1,253 @@
+# 2-4 Trees
+
+* is a rooted tree with the following properties:
+
+* height: all leaves have the same depth
+* degree: every internal node has 2, 3 or 4 children.
+
+lemma:
+
+> A 2-4 tree with n leaves has height at most log n.
+
+# Red-Black Trees
+
+[Lecture Video](https://www.youtube.com/watch?v=JMZkuYa04tY)
+
+* A binary search tree with logarithmic height.
+
+1. tree with `n` values has a height of most 2logn
+1. The `add(x)` and `remove(x)` operations on a red-black tree run in `O(logn)` worst case time.
+1. The amortized number of rotations performed during an `add(x)` or `remove(x)` operation is constant.
+
+Each node, `u`, has a colour which is either `red` or `black`.
+
+* red: is represented by the value 0.
+* black: is represented by the value 1.
+
+A red-black tree implements the SSet interface and supports
+operations `add(x)`, `remove(x)`, and `find(x)` in O(logn) worst-case time
+per operation.
+
+
+```java
+class Node<T> extends BSTNode<Node<T>, T> {
+  byte colour;
+
+  void flipRight(Node<T> u) {
+    swapColours(u, u.left);
+    rotateRight(u);
+  }
+
+  void flipLeft(Node<T> u) {
+    swapColours(u, u.right);
+    rotateLeft(u);
+  }
+
+  boolean add(T x) {
+    Node<T> u = newNode(x);
+    u.colour = red;
+    boolean added = add(u);
+    if (added)
+      addFixup(u);
+    return added;
+  }
+
+  void addFixup(Node<T> u) {
+    while (u.colour == red) {
+      if (u == r) {
+        u.colour = black;
+        return;
+      }
+      Node<T> w = u.parent;
+      if (w.left.colour == black) {
+        flipLeft(w);
+        u = w;
+        w = u.parent;
+      }
+      if (w.colour == black)
+        return;
+      Node<T> g = w.parent;
+      if (g.right.colour == black) {
+        flipRight(g);
+        return;
+      } else {
+        pushBlack(g);
+        u.x = w.x;
+        u = w.right;
+      }
+    }
+    splice(w);
+    u.colour += w.colour;
+    u.parent = w.parent;
+    removeFixup(u);
+    return true;
+  }
+
+  void removeFixup(Node<T> u) {
+    while (u.colour > black) {
+      if (u == r) {
+        u.colour = black;
+      } else if (u.parent.left.colour == red) {
+        u = removeFixupCase1(u);
+      } else if (u == u.parent.left) {
+        u = removeFixupCase2(u);
+      } else {
+        u = removeFixupCase3(u);
+      }
+    }
+    if (u != r) {
+      Node<T> w = u.parent;
+      if (w.right.colour == red && w.left.colour == black) {
+        flipLeft(w);
+      }
+    }
+  }
+
+  Node<T> removeFixupCase3(Node<T> u) {
+    Node<T> w = u.parent;
+    Node<T> v = w.left;
+    pullBlack(w);
+    flipRight(w);
+    Node<T> q = w.left;
+    if (q.colour == red) {
+      rotateRight(w);
+      flipLeft(v);
+      pushBlack(q);
+      return q;
+    } else {
+      if (v.left.colour == red) {
+        pushBlack(v);
+        return v;
+      } else {
+        flipLeft(v);
+        return w;
+      }
+    }
+  }
+}
+```
+
+The following properties are satisfied before and after any operation:
+
+* black-height: there are the same # of black nodes on every root to the leaf path. (sum of colours on any root to leaf path is the same.)
+* no-red-edge: No two red nodes are adjacent. (except the root, `u.colour + u.parent.colour >= 1`)
+
+The root is black.
+
+
+## AVL Trees
+
+AVL trees are height-balanced.
+
+* height-balanced: at each node `u`, the height of the subtree rooted at `u.left` and the subtree rooted at `u.right` differ by at most one.
+
+AVL trees have a smaller height than red-black trees. The height
+balancing can be maintained during `add(x)` and `remove(x)` operations
+by walking back up the path to the root and performing a rebalancing
+operation at each node `u` where the height of `u`'s left and right subtrees differ by two.
+
+AVL is a self balancing binary search tree in which each node maintains
+extra information called a balance factor whose value is either -1, 0, or +1.
+
+The balance factor is determined by calculating the difference
+between the height of the left subtree and that of the right subtree of that node.
+
+Balance Factor = (Height of left subtree - height of right subtree) or (height of right subtree - height of left subtree).
+
+The self balancing property of an avl tree is maintained by the balance factory.
+
+E.g.
+
+```plaintext
+        (33) 1
+      /     \
+   (9) -1    (53) -1
+  /   \        \
+(8) 0 (21) 1    (61) 0
+     /
+  (11) 0
+```
+
+### Operations
+
+* Left Rotate: nodes on the right is transformed into arrangement on the left.
+* Right Rotate: nodes on the left are transformed into arrangment on the right.
+* Left-Right and Right-Left Rotate: shift left then right.
+
+
+Left Rotate:
+
+```plaintext
+1.
+  (x)
+    \
+    (y)
+
+2.
+
+   (y)
+  /
+(x)
+
+```
+
+Right Rotate:
+
+```plaintext
+1.
+  (y)
+  /
+(x)
+
+2.
+(x)
+  \
+  (y)
+```
+
+Left-Right Rotate:
+
+```plaintext
+1.
+  (z)
+  /
+(x)
+  \
+  (y)
+
+2.
+    (z)
+    /
+  (y)
+  /
+(x)
+
+3.
+  (y)
+  / \
+(x) (z)
+```
+
+
+```plaintext
+1.
+
+(z)
+  \
+   (x)
+  /
+(y)
+
+2.
+
+(z)
+  \
+   (y)
+     \
+     (x)
+
+3.
+   (y)
+  /   \
+(z)   (x)
+```
doc/unit/10/README.md
@@ -0,0 +1,103 @@
+# Heaps
+
+> a disorganized pile
+
+## BinaryHeap: An implicit Binary Tree
+
+Eytzinger's method can represent a complete binary tree as an array
+by laying out the nodes of the tree in a breadth-first order.
+
+* The root is stored at position 0
+* The root's left child is stored at position 1
+* The root's right child is stored at position 2.
+
+The left child of the node at index `i` is at index `left(i) = 2i + 1`
+and the right child of the node at index `i` is at index `right(i) = 2i +2`.
+The parent of the node at index `i` is at index `parent(i) = (i-1)/2`.
+
+```plaintext
+
+           -------(0)--------
+          /                  \
+       (1)                    (2)
+      /    \               /      \
+   (3)       (4)        (5)         (6)
+  /  \      /   \       /  \       /   \
+(7)  (8)  (9)  (10)  (11)  (12)  (13)  (14)
+
+| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|
+```
+
+* left: `2i+1`
+* right: `2i+2`
+
+The binary heap implements the priority queue interface.
+Ignoring the cost of `resize()` it supports the operations
+`add(x)` and `remove(x)` in `O(logn)` time per operation.
+
+```java
+class BinaryHeap {
+  T[] a;
+  int n;
+
+  int left(int i) {
+    return 2*i + 1;
+  }
+  int right(int i) {
+    return 2*i + 2;
+  }
+  int parent(int i) {
+    return (i-1)/2;
+  }
+  boolean add(T x) {
+    if (n+1 > a.length) resize();
+    a[n++] = x;
+    bubbleUp(n-1);
+    return true;
+  }
+  void bubbleUp(int i) {
+    int p = parent(i);
+    while (i > 0 && compare(a[i], a[p]) < 0) {
+      swap(i, p);
+      i = p;
+      p = parent(i);
+    }
+  }
+  T remove() {
+    T x = a[0];
+    a[0] = a[--n];
+    trickleDown(0);
+    if (3*n < a.length) resize();
+    return x;
+  }
+  void trickleDown(int i) {
+    do {
+      int j = -1;
+      int r = right(i);
+      if (r < n && compare(a[r], a[i]) < 0) {
+        int l = left(i);
+        if (compare(a[1], a[r]) < 0) {
+          j = 1;
+        } else {
+          j = r;
+        }
+      } else {
+        int l = left(i);
+        if (l < n && compare(a[l], a[i]) < 0) {
+          j = 1;
+        }
+      }
+      if (j >= 0) swap(i, j);
+      i = j;
+    } while (i >= 0);
+  }
+}
+```
+
+A `BinaryHeap` uses this technique to implicitly represent a complete
+binary tree in which the elements are `heap-ordered.`
+
+heap-ordered: The value stored at any index `i` is not smaller than the value stored at index `parent(i)`, with the exception of the root value, `i = 0`.
+The smallest value in the priority Queue is at position 0.
+
+## MeldableHeap: A randomized meldable heap
doc/unit/11/README.md
@@ -0,0 +1,134 @@
+# Comparison-Based Sorting
+
+* merge sort O(nlogn)
+* quick sort O(nlogn)
+* heap sort O(nlogn)
+
+`compare(a,b)`
+
+* -1: a < b
+* 0: a == b
+* +1: a > b
+
+## Merge-Sort
+
+is a classic recursive divide and conquer.
+
+* if `a` is at most 1 then `a` is sorted.
+* else we split `a` into two halves
+  * `a0 = a[0...(n/2)-1]`
+  * `a1 = a[(n/2)...n-1]`
+  * merge a0, a1
+
+```java
+void mergeSort(T[] a, Comparator<T> c) {
+  if (a.length <= 1) return;
+
+  T[] a0 = Arrays.copyOfRange(a, 0, a.length/2);
+  T[] a1 = Arrays.copyOfRange(a, a.length/2, a.length);
+  mergeSort(a0, c);
+  mergeSort(a1, c);
+  merge(a0, a1, a, c);
+}
+```
+
+## Quicksort
+
+Unlike mergesort which does merging after solving the two subproblems,
+quicksort does all of its work upfront.
+
+1. pick a random `pivot` element `x` from `a`
+2. partition `a` into the set of elements less than `x`, the set of elements equal to `x` and the set of elements greater than `x`.
+3. recursively sort the first and third sets in this partition.
+
+```java
+void quickSort(T[] a, Comparator<T> c) {
+  quickSort(a, 0, a.length, c);
+}
+void quickSort(T[] a, int i, int n, Comparator<T> c) {
+  if (n <= 1) return;
+  T x = a[i + rand.nextInt(n)];
+  int p = i - 1, j = i, q = i+n;
+
+  while (j < q) {
+    int comp = compare(a[j], x);
+    if (comp < 0) {
+      swap(a, j++,  ++p);
+    } else if (comp > 0) {
+      swap(a, j, --q);
+    } else {
+      j++;
+    }
+  }
+  quickSort(a, i, p-i+1, c);
+  quickSort(a, q, n-(q-i), c);
+}
+```
+
+## Heap-sort
+
+In-place sorting algorithm. Uses binary heaps.
+Binary heap data structure represents a heap in a single array.
+The heap sort converts the input array into a heap and then extracts the min
+value.
+
+## Counting sort and Radix sort
+
+These are not comparison based sorting algorithms.
+These are specialized for sorting small integers.
+
+### Counting Sort
+
+This algorithm sorts using an auxiliary array of counters.
+This is very efficient for sorting an array of integers when the length,
+`n`, of the array is not much smaller than the maximum value, `k-1`,
+that appears in the array.
+
+```java
+int[] counting_sort(int[] a, int k) {
+  int c[] == new int[k];
+  for (int i = 0; i < a.length; i++)
+    c[a[i]]++;
+  for (int i = 1; i < k; i++)
+    c[i] += c[i-1];
+  int b[] new int[a.length];
+  for (int i = a.length - 1; i >= 0; i--)
+    b[--c[a[i]]] = a[i];
+  return b;
+}
+```
+
+### Radix Sort
+
+Uses several passes of counting-sort to allow for a much
+greater range of maximum values.
+
+Sorts `w-bit` integers by using `w/d` passes of counting-sort
+to sort these integers `d` bits at a time.
+
+i.e.
+
+first sorts the ints by their least significant `d` bits,
+then their next significant `d` bits, and so on until,
+in the last pass, the ints are sorted by their most
+significant `d` bits.
+
+
+```java
+int[] radixSort(int[] a) {
+  int[] b = null;
+
+  for (int p = 0; p < w/d; p++) {
+    int c[] = new int[1<<d];
+    b = new int[a.length];
+    for (int i = 0; i < a.length; i++)
+      c[(a[i] >> d*p)&((1<<d)-1)]++;
+    for (int i = 1; i < 1<<d; i++)
+      c[i] += c[i-1];
+    for (int i = a.length - 1; i >= 0; i--)
+      b[--c[(a[i] >> d*p)&((1<<d)-1)]] = a[i];
+    a = b;
+  }
+  return b;
+}
+```
doc/unit/12/README.md
@@ -0,0 +1,225 @@
+# Graphs
+
+## Directed graph
+
+```plaintext
+G = (V,E) where
+* V is a set of vertices
+* E is a set of ordered pairs of vertices called edges
+```
+
+An edge `(i, j)` is directed from `i` to `j`;
+
+* `i` is the source
+* `j` is the target
+
+A `path` in `G` is a sequence of vertices.
+
+Typical operations:
+
+* `addEdge(i,j)`: Add the edge (i, j) to E. `O(1)` time.
+* `removeEdge(i,j)`: Remove the edge `(i, j)` from E. `O(1)` time.
+* `hasEdge(i, j)`: Check if the edge `(i, j)` is an element of E. `O(1)` time.
+* `outEdges(i)`: Return a `List` of all ints `j` such that `(i,j)` is an element of E. `O(n)` time.
+* `inEdges(i)`: Return a `List` of all ints `j` such that `(j,i)` is an element of E. `O(n)` time.
+
+`O(n^2)` space.
+
+### AdjacencyMatrix: Representing a Graph by a Matrix
+
+Is a way of representing an `n` vertex graph `G = (V,E)`
+by an `n x m` matrix, `a`, whose entries are boolean values.
+
+```java
+int n;
+boolean[][] a;
+
+AdjacencyMatrix(int nO) {
+  n = nO;
+  a = new boolean[n][n];
+}
+```
+
+The matrix entry `a[i][j]` is defined as:
+
+```plaintext
+a[i][j] = { true if (i, j) element of E otherwise false
+```
+
+```java
+void addEdge(int i, int j) {
+  a[i][j] = true;
+}
+
+void removeEdge(int i, int j) {
+  a[i][j] = false;
+}
+
+boolean hasEdge(int i, int j) {
+  return a[i][j];
+}
+
+List<Integer> outEdges(int i) {
+  List<Integer> edges = new ArrayList<Integer>();
+  for (int j = 0; j < n; j++)
+    if (a[i][j])
+      edges.add(j);
+  return edges;
+}
+
+List<Integer> inEdges(int i) {
+  List<Integer> edges = new ArrayList<Integer>();
+  for (int j = 0; j < n; j++)
+    if (a[j][i])
+      edges.add(j);
+  return edges;
+}
+```
+
+It is large. It stores `n x n` boolean matrix, so it requires
+at least `n^2` bits of memory.
+
+### AdjacencyLists: A Graph as a Collection of Lists
+
+representations of graphs take a more vertex-centric approach.
+There are many possible implementations of adjacency lists.
+
+Operations:
+
+* `addEdge(i, j)`: `O(1)` time
+* `removeEdge(i, j)`: `O(deg(1))` time
+* `hasEdge(i, j)`: `O(deg(1))` time
+* `outEdges(i)`: in `O(1)` time
+* `inEdges(i)`: in `O(n + m)` time
+
+`O(n + m)` space.
+
+
+```java
+int n;
+List<Integer>[] adj;
+
+AdjacencyLists(int nO) {
+  n = nO;
+  adj = (List<Integer>[])new List[n];
+  for (int i = 0; i < n; i++)
+    adj[i] = new ArrayStack<Integer>();
+}
+
+void addEdge(int i, int j) {
+  adj[i].add(j);
+}
+
+void removeEdge(int i, int j) {
+  Iterator<Integer> it = adj[i].iterator();
+  while (it.hasNext()) {
+    if (it.next() == j) {
+      it.remove();
+      return;
+    }
+  }
+}
+
+boolean hasEdge(int i, int j) {
+  return adj[i].contains(j);
+}
+
+List<Integer> outEdges(int i) {
+  return adj[i];
+}
+
+List<Integer> inEdges(int i) {
+  List<Integer> edges = new ArrayStack<Integer>();
+  for (int j = 0; j < n; j++)
+    if (adj[j].contains(i))
+      edges.add(j);
+  return edges;
+}
+```
+
+## Graph Traversal
+
+### Breadth-First Search
+
+starts at a vertex `i` and visits, first the neighbours of `i`,
+then the neighbours of the neighbours of `i`, then the
+neighbours of the neighbours of the neighbours of `i`, and so on.
+
+It uses a `queue` and makes sure that the same vertex is
+not added more than once. It does this be keep track of each 
+vertex that has been visited.
+
+```java
+void bfs(Graph g, int r) {
+  boolean[] seen = new boolean[g.nVertices()];
+  Queue<Integer> q = new SLList<Integer>();
+  q.add(r);
+  seen[r] = true;
+  while (!q.isEmpty()) {
+    int i = q.remove();
+    for (Integer j : g.outEdges(i)) {
+      if (!seen[j]) {
+        q.add(j);
+        seen[j] = true;
+      }
+    }
+  }
+}
+```
+
+time complexity: when using an adjacency list `O(n+m)`.
+
+BFS is useful for computing shortest paths.
+
+### Depth-First Search
+
+is similar to the standard algorithm for traversing binary trees.
+It fully explores one subtree before returning to the current
+node and then exploring the other subtree. Another way to
+think of depth-first search is by saying that it is similar
+to breadth-first search except that it uses a stack instead
+of a queue.
+
+Each node has a state:
+
+* not visited
+* visited
+* visiting
+
+Think of it as a recursive algorithm.
+
+```java
+void dfs(Graph g, int r) {
+  byte[] c = new byte[g.nVertices()];
+  dfs(g, r, c);
+}
+
+// uses recursive stack
+void dfs(Graph g, int i, byte[] c) {
+  c[i] = grey;
+  for (Integer j : g.outEdges(i)) {
+    if (c[j] == white) {
+      c[j] = grey;
+      dfs(g, j, c);
+    }
+  }
+  c[i] = black;
+}
+
+void dfs2(Graph g, int r) {
+  byte[] c = new byte[g.nVertices()];
+  Stack<Integer> s = new Stack<Integer>();
+  s.push(r);
+
+  while (!s.isEmpty()) {
+    int i = s.pop();
+    if (c[i] == white) {
+      c[i] = grey;
+      for (int j : g.outEdges(i))
+        s.push(j);
+    }
+  }
+}
+```
+
+time complexity: when using an adjacency list `O(n+m)` time.
doc/unit/13/README.md
@@ -0,0 +1,44 @@
+# Data Structures for Integers
+
+## BinaryTrie: A digital search tree
+
+encodes a set of `w` bit integers in a binary tree.
+
+* all leaves have depth `w`.
+* each integer is encoded as a root-to-leap path.
+
+The path for the int `x` trusn left at level `i` if the `ith`
+msb of `x` is a `0` and turns right if it is a `1`.
+
+* 3  -> 0011
+* 9  -> 1001
+* 12 -> 1100
+* 13 -> 1101
+
+
+```plaintext
+                (****)
+            /           \
+      (0***)             (1***)
+      /                  /    \
+(00**)             (10**)      (11**)
+     \             /           /
+     (001*)   (100*)        (110*)
+         \         \       /       \
+        (3:0011) (9:1001) (12:1100) (13:1101)
+```
+
+```java
+T find(T x) {
+  int i, c = 0, ix = it.intValue(x);
+  Node u = r;
+  for (i = 0; i < w; i++) {
+    c = (ix >>> w-i-1) & 1;
+    if (u.child[c] == null) break;
+    u = u.child[c];
+  }
+  if (i == w) return u.x;
+  u = (c == 0) ? u.jump : u.jump.child[next];
+  return u == dummy ? null : u.x;
+}
+```
src/03/avl_tree.c
@@ -0,0 +1,334 @@
+#include "avl_tree.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * Print a visual representation of an AVL Tree.
+ *
+ * @param tree The subtree to print
+ * @param level The level in the tree that this subtree is in
+ */
+static void print_tree(AVLTree *tree, int level) {
+  for (int i = 0; i < level; i++)
+    printf(" ");
+
+  if (tree) {
+    printf("(%d:%d)\n", tree->value, tree->height);
+
+    if (!tree->left && !tree->right)
+      return;
+    print_tree(tree->left, level + 1);
+    print_tree(tree->right, level + 1);
+  } else {
+    printf("( )\n");
+  }
+}
+
+/*
+ * Determines if a integer value is evenly divisibly by 2.
+ *
+ * @param value The integer to check
+ * @return true when the value is even otherwise false
+ */
+static bool is_even(int value) { return value % 2 == 0; }
+
+/*
+ * Determines if a integer value is an odd number
+ *
+ * @param value The integer to check
+ * @return true when the value is odd otherwise false
+ */
+static bool is_odd(int value) { return !is_even(value); }
+
+/**
+ * Converts an AVL tree to a Red Black tree with all
+ * nodes in the tree coloured black.
+ *
+ * @param tree The AVL subtree to convert
+ * @param parent The parent node of the current subtree. Use NULL for the root.
+ * @return The converted Red Black tree
+ */
+static RBTree *to_rb_tree(AVLTree *tree, AVLTree *parent) {
+  if (!tree)
+    return NULL;
+
+  RBTree *rb_tree = rb_tree_initialize(tree->value);
+
+  rb_tree->left = to_rb_tree(tree->left, tree);
+  if (rb_tree->left)
+    rb_tree->left->parent = rb_tree;
+
+  rb_tree->right = to_rb_tree(tree->right, tree);
+  if (rb_tree->right)
+    rb_tree->right->parent = rb_tree;
+  return rb_tree;
+}
+
+/**
+ * Applies the correct colouring to each descendant node in a Red Black tree.
+ *
+ * @param tree The Red Black subtree to colour
+ * @param colour The colour to apply to the provided subtree node.
+ */
+static void change_colour(RBTree *tree, enum Colour colour) {
+  if (!tree)
+    return;
+
+  int l = rb_tree_height(tree->left);
+  int r = rb_tree_height(tree->right);
+
+  tree->colour = colour;
+  change_colour(tree->left, l < r || is_odd(l) ? black : red);
+  change_colour(tree->right, r < l || is_odd(r) ? black : red);
+}
+
+/**
+ * Returns the larger integer between the two provided as arguments.
+ *
+ * @param a An integer value to compare
+ * @param b Another integer value to compare
+ * @return Returns the larger value
+ */
+static int max(int a, int b) { return (a > b) ? a : b; }
+
+/**
+ * Returns the height of an AVL subtree.
+ *
+ * @param tree The subtree to interrogate.
+ * @return The height of the subtree
+ */
+static int height_of(AVLTree *tree) { return tree == NULL ? 0 : tree->height; }
+
+/**
+ * Returns the smallest value stored in the AVL tree.
+ *
+ * @param tree The subtree to traverse to find the smallest value.
+ * @return The subtree node containing the smallest value in the tree.
+ */
+static AVLTree *smallest(AVLTree *tree) {
+  AVLTree *current = tree;
+
+  while (current && current->left != NULL)
+    current = current->left;
+
+  return current;
+}
+
+/**
+ * Performs a right rotation on an AVL subtree
+ *
+ * @param y The subtree to perform the rotation on
+ * @return The new root after the rotation is performed.
+ */
+static AVLTree *rotate_right(AVLTree *y) {
+  AVLTree *x = y->left;
+  AVLTree *t = x->right;
+
+  x->right = y;
+  y->left = t;
+
+  y->height = max(height_of(y->left), height_of(y->right)) + 1;
+  x->height = max(height_of(x->left), height_of(x->right)) + 1;
+
+  return x;
+}
+
+/**
+ * Performs a left rotation on an AVL subtree
+ *
+ * @param x The subtree to perform the rotation on
+ * @return The new root after the rotation is performed.
+ */
+static AVLTree *rotate_left(AVLTree *x) {
+  AVLTree *y = x->right;
+  AVLTree *t = y->left;
+
+  y->left = x;
+  x->right = t;
+
+  x->height = max(height_of(x->left), height_of(x->right)) + 1;
+  y->height = max(height_of(y->left), height_of(y->right)) + 1;
+
+  return y;
+}
+
+/**
+ * Calculates the balance of a subtree by taking the difference
+ * of the height of the left subtree and the right subtree.
+ *
+ * @param tree The tree to investigate.
+ * @return The balace
+ */
+static int balance_of(AVLTree *tree) {
+  return (tree == NULL) ? 0 : height_of(tree->left) - height_of(tree->right);
+}
+
+/**
+ * Compares two integers and returns -1, 0, 1.
+ * If a is equal to b then 0 is returned.
+ * If a is greater than b then 1 is returned.
+ * If a is less than b then -1 is returned.
+ *
+ * @param a An integer
+ * @param b Another integer
+ * @return Returns 0, 1, or -1.
+ */
+static int compare(int a, int b) { return (a < b) ? -1 : ((a > b) ? 1 : 0); }
+
+/**
+ * Initializes an instance of an AVL tree.
+ *
+ * @param value The value to assign to the new node in the tree.
+ * @return Returns the new AVL tree node instance.
+ */
+AVLTree *avl_tree_initialize(int value) {
+  AVLTree *tree = malloc(sizeof(AVLTree));
+  tree->value = value;
+  tree->left = NULL;
+  tree->right = NULL;
+  tree->height = 1;
+  return tree;
+}
+
+/**
+ * Computes the # of nodes stored in an AVL subtree.
+ *
+ * @param tree The subtree to investigate.
+ * @return Returns the # of descendant nodes found in the subtree.
+ */
+int avl_tree_size(AVLTree *tree) {
+  int total = 0;
+  if (tree == NULL)
+    return total;
+  if (tree->left)
+    total += avl_tree_size(tree->left);
+  if (tree->right)
+    total += avl_tree_size(tree->right);
+  return total + 1;
+}
+
+/**
+ * Inserts a new value into an AVL subtree.
+ *
+ * @param tree The subtree to attempt to insert a new value into.
+ * @param value The value to insert.
+ * @return Returns the new root of the subtree.
+ */
+AVLTree *avl_tree_insert(AVLTree *tree, int value) {
+  if (tree == NULL)
+    return avl_tree_initialize(value);
+
+  switch (compare(value, tree->value)) {
+  case -1:
+    tree->left = avl_tree_insert(tree->left, value);
+    break;
+  case 1:
+    tree->right = avl_tree_insert(tree->right, value);
+    break;
+  default:
+    return tree;
+  }
+
+  tree->height = 1 + max(height_of(tree->left), height_of(tree->right));
+
+  int balance = balance_of(tree);
+  if (balance > 1 && value < tree->left->value)
+    return rotate_right(tree);
+
+  if (balance < -1 && value > tree->right->value)
+    return rotate_left(tree);
+
+  if (balance > 1 && value > tree->left->value) {
+    tree->left = rotate_left(tree->left);
+    return rotate_right(tree);
+  }
+
+  if (balance < -1 && value < tree->right->value) {
+    tree->right = rotate_right(tree->right);
+    return rotate_left(tree);
+  }
+
+  return tree;
+}
+
+/**
+ * Deletes a value from an AVL subtree.
+ *
+ * @param tree The subtree to search to find the value to delete.
+ * @param value The value to search for.
+ * @return Returns the new root of the subtree.
+ */
+AVLTree *avl_tree_delete(AVLTree *tree, int value) {
+  if (tree == NULL)
+    return tree;
+
+  switch (compare(value, tree->value)) {
+  case -1:
+    tree->left = avl_tree_delete(tree->left, value);
+    break;
+  case 1:
+    tree->right = avl_tree_delete(tree->right, value);
+    break;
+  default:
+    if (tree->left && tree->right) {
+      AVLTree *min = smallest(tree->right);
+      tree->value = min->value;
+      tree->right = avl_tree_delete(tree->right, min->value);
+    } else {
+      AVLTree *tmp = tree->left ? tree->left : tree->right;
+
+      if (tmp) {
+        *tree = *tmp;
+        free(tmp);
+      } else {
+        free(tree);
+        return NULL;
+      }
+    }
+    break;
+  }
+
+  tree->height = 1 + max(height_of(tree->left), height_of(tree->right));
+
+  int balance = balance_of(tree);
+  if (balance > 1 && balance_of(tree->left) >= 0)
+    return rotate_right(tree);
+
+  if (balance > 1 && balance_of(tree->left) < 0) {
+    tree->left = rotate_left(tree->left);
+    return rotate_right(tree);
+  }
+
+  if (balance < -1 && balance_of(tree->right) <= 0)
+    return rotate_left(tree);
+
+  if (balance < -1 && balance_of(tree->right) > 0) {
+    tree->right = rotate_right(tree->right);
+    return rotate_left(tree);
+  }
+
+  return tree;
+}
+
+/**
+ * Converts an AVL tree to a Red Black tree.
+ *
+ * @param tree The AVL tree to convert.
+ * @return Returns a new Red Black tree.
+ */
+RBTree *avl_tree_to_rb_tree(AVLTree *tree) {
+  if (!tree)
+    return NULL;
+
+  RBTree *rb_tree = to_rb_tree(tree, NULL);
+  change_colour(rb_tree, black);
+  return rb_tree;
+}
+
+/**
+ * Prints a visual inspection of
+ * an AVL tree for debugging purposes to stdout.
+ *
+ * @param tree The tree to visualize
+ */
+void avl_tree_inspect(AVLTree *tree) { print_tree(tree, 0); }
src/03/avl_tree.h
@@ -0,0 +1,15 @@
+#include "rb_tree.h"
+
+typedef struct node {
+  struct node *left;
+  struct node *right;
+  int height;
+  int value;
+} AVLTree;
+
+AVLTree *avl_tree_initialize(int value);
+int avl_tree_size(AVLTree *tree);
+AVLTree *avl_tree_insert(AVLTree *tree, int value);
+AVLTree *avl_tree_delete(AVLTree *tree, int value);
+void avl_tree_inspect(AVLTree *tree);
+RBTree *avl_tree_to_rb_tree(AVLTree *tree);
src/03/avl_tree_test.c
@@ -0,0 +1,400 @@
+#include "avl_tree.h"
+#include <cgreen/cgreen.h>
+#include <string.h>
+
+Ensure(initialize_returns_new_tree) {
+  AVLTree *tree = avl_tree_initialize(1);
+  assert_that(tree, is_not_equal_to(NULL));
+}
+
+Ensure(size_returns_zero) {
+  AVLTree *tree = avl_tree_initialize(1);
+
+  assert_that(avl_tree_size(tree), is_equal_to(1));
+}
+
+Ensure(insert_changes_size) {
+  AVLTree *tree = avl_tree_initialize(5);
+  avl_tree_insert(tree, 4);
+
+  assert_that(avl_tree_size(tree), is_equal_to(2));
+}
+
+Ensure(insert_changes_height) {
+  AVLTree *tree = avl_tree_initialize(5);
+  tree = avl_tree_insert(tree, 4);
+
+  assert_that(tree->height, is_equal_to(2));
+  assert_that(tree->left->height, is_equal_to(1));
+}
+
+Ensure(insert_creates_a_new_root) {
+  AVLTree *tree = avl_tree_insert(NULL, 10);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(10));
+  assert_that(tree->left, is_equal_to(NULL));
+  assert_that(tree->right, is_equal_to(NULL));
+}
+
+Ensure(insert_performs_a_left_rotation) {
+  /*
+    (10)                  (20)
+      \                  /    \
+      (20)      ->    (10)    (30)
+        \
+        (30)
+  */
+  AVLTree *tree = avl_tree_initialize(10);
+  tree = avl_tree_insert(tree, 20);
+  tree = avl_tree_insert(tree, 30);
+
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->left->value, is_equal_to(10));
+  assert_that(tree->right->value, is_equal_to(30));
+};
+
+Ensure(insert_performs_a_right_rotation) {
+  /*
+       (30)            (20)
+       /              /   \
+     (20)     -->   (10)  (30)
+     /
+  (10)
+  */
+  AVLTree *tree = avl_tree_initialize(30);
+  tree = avl_tree_insert(tree, 20);
+  tree = avl_tree_insert(tree, 10);
+
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->left->value, is_equal_to(10));
+  assert_that(tree->right->value, is_equal_to(30));
+}
+
+Ensure(insert_performs_a_left_right_rotation) {
+  /*
+     (30)         (20)
+     /           /    \
+  (10)     -> (10)    (30)
+     \
+     (20)
+  */
+  AVLTree *tree = avl_tree_initialize(30);
+  tree = avl_tree_insert(tree, 10);
+  tree = avl_tree_insert(tree, 20);
+
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->left->value, is_equal_to(10));
+  assert_that(tree->right->value, is_equal_to(30));
+}
+
+Ensure(insert_performs_a_right_left_rotation) {
+  /*
+  (10)             (20)
+      \            /  \
+      (30)  --> (10)  (30)
+     /
+  (20)
+  */
+  AVLTree *tree = avl_tree_initialize(10);
+  tree = avl_tree_insert(tree, 30);
+  tree = avl_tree_insert(tree, 20);
+
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->left->value, is_equal_to(10));
+  assert_that(tree->right->value, is_equal_to(30));
+}
+
+Ensure(delete_handles_left_left_case) {
+  /*
+        (z)                   (y)
+        / \                /      \
+      (y) (T4)          (X)        (z)
+      / \       -->   /    \      /   \
+    (x) (T3)        (T1)  (T2)  (T3)  (T4)
+    / \
+  (T1) (T2)
+
+  Delete (37):
+
+        (30)                           (20)
+        /  \                         /      \
+      (20) (35)                  (10)        (30)
+      / \     \           -->   /    \      /   \
+    (10) (25) *(37)            (5)  (15)  (25)  (35)
+    / \
+  (5) (15)
+  */
+
+  AVLTree *tree = avl_tree_initialize(30);
+  tree = avl_tree_insert(tree, 35);
+  tree = avl_tree_insert(tree, 20);
+  tree = avl_tree_insert(tree, 10);
+  tree = avl_tree_insert(tree, 25);
+  tree = avl_tree_insert(tree, 37);
+  tree = avl_tree_insert(tree, 15);
+  tree = avl_tree_insert(tree, 5);
+
+  tree = avl_tree_delete(tree, 37);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->left->value, is_equal_to(10));
+  assert_that(tree->left->left->value, is_equal_to(5));
+  assert_that(tree->left->right->value, is_equal_to(15));
+
+  assert_that(tree->right->value, is_equal_to(30));
+  assert_that(tree->right->left->value, is_equal_to(25));
+  assert_that(tree->right->right->value, is_equal_to(35));
+}
+
+Ensure(delete_handles_left_right_case) {
+  /*
+        (z)                   (x)
+        / \                 /     \
+      (y) (T4)           (y)       (z)
+      /  \        -->   /   \     /   \
+    (T1)  (x)         (T1) (T2) (T3) (T4)
+         /   \
+      (T2)  (T3)
+
+  Delete (37):
+
+        (30)                           (25)
+        /  \                         /      \
+      (20) (35)                  (20)        (30)
+      / \     \           -->   /    \      /   \
+    (10) (25) *(37)           (10)  (22)  (27)  (35)
+          / \
+        (22) (27)
+  */
+  AVLTree *tree = avl_tree_initialize(30);
+  tree = avl_tree_insert(tree, 20);
+  tree = avl_tree_insert(tree, 35);
+  tree = avl_tree_insert(tree, 10);
+  tree = avl_tree_insert(tree, 37);
+  tree = avl_tree_insert(tree, 25);
+  tree = avl_tree_insert(tree, 22);
+  tree = avl_tree_insert(tree, 27);
+
+  tree = avl_tree_delete(tree, 37);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(25));
+  assert_that(tree->left->value, is_equal_to(20));
+  assert_that(tree->left->left->value, is_equal_to(10));
+  assert_that(tree->left->right->value, is_equal_to(22));
+
+  assert_that(tree->right->value, is_equal_to(30));
+  assert_that(tree->right->left->value, is_equal_to(27));
+  assert_that(tree->right->right->value, is_equal_to(35));
+}
+
+Ensure(delete_handles_right_right_case) {
+  /*
+        (z)                       (y)
+        / \                    /       \
+     (T4) (y)                (z)        (x)
+          / \       -->     /   \      /   \
+       (T3) (x)          (T4)  (T3)  (T2)  (T1)
+            / \
+         (T2) (T1)
+
+
+        (20)                      (30)
+        / \                    /       \
+     (15) (30)               (20)      (35)
+     /     / \      -->     /   \      /   \
+  *(10) (25) (35)        (15)  (25)  (33)  (37)
+              / \
+           (33) (37)
+  */
+  AVLTree *tree = avl_tree_initialize(20);
+
+  tree = avl_tree_insert(tree, 30);
+  tree = avl_tree_insert(tree, 15);
+  tree = avl_tree_insert(tree, 10);
+  tree = avl_tree_insert(tree, 20);
+  tree = avl_tree_insert(tree, 25);
+  tree = avl_tree_insert(tree, 35);
+  tree = avl_tree_insert(tree, 33);
+  tree = avl_tree_insert(tree, 37);
+
+  tree = avl_tree_delete(tree, 10);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(30));
+
+  assert_that(tree->left->value, is_equal_to(20));
+  assert_that(tree->left->left->value, is_equal_to(15));
+  assert_that(tree->left->right->value, is_equal_to(25));
+
+  assert_that(tree->right->value, is_equal_to(35));
+  assert_that(tree->right->left->value, is_equal_to(33));
+  assert_that(tree->right->right->value, is_equal_to(37));
+}
+
+Ensure(delete_handles_right_left) {
+  /*
+        (z)                       (x)
+        /   \                   /       \
+      (T4)  (y)               (z)       (y)
+            / \              /  \      /   \
+          (x) (T1)   -->  (T4)  (T3) (T2)  (T1)
+          / \
+      (T3) (T2)
+
+
+        (20)                       (22)
+        /   \                   /       \
+      (15)  (25)               (20)      (25)
+      /      / \              /  \      /   \
+  *(10)  (22)  (30)   -->  (15)  (21) (23)  (30)
+        /  \
+     (21)  (23)
+  */
+
+  AVLTree *tree = avl_tree_initialize(20);
+  tree = avl_tree_insert(tree, 15);
+  tree = avl_tree_insert(tree, 25);
+  tree = avl_tree_insert(tree, 10);
+  tree = avl_tree_insert(tree, 22);
+  tree = avl_tree_insert(tree, 30);
+  tree = avl_tree_insert(tree, 21);
+  tree = avl_tree_insert(tree, 23);
+
+  tree = avl_tree_delete(tree, 10);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(22));
+  assert_that(tree->left->value, is_equal_to(20));
+  assert_that(tree->left->left->value, is_equal_to(15));
+  assert_that(tree->left->right->value, is_equal_to(21));
+
+  assert_that(tree->right->value, is_equal_to(25));
+  assert_that(tree->right->left->value, is_equal_to(23));
+  assert_that(tree->right->right->value, is_equal_to(30));
+}
+
+Ensure(delete_handles_a_complicated_and_large_tree) {
+  int items[] = {44, 17, 62, 10, 32, 50, 78, 21, 48,
+                 54, 72, 88, 45, 49, 52, 56, 81, 92};
+  unsigned int length = sizeof(items) / sizeof(items[0]);
+  AVLTree *tree = NULL;
+
+  for (int i = 0; i < length; i++)
+    tree = avl_tree_insert(tree, items[i]);
+
+  tree = avl_tree_delete(tree, 32);
+
+  assert_that(tree->value, is_equal_to(62));
+}
+
+Ensure(delete_handles_a_complicated_and_small_tree) {
+  int items[] = {9, 1, 10, 0, 5, 11, -1, 2, 6};
+  unsigned int length = sizeof(items) / sizeof(items[0]);
+  AVLTree *tree = NULL;
+
+  for (int i = 0; i < length; i++)
+    tree = avl_tree_insert(tree, items[i]);
+
+  tree = avl_tree_delete(tree, 10);
+
+  assert_that(tree->value, is_equal_to(1));
+}
+
+Ensure(delete_returns_a_null_root) {
+  AVLTree *tree = avl_tree_delete(NULL, 10);
+
+  assert_that(tree, is_equal_to(NULL));
+}
+
+Ensure(to_rb_tree_returns_a_new_red_black_tree) {
+  /*
+          (20:3)                      (20:b)
+          /    \          -->         /    \
+      (15:2)    (30:2)           (15:b)    (30:b)
+      /    \        \            /   \         \
+  (10:1) (17:1)     (35:1)  (10:r) (17:r)      (35:r)
+   */
+  AVLTree *tree = NULL;
+  RBTree *expected = NULL;
+  int items[] = {20, 15, 30, 10, 17, 35};
+  int length = sizeof(items) / sizeof(items[0]);
+
+  for (int i = 0; i < length; i++) {
+    tree = avl_tree_insert(tree, items[i]);
+    expected = rb_tree_insert(expected, items[i]);
+  }
+
+  RBTree *actual = avl_tree_to_rb_tree(tree);
+
+  assert_that(rb_equals(expected, actual), is_equal_to(true));
+  assert_that(rb_tree_is_valid(actual), is_equal_to(true));
+  assert_that(rb_tree_is_valid(expected), is_equal_to(true));
+}
+
+Ensure(to_rb_tree_handles_trees_with_a_large_depth) {
+  AVLTree *subject = NULL;
+  int n = 100;
+
+  for (int i = 0; i < n; i++)
+    subject = avl_tree_insert(subject, i);
+
+  RBTree *actual = avl_tree_to_rb_tree(subject);
+
+  assert_that(rb_tree_is_valid(actual), is_equal_to(true));
+
+  for (int i = 0; i < n; i++) {
+    RBTree *node = rb_tree_find(actual, i);
+
+    assert_that(node, is_not_equal_to(NULL));
+    assert_that(node->value, is_equal_to(i));
+  }
+}
+
+TestSuite *avl_tree_tests() {
+  TestSuite *x = create_test_suite();
+  add_test(x, initialize_returns_new_tree);
+
+  add_test(x, size_returns_zero);
+
+  add_test(x, insert_changes_size);
+  add_test(x, insert_changes_height);
+  add_test(x, insert_creates_a_new_root);
+  add_test(x, insert_performs_a_left_rotation);
+  add_test(x, insert_performs_a_right_rotation);
+  add_test(x, insert_performs_a_left_right_rotation);
+  add_test(x, insert_performs_a_right_left_rotation);
+
+  add_test(x, delete_handles_left_left_case);
+  add_test(x, delete_handles_left_right_case);
+  add_test(x, delete_handles_right_right_case);
+  add_test(x, delete_handles_right_left);
+  add_test(x, delete_handles_a_complicated_and_large_tree);
+  add_test(x, delete_handles_a_complicated_and_small_tree);
+  add_test(x, delete_returns_a_null_root);
+
+  add_test(x, to_rb_tree_returns_a_new_red_black_tree);
+  add_test(x, to_rb_tree_handles_trees_with_a_large_depth);
+  return x;
+}
+
+TestSuite *btree_tests();
+TestSuite *graph_tests();
+TestSuite *matrix_tests();
+TestSuite *meldable_heap_tests();
+TestSuite *rb_tree_tests();
+TestSuite *sort_tests();
+
+int main(int argc, char **argv) {
+  TestSuite *suite = create_test_suite();
+  add_suite(suite, avl_tree_tests());
+  add_suite(suite, btree_tests());
+  add_suite(suite, graph_tests());
+  add_suite(suite, matrix_tests());
+  add_suite(suite, meldable_heap_tests());
+  add_suite(suite, rb_tree_tests());
+  add_suite(suite, sort_tests());
+  return run_test_suite(suite, create_text_reporter());
+}
src/03/btree.c
@@ -0,0 +1,108 @@
+#include "btree.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * Print a visual representation of an binary tree.
+ *
+ * @param tree The subtree to print
+ * @param level The level in the tree that this subtree is in
+ */
+static void inspect(BTree *tree, int level) {
+  if (!tree)
+    return;
+
+  for (int i = 0; i < level; i++)
+    printf("  ");
+
+  printf("%2d\n", tree->data);
+  inspect(tree->left, level + 1);
+  inspect(tree->right, level + 1);
+}
+
+/**
+ * Initializes an instance of an binary tree.
+ *
+ * @param data The value to assign to the new node in the tree.
+ * @return Returns the new binary tree node instance.
+ */
+BTree *btree_initialize(int data) {
+  BTree *tree = malloc(sizeof(BTree));
+  tree->left = NULL;
+  tree->right = NULL;
+  tree->data = data;
+  return tree;
+}
+
+/**
+ * Inserts a new value into a binary subtree.
+ *
+ * @param tree The subtree to attempt to insert a new value into.
+ * @param data The data to insert into the tree.
+ * @return Returns the new root of the subtree.
+ */
+BTree *btree_insert(BTree *tree, int data) {
+  if (!tree)
+    return btree_initialize(data);
+
+  if (data <= tree->data)
+    if (tree->left)
+      btree_insert(tree->left, data);
+    else
+      tree->left = btree_initialize(data);
+  else if (tree->right)
+    btree_insert(tree->right, data);
+  else
+    tree->right = btree_initialize(data);
+
+  return tree;
+}
+
+/**
+ * Returns the height of a binary subtree.
+ *
+ * @param tree The subtree to interrogate.
+ * @return The height of the subtree
+ */
+int btree_height(BTree *tree) {
+  if (tree == NULL)
+    return 0;
+
+  int left = btree_height(tree->left);
+  int right = btree_height(tree->right);
+
+  return (left > right) ? left + 1 : right + 1;
+}
+
+/**
+ * Prints a visual inspection of
+ * a binary tree for debugging purposes to stdout.
+ *
+ * @param tree The tree to visualize
+ */
+void btree_inspect(BTree *tree) { inspect(tree, 0); }
+
+int btree_leaves(BTree *tree) {
+  if (tree == NULL)
+    return 0;
+
+  if (tree->left == NULL && tree->right == NULL)
+    return 1;
+
+  return btree_leaves(tree->left) + btree_leaves(tree->right);
+}
+
+/**
+ * Generates a binary tree with a desired number of leaf
+ * nodes.
+ *
+ * @param leaves The total number of leaf nodes to generate in the tree.
+ * @return Returns a new binary tree.
+ */
+BTree *btree_generate(int leaves) {
+  BTree *tree = NULL;
+
+  while (btree_leaves(tree) < leaves)
+    tree = btree_insert(tree, rand());
+  return tree;
+}
src/03/btree.h
@@ -0,0 +1,11 @@
+typedef struct node {
+  struct node *left;
+  struct node *right;
+  int data;
+} BTree;
+
+BTree *btree_initialize(int data);
+BTree *btree_insert(BTree *tree, int data);
+int btree_height(BTree *tree);
+void btree_inspect(BTree *tree);
+BTree *btree_generate(int leaves);
src/03/btree_test.c
@@ -0,0 +1,37 @@
+#include "btree.h"
+#include "rb_tree.h"
+#include <cgreen/cgreen.h>
+#include <math.h>
+#include <string.h>
+
+Ensure(initialize_returns_new_btree) {
+  BTree *tree = btree_initialize(10);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->data, is_equal_to(10));
+}
+
+Ensure(height_returns_height_of_tree) {
+  BTree *tree = NULL;
+
+  int n = 10;
+  for (int i = 0; i < n; ++i)
+    tree = btree_insert(tree, i);
+
+  assert_that(btree_height(tree), is_equal_to(n));
+}
+
+Ensure(tree_with_k_leaves_has_height_of_log_k) {
+  for (int k = 0; k < 500; ++k)
+    assert_that(btree_height(btree_generate(k)) >= log2(k), is_equal_to(true));
+}
+
+TestSuite *btree_tests() {
+  TestSuite *x = create_test_suite();
+
+  add_test(x, initialize_returns_new_btree);
+  add_test(x, height_returns_height_of_tree);
+  add_test(x, tree_with_k_leaves_has_height_of_log_k);
+
+  return x;
+}
src/03/graph.c
@@ -0,0 +1,67 @@
+#include "graph.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * Creates a new Vertex for use in a Graph.
+ *
+ * @param label The label to attach to the node.
+ * @return Returns a new vertex
+ */
+Vertex *vertex_initialize(char label) {
+  Vertex *item = malloc(sizeof(Vertex));
+  item->label = label;
+  return item;
+};
+
+/**
+ * Initializes a new Graph
+ *
+ * @return Returns a new instance of a Graph.
+ */
+Graph *graph_initialize(void) {
+  Graph *item = malloc(sizeof(Graph));
+  for (int i = 0; i < 128; ++i)
+    item->vertices[i] = NULL;
+  return item;
+}
+
+/**
+ * Inserts a new vertex into a graph with the provided label.
+ *
+ * @param graph The graph to insert a new vertex into
+ * @param label The label to apply to the new vertex.
+ * @return Returns the new vertex
+ */
+Vertex *graph_add_vertex(Graph *graph, char label) {
+  Vertex *item = vertex_initialize(label);
+  graph->vertices[(int)label] = item;
+  return item;
+}
+
+/**
+ * Updates a adjacency matrix to indicate that an edge exists
+ * between two vertexes.
+ *
+ * @param graph The graph to modify.
+ * @param a The vertex that points to vertex b.
+ * @param b The vertex that vertex a points to.
+ */
+void graph_add_edge(Graph *graph, Vertex *a, Vertex *b) {
+  graph->edges[a->label][b->label] = true;
+}
+
+/**
+ * Returns true or false to specify if vertex `a`
+ * in a graph is connected to vertex `b` in the same
+ * graph.
+ *
+ * @param graph The graph to investigate
+ * @param a The starting vertext to check
+ * @param b The vertex that vertex a might be pointing at.
+ * @return Returns true if an edge exists between the two vertexes otherwise
+ * false.
+ */
+bool graph_has_edge(Graph *graph, Vertex *a, Vertex *b) {
+  return graph->edges[a->label][b->label];
+}
src/03/graph.h
@@ -0,0 +1,15 @@
+#include <stdbool.h>
+
+typedef struct {
+  char label;
+} Vertex;
+
+typedef struct {
+  Vertex *vertices[128];
+  bool edges[128][128];
+} Graph;
+
+Graph *graph_initialize(void);
+Vertex *graph_add_vertex(Graph *graph, char label);
+void graph_add_edge(Graph *graph, Vertex *a, Vertex *b);
+bool graph_has_edge(Graph *graph, Vertex *a, Vertex *b);
src/03/graph_test.c
@@ -0,0 +1,74 @@
+#include "graph.h"
+#include <cgreen/cgreen.h>
+#include <string.h>
+
+Ensure(initialize_returns_a_new_graph) {
+  Graph *graph = graph_initialize();
+
+  assert_that(graph, is_not_equal_to(NULL));
+  for (int i = 0; i < 128; ++i)
+    assert_that(graph->vertices[i], is_equal_to(NULL));
+}
+
+Ensure(add_vertex_returns_a_new_vertex) {
+  Graph *graph = graph_initialize();
+  char label = 'a';
+  Vertex *a = graph_add_vertex(graph, label);
+
+  assert_that(a, is_not_equal_to(NULL));
+  assert_that(graph->vertices[(int)label], is_equal_to(a));
+}
+
+Ensure(add_vertex_adds_max_number_of_verticies_to_graph) {
+  Graph *graph = graph_initialize();
+
+  for (int i = 0; i < 128; ++i) {
+    Vertex *item = graph_add_vertex(graph, (char)i);
+    assert_that(item, is_not_equal_to(NULL));
+    assert_that(graph->vertices[i], is_equal_to(item));
+  }
+}
+
+Ensure(add_edge_connects_two_vertices) {
+  Graph *graph = graph_initialize();
+
+  graph_add_edge(graph, graph_add_vertex(graph, 'a'),
+                 graph_add_vertex(graph, 'b'));
+
+  assert_that(graph->edges['a']['b'], is_equal_to(true));
+  assert_that(graph->edges['b']['a'], is_equal_to(false));
+}
+
+Ensure(has_edge_returns_true) {
+  Graph *graph = graph_initialize();
+  Vertex *a = graph_add_vertex(graph, 'a');
+  Vertex *b = graph_add_vertex(graph, 'b');
+
+  graph_add_edge(graph, a, b);
+
+  assert_that(graph_has_edge(graph, a, b), is_equal_to(true));
+}
+
+Ensure(has_edge_returns_false) {
+  Graph *graph = graph_initialize();
+  Vertex *a = graph_add_vertex(graph, 'a');
+  Vertex *b = graph_add_vertex(graph, 'b');
+  Vertex *c = graph_add_vertex(graph, 'c');
+
+  graph_add_edge(graph, a, b);
+
+  assert_that(graph_has_edge(graph, a, c), is_equal_to(false));
+}
+
+TestSuite *graph_tests() {
+  TestSuite *x = create_test_suite();
+
+  add_test(x, add_edge_connects_two_vertices);
+  add_test(x, add_vertex_adds_max_number_of_verticies_to_graph);
+  add_test(x, add_vertex_returns_a_new_vertex);
+  add_test(x, has_edge_returns_true);
+  add_test(x, has_edge_returns_false);
+  add_test(x, initialize_returns_a_new_graph);
+
+  return x;
+}
src/03/Makefile
@@ -0,0 +1,37 @@
+#!/usr/bin/make -f
+SHELL=/bin/sh
+
+CC=clang
+TEST_LIBS = -lcgreen -lm
+
+BUILDDIR := build
+OBJS := $(addprefix $(BUILDDIR)/,avl_tree.o rb_tree.o sort.o graph.o matrix.o meldable_heap.o btree.o)
+TEST_OBJS := $(addprefix $(BUILDDIR)/,avl_tree_test.o rb_tree_test.o sort_test.o graph_test.o matrix_test.o meldable_heap_test.o btree_test.o)
+
+$(BUILDDIR)/%.o : %.c
+	$(COMPILE.c) $(OUTPUT_OPTION) $<
+
+.PHONY: all
+all: $(OBJS) $(BUILDDIR)/main.o
+	$(CC) $(OBJS) $(BUILDDIR)/main.o $(TEST_LIBS) -o $(BUILDDIR)/program
+
+.PHONY: test
+test: $(OBJS) $(TEST_OBJS)
+	$(CC) $(OBJS) $(TEST_OBJS) $(TEST_LIBS) -o $(BUILDDIR)/test
+
+$(OBJS): | $(BUILDDIR)
+
+$(TEST_OBJS): | $(BUILDDIR)
+
+$(BUILDDIR):
+	mkdir $(BUILDDIR)
+
+.PHONY: clean
+clean:
+	rm -fr build
+
+run : all
+	./build/program
+
+run_test : test
+	cgreen-runner -c -v $(BUILDDIR)/test
src/03/matrix.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+char labels[26] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+                   'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
+                   's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
+
+/**
+ * Traverses a graph represented as an adjacency matrix
+ * to visit every vertex in the graph and traverse each
+ * edge in both directions only once.
+ *
+ * @param n The # of vertexes in the graph
+ * @param graph An adjacency matrix that represents the graph
+ * @param visited An array that keeps track of which vertexes have been visited
+ * @param vertex The current vertex to traverse.
+ */
+void matrix_traverse(int n, int graph[n][n], int visited[n], int vertex) {
+  printf("->(%c)", labels[vertex]);
+  visited[vertex] = 1;
+
+  for (int edge = 0; edge < n; ++edge) {
+    if (!visited[edge] && graph[vertex][edge] > 0) {
+      graph[vertex][edge] = 0;
+      matrix_traverse(n, graph, visited, edge);
+      graph[edge][vertex] = 0;
+      printf("->(%c)", labels[vertex]);
+    }
+  }
+  for (int edge = 0; edge < n; ++edge) {
+    if (graph[vertex][edge] > 0 && graph[edge][vertex] > 0) {
+      graph[vertex][edge] = 0;
+      matrix_traverse(n, graph, visited, edge);
+      graph[edge][vertex] = 0;
+      printf("->(%c)", labels[vertex]);
+    }
+  }
+}
+
+/**
+ * Prints a visual representation of an
+ * adjacency matrix to stdout out for debugging purposes.
+ *
+ * @param n The number of vertexes in the graph.
+ * @param graph The adjacency matrix that represents the graph.
+ */
+void matrix_inspect(int n, int graph[n][n]) {
+  printf("\n");
+
+  printf("| ");
+  for (int i = 0; i < n; ++i)
+    printf("|%c", labels[i]);
+  printf("|\n");
+
+  for (int i = 0; i < n; ++i) {
+    printf("|%c|", labels[i]);
+    for (int j = 0; j < n; ++j)
+      printf("%d|", graph[i][j]);
+    printf("\n");
+  }
+}
src/03/matrix.h
@@ -0,0 +1,3 @@
+
+void matrix_traverse(int n, int graph[n][n], int visited[n], int vertex);
+void matrix_inspect(int n, int graph[n][n]);
src/03/matrix_test.c
@@ -0,0 +1,41 @@
+#include "matrix.h"
+#include <cgreen/cgreen.h>
+#include <string.h>
+
+Ensure(every_edge_is_traversed_in_both_directions_at_least_once) {
+  int n = 16;
+  int visited[16] = {0};
+  int graph[16][16] = {
+      {0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+      {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+      {0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+      {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+      {1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
+      {1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
+      {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0},
+      {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0},
+      {0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0},
+      {0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0},
+      {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0},
+      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+      {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
+      {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0},
+      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1},
+      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0},
+  };
+
+  matrix_traverse(n, graph, visited, 0);
+  printf("\n");
+
+  for (int i = 0; i < n; ++i)
+    for (int j = 0; j < n; ++j)
+      assert_that(graph[i][j], is_equal_to(0));
+}
+
+TestSuite *matrix_tests() {
+  TestSuite *x = create_test_suite();
+
+  add_test(x, every_edge_is_traversed_in_both_directions_at_least_once);
+
+  return x;
+}
src/03/meldable_heap.c
@@ -0,0 +1,122 @@
+#include "meldable_heap.h"
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * Compares two integers and returns -1, 0, 1.
+ * If a is equal to b then 0 is returned.
+ * If a is greater than b then 1 is returned.
+ * If a is less than b then -1 is returned.
+ *
+ * @param a An integer
+ * @param b Another integer
+ * @return Returns 0, 1, or -1.
+ */
+static int compare(int a, int b) { return (a < b) ? -1 : ((a > b) ? 1 : 0); }
+
+/**
+ * Print a visual representation of a heap.
+ *
+ * @param heap The subtree to print
+ * @param level The level in the heap that this subtree is in
+ */
+static void print_tree(MeldableHeap *heap, int level) {
+  for (int i = 0; i < level; i++)
+    printf(" ");
+
+  if (heap) {
+    printf("(%d)\n", heap->value);
+
+    if (!heap->left && !heap->right)
+      return;
+    print_tree(heap->left, level + 1);
+    print_tree(heap->right, level + 1);
+  } else {
+    printf("( )\n");
+  }
+}
+
+/**
+ * Initializes an instance of an meldable heap.
+ *
+ * @param value The value to assign to the new node in the heap.
+ * @return Returns the new heap node instance.
+ */
+MeldableHeap *meldable_heap_initialize(int value) {
+  MeldableHeap *heap = malloc(sizeof(MeldableHeap));
+  heap->left = NULL;
+  heap->right = NULL;
+  heap->parent = NULL;
+  heap->value = value;
+  return heap;
+};
+
+/**
+ * Adds a new value into a heap.
+ *
+ * @param heap The subtree to attempt to insert a new value into.
+ * @param value The value to insert.
+ * @return Returns the new root of the subtree.
+ */
+MeldableHeap *meldable_heap_add(MeldableHeap *heap, int value) {
+  MeldableHeap *root =
+      meldable_heap_merge(meldable_heap_initialize(value), heap);
+  root->parent = NULL;
+  return root;
+}
+
+/**
+ * Merges to meldable heaps into a single heap and returns the
+ * root of the new heap.
+ *
+ * @param h1 A heap
+ * @param h2 Another heap
+ * @return Returns the merged heap
+ */
+MeldableHeap *meldable_heap_merge(MeldableHeap *h1, MeldableHeap *h2) {
+  if (h1 == NULL)
+    return h2;
+  if (h2 == NULL)
+    return h1;
+
+  if (compare(h2->value, h1->value) < 0)
+    return meldable_heap_merge(h2, h1);
+
+  if (rand() % 2 == 0) {
+    h1->left = meldable_heap_merge(h1->left, h2);
+    h1->left->parent = h1;
+  } else {
+    h1->right = meldable_heap_merge(h1->right, h2);
+    h1->right->parent = h1;
+  }
+  return h1;
+}
+
+/**
+ * Prints a visual inspection of
+ * a heap for debugging purposes to stdout.
+ *
+ * @param heap The heap to visualize
+ */
+void meldable_heap_inspect(MeldableHeap *heap) { print_tree(heap, 0); }
+
+/**
+ * Removes a value from a meldable heap.
+ *
+ * @param heap The subtree to remove
+ */
+void meldable_heap_remove(MeldableHeap *heap) {
+  MeldableHeap *replacement = meldable_heap_merge(heap->left, heap->right);
+
+  if (replacement)
+    replacement->parent = heap->parent;
+
+  if (!heap->parent)
+    return;
+
+  if (heap->parent->left == heap)
+    heap->parent->left = replacement;
+  else
+    heap->parent->right = replacement;
+}
src/03/meldable_heap.h
@@ -0,0 +1,12 @@
+typedef struct mnode {
+  struct mnode *left;
+  struct mnode *parent;
+  struct mnode *right;
+  int value;
+} MeldableHeap;
+
+MeldableHeap *meldable_heap_initialize(int value);
+MeldableHeap *meldable_heap_add(MeldableHeap *heap, int value);
+MeldableHeap *meldable_heap_merge(MeldableHeap *heap, MeldableHeap* other);
+void meldable_heap_inspect(MeldableHeap *heap);
+void meldable_heap_remove(MeldableHeap *heap);
src/03/meldable_heap_test.c
@@ -0,0 +1,101 @@
+#include "meldable_heap.h"
+#include <cgreen/cgreen.h>
+#include <string.h>
+
+Ensure(add_inserts_item_into_right_subtree) {
+  MeldableHeap *heap = meldable_heap_initialize(5);
+  heap = meldable_heap_add(heap, 3);
+
+  assert_that(heap->value, is_equal_to(3));
+  assert_that(heap->right->value, is_equal_to(5));
+}
+
+Ensure(add_inserts_item_into_left_subtree) {
+  MeldableHeap *heap = meldable_heap_initialize(5);
+  heap = meldable_heap_add(heap, 8);
+
+  assert_that(heap->value, is_equal_to(5));
+  assert_that(heap->right->value, is_equal_to(8));
+}
+
+/*
+          (1)
+        /      \
+      (3)      (2)
+     /  \     /   \
+  (10)  (6) (7)   (4)
+           /  \   /
+         (9)  (8)(5)
+*/
+Ensure(add_inserts_multiple_items_into_the_subtree) {
+  MeldableHeap *heap = NULL;
+
+  for (int i = 1; i <= 10; ++i)
+    heap = meldable_heap_add(heap, i);
+
+  assert_that(heap->value, is_equal_to(1));
+
+  assert_that(heap->right->value, is_equal_to(2));
+  assert_that(heap->right->right->value, is_equal_to(4));
+  assert_that(heap->right->right->left->value, is_equal_to(5));
+
+  assert_that(heap->right->left->value, is_equal_to(7));
+  assert_that(heap->right->left->left->value, is_equal_to(9));
+  assert_that(heap->right->left->right->value, is_equal_to(8));
+
+  assert_that(heap->left->value, is_equal_to(3));
+  assert_that(heap->left->left->value, is_equal_to(10));
+  assert_that(heap->left->right->value, is_equal_to(6));
+}
+
+/*
+          (1)
+        /      \
+      (3)      (2)
+     /  \     /   \
+  (10)  (6) (7)   (4)
+           /  \   /
+         (9)  (8)(5)
+
+         to
+
+          (1)
+        /      \
+      (3)      (2)
+     /  \     /   \
+  (10)  (6)       (4)
+           /  \   /
+         (9)  (8)(5)
+*/
+Ensure(remove_removes_the_node_from_the_tree) {
+  MeldableHeap *heap = NULL;
+
+  for (int i = 1; i <= 10; ++i)
+    heap = meldable_heap_add(heap, i);
+
+  meldable_heap_remove(heap->right->left);
+
+  assert_that(heap->value, is_equal_to(1));
+
+  assert_that(heap->right->value, is_equal_to(2));
+  assert_that(heap->right->right->value, is_equal_to(4));
+  assert_that(heap->right->right->left->value, is_equal_to(5));
+
+  assert_that(heap->right->left->value, is_equal_to(8));
+  assert_that(heap->right->left->left->value, is_equal_to(9));
+  assert_that(heap->right->left->right, is_equal_to(NULL));
+
+  assert_that(heap->left->value, is_equal_to(3));
+  assert_that(heap->left->left->value, is_equal_to(10));
+  assert_that(heap->left->right->value, is_equal_to(6));
+}
+
+TestSuite *meldable_heap_tests() {
+  TestSuite *x = create_test_suite();
+
+  add_test(x, add_inserts_item_into_right_subtree);
+  add_test(x, add_inserts_item_into_left_subtree);
+  add_test(x, add_inserts_multiple_items_into_the_subtree);
+  add_test(x, remove_removes_the_node_from_the_tree);
+  return x;
+}
src/03/rb_tree.c
@@ -0,0 +1,399 @@
+#include "rb_tree.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Implementation derived from:
+ * * https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#Insertion
+ */
+
+/**
+ * Returns the larger integer between the two provided as arguments.
+ *
+ * @param a An integer value to compare
+ * @param b Another integer value to compare
+ * @return Returns the larger value
+ */
+static int max(int a, int b) { return a == b ? a : (a > b ? a : b); }
+
+/**
+ * Number of black nodes to leaf.
+ *
+ * @param tree The node to traverse down to a leaf.
+ * @return the # of black nodes from the given node to a leaf.
+ */
+static int depth(RBTree *tree) {
+  int total = 1;
+
+  while (tree) {
+    if (tree->colour == black)
+      total += 1;
+    tree = tree->left;
+  }
+  return total;
+}
+
+/**
+ * Determines if a provided subtree is the root.
+ *
+ * @param node The subtree to investigate
+ * @param Returns tree when the node is the root otherwise false.
+ */
+static bool is_root(RBTree *node) { return node->parent == NULL; }
+
+/**
+ * Returns the parent node of a node.
+ *
+ * @param node The node to investigate.
+ * @return The parent of the node or NULL.
+ */
+static RBTree *parent_of(RBTree *node) { return node ? node->parent : NULL; }
+
+/**
+ * Returns the root of a subtree
+ *
+ * @param node The subtree to investigate
+ * @return Returns the root of the subtree
+ */
+static RBTree *root_of(RBTree *node) {
+  RBTree *current = node;
+  RBTree *next = parent_of(current);
+
+  while (next) {
+    current = next;
+    next = parent_of(current);
+  }
+  return current;
+}
+
+/**
+ * Returns the grand parent node of a node.
+ *
+ * @param node The node to investigate.
+ * @return The grand parent of the node or NULL.
+ */
+static RBTree *grand_parent_of(RBTree *node) {
+  return parent_of(parent_of(node));
+}
+
+/**
+ * Returns a sibling node of a given node.
+ *
+ * @param node The node to investigate.
+ * @return The sibling of the node or NULL.
+ */
+static RBTree *sibling_of(RBTree *node) {
+  RBTree *parent = parent_of(node);
+
+  if (!parent)
+    return NULL;
+
+  return node == parent->left ? parent->right : parent->left;
+}
+
+/**
+ * Returns a pibling (aunt/uncle) node of a given node.
+ *
+ * @param node The node to investigate.
+ * @return The pibling of the node or NULL.
+ */
+static RBTree *pibling_of(RBTree *node) { return sibling_of(parent_of(node)); }
+
+static void rb_rotate_left(RBTree *tree) {
+  RBTree *tmp = tree->right;
+  RBTree *parent = parent_of(tree);
+
+  tree->right = tmp->left;
+  tmp->left = tree;
+  tree->parent = tmp;
+
+  if (tree->right)
+    tree->right->parent = tree;
+
+  if (parent) {
+    if (tree == parent->left)
+      parent->left = tmp;
+    else if (tree == parent->right)
+      parent->right = tmp;
+  }
+  tmp->parent = parent;
+}
+
+/**
+ * Performs a right rotation on a subtree
+ *
+ * @param tree The subtree to perform the rotation on
+ */
+static void rb_rotate_right(RBTree *tree) {
+  RBTree *tmp = tree->left;
+  RBTree *parent = parent_of(tree);
+
+  tree->left = tmp->right;
+  tmp->right = tree;
+  tree->parent = tmp;
+
+  if (tree->left)
+    tree->left->parent = tree;
+
+  if (parent) {
+    if (tree == parent->left)
+      parent->left = tmp;
+    else if (tree == parent->right)
+      parent->right = tmp;
+  }
+  tmp->parent = parent;
+}
+
+/**
+ * Performs any repairs necessary on a subtree
+ *
+ * @param tree The subtree to perform a repair on
+ */
+static void repair_from(RBTree *tree) {
+  RBTree *parent = parent_of(tree);
+  RBTree *pibling = pibling_of(tree);
+
+  if (parent == NULL || parent->colour == black) {
+    return;
+  }
+
+  if (pibling && pibling->colour == red) {
+    parent->colour = black;
+    pibling->colour = black;
+    RBTree *grand_parent = grand_parent_of(tree);
+    if (grand_parent->parent)
+      grand_parent->colour = red;
+    repair_from(grand_parent_of(tree));
+  } else {
+    RBTree *grand_parent = grand_parent_of(tree);
+
+    if (!grand_parent)
+      return;
+    if (tree == parent->right && parent == grand_parent->left) {
+      rb_rotate_left(parent);
+    } else if (tree == parent->left && parent == grand_parent->right) {
+      rb_rotate_right(parent);
+      tree = tree->right;
+    }
+
+    parent = parent_of(tree);
+    grand_parent = grand_parent_of(tree);
+
+    if (tree == parent->left) {
+      rb_rotate_right(grand_parent);
+    } else {
+      rb_rotate_left(grand_parent);
+    }
+    parent->colour = black;
+    if (grand_parent->parent)
+      grand_parent->colour = red;
+  }
+}
+
+/**
+ * Compares two integers and returns -1, 0, 1.
+ * If a is equal to b then 0 is returned.
+ * If a is greater than b then 1 is returned.
+ * If a is less than b then -1 is returned.
+ *
+ * @param a An integer
+ * @param b Another integer
+ * @return Returns 0, 1, or -1.
+ */
+static int compare(int a, int b) { return a == b ? 0 : a < b ? -1 : 1; }
+
+/**
+ * Inserts a new node into a subtree.
+ *
+ * @param tree The subtree to attempt to insert a new value into.
+ * @param node The new node to insert.
+ */
+static void insert(RBTree *root, RBTree *node) {
+  if (!root)
+    return;
+
+  if (compare(node->value, root->value) < 0) {
+    if (root->left)
+      insert(root->left, node);
+    else {
+      root->left = node;
+      node->parent = root;
+    }
+  } else {
+    if (root->right)
+      insert(root->right, node);
+    else {
+      root->right = node;
+      node->parent = root;
+    }
+  }
+}
+
+/**
+ * Print a visual representation of a tree.
+ *
+ * @param tree The subtree to print
+ * @param level The level in the tree that this subtree is in
+ */
+static void print_tree(RBTree *tree, int level) {
+  for (int i = 0; i < level; i++)
+    printf(" ");
+
+  if (tree) {
+    printf("(%d%c H:%d)\n", tree->value, tree->colour == red ? 'R' : 'B',
+           rb_tree_height(tree));
+
+    if (!tree->left && !tree->right)
+      return;
+    print_tree(tree->left, level + 1);
+    print_tree(tree->right, level + 1);
+  } else {
+    printf("( )\n");
+  }
+}
+
+/**
+ * Initializes an instance of a tree.
+ *
+ * @param value The value to assign to the new node in the tree.
+ * @param color The colour to assign to the new node in the tree.
+ * @return Returns the new tree node instance.
+ */
+RBTree *rb_tree_initialize_with(int value, enum Colour colour) {
+  RBTree *tree = malloc(sizeof(RBTree));
+  tree->colour = colour;
+  tree->left = NULL;
+  tree->parent = NULL;
+  tree->right = NULL;
+  tree->value = value;
+  return tree;
+}
+
+/**
+ * Initializes an instance of a tree with a default colour of black.
+ *
+ * @param value The value to assign to the new node in the tree.
+ * @return Returns the new tree node instance.
+ */
+RBTree *rb_tree_initialize(int value) {
+  return rb_tree_initialize_with(value, black);
+}
+
+/**
+ * Inserts a new value into a subtree.
+ *
+ * @param tree The subtree to attempt to insert a new value into.
+ * @param value The value to insert.
+ * @return Returns the new root of the subtree.
+ */
+RBTree *rb_tree_insert(RBTree *tree, int value) {
+  if (tree == NULL)
+    return rb_tree_initialize(value);
+
+  RBTree *node = rb_tree_initialize_with(value, red);
+  insert(tree, node);
+  repair_from(node);
+  return root_of(node);
+}
+
+/**
+ * Prints a visual inspection of
+ * a tree for debugging purposes to stdout.
+ *
+ * @param tree The tree to visualize
+ */
+void rb_tree_inspect(RBTree *tree) { print_tree(tree, 0); }
+
+int rb_tree_size(RBTree *tree) {
+  int total = 0;
+  if (tree == NULL)
+    return total;
+  if (tree->left)
+    total += rb_tree_size(tree->left);
+  if (tree->right)
+    total += rb_tree_size(tree->right);
+  return total + 1;
+}
+
+/**
+ * Determines if two trees are equal by verifying
+ * that each descendant node in each subtree have
+ * the same value and colour.
+ *
+ * @param tree A tree to compare
+ * @param other_tree Another tree to compare
+ * @return Returns true when both subtrees are equal otherwise false
+ */
+bool rb_equals(RBTree *tree, RBTree *other_tree) {
+  if (!tree || !other_tree)
+    return tree == other_tree;
+
+  if (tree->parent && !other_tree->parent)
+    return false;
+
+  if (!tree->parent && other_tree->parent)
+    return false;
+
+  if (tree->parent && tree->parent->value != other_tree->parent->value)
+    return false;
+
+  return tree->value == other_tree->value &&
+         tree->colour == other_tree->colour &&
+         rb_equals(tree->left, other_tree->left) &&
+         rb_equals(tree->right, other_tree->right);
+}
+
+/**
+ * Determines if a tree matches the properties
+ * necessary to claim to be a valid Red Black tree.
+ *
+ * 1. root must be black
+ * 2. there are the same # of black nodes on every root to the leaf path.
+ * 3. No two red nodes are adjacent.
+ *
+ * @param tree The tree to investigate
+ * @return Returns true if the tree meets the criteria otherwise false.
+ */
+bool rb_tree_is_valid(RBTree *tree) {
+  if (tree == NULL)
+    return true;
+
+  if (is_root(tree) && tree->colour == red)
+    return false;
+
+  if (tree->colour == red && tree->parent->colour == red)
+    return false;
+
+  if (depth(tree->left) != depth(tree->right))
+    return false;
+
+  return rb_tree_is_valid(tree->left) && rb_tree_is_valid(tree->right);
+}
+
+/**
+ * Returns the height of a subtree.
+ *
+ * @param tree The subtree to investigate
+ * @return Returns the height of the subtree
+ */
+int rb_tree_height(RBTree *tree) {
+  if (!tree)
+    return 1;
+
+  return 1 + max(rb_tree_height(tree->left), rb_tree_height(tree->right));
+}
+
+/**
+ * Searches for a node in a subtree with a particular value.
+ *
+ * @param t The subtree to search.
+ * @param value The value to search for
+ * @returns Returns the node containing the value otherwise NULL
+ */
+RBTree *rb_tree_find(RBTree *t, int value) {
+  if (!t)
+    return NULL;
+
+  int x = compare(value, t->value);
+  return x == 0 ? t : rb_tree_find(x < 0 ? t->left : t->right, value);
+}
src/03/rb_tree.h
@@ -0,0 +1,24 @@
+#include <stdbool.h>
+
+enum Colour {
+  black = 0x01,
+  red = 0x00,
+};
+
+typedef struct rb_node {
+  struct rb_node *left;
+  struct rb_node *parent;
+  struct rb_node *right;
+  enum Colour colour;
+  int value;
+} RBTree;
+
+RBTree *rb_tree_initialize(int value);
+RBTree *rb_tree_initialize_with(int value, enum Colour colour);
+RBTree *rb_tree_insert(RBTree *tree, int value);
+RBTree *rb_tree_find(RBTree *tree, int value);
+bool rb_equals(RBTree *tree, RBTree *other_tree);
+bool rb_tree_is_valid(RBTree *tree);
+int rb_tree_size(RBTree *tree);
+void rb_tree_inspect(RBTree *tree);
+int rb_tree_height(RBTree *tree);
src/03/rb_tree_test.c
@@ -0,0 +1,338 @@
+#include "rb_tree.h"
+#include <cgreen/cgreen.h>
+#include <string.h>
+/*
+ * Every node has a colour. red or black
+ * Root of the tree is always black.
+ * There are no two adjacent red nodes. (red node cannot have red parent or
+child)
+ * Every path from root to child NULL node has same # of black nodes.
+ *
+ *
+ * 1. every node is coloured red or black.
+ * 2. All leaves (nils) are black.
+ * 3. Every red node has black children. black nodes can have any color
+children.
+ * 4. From any node, the # of black nodes on any path to the leaves is the same.
+(same # of black nodes from top to bottom)
+
+height: logn if perfectly balanced.
+
+            (B)
+          /     \
+       (R)       (R)
+      /   \     /   \
+    (B)  (B)  (B)   (B)
+   /  \
+(nil) (nil)
+ */
+
+Ensure(initialize_returns_a_new_tree) {
+  RBTree *tree = rb_tree_initialize(10);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(10));
+  assert_that(tree->colour, is_equal_to(black));
+}
+
+Ensure(insert_returns_a_new_tree_when_null) {
+  RBTree *tree = rb_tree_insert(NULL, 20);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->colour, is_equal_to(black));
+}
+
+Ensure(insert_adds_a_new_item_to_right_subtree) {
+  RBTree *tree = rb_tree_initialize(10);
+
+  tree = rb_tree_insert(tree, 20);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(10));
+  assert_that(tree->colour, is_equal_to(black));
+  assert_that(tree->right, is_not_equal_to(NULL));
+  assert_that(tree->right->value, is_equal_to(20));
+}
+
+Ensure(insert_adds_a_new_item_to_left_subtree) {
+  RBTree *tree = rb_tree_initialize(20);
+
+  tree = rb_tree_insert(tree, 10);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->colour, is_equal_to(black));
+  assert_that(tree->left, is_not_equal_to(NULL));
+  assert_that(tree->left->value, is_equal_to(10));
+}
+
+Ensure(rb_tree_insert_performs_a_right_rotation) {
+  /*
+        (30)          (20:b)
+        /            /    \
+     (20)     ->  (10:r)    (30:r)
+     /
+  (10)
+
+  */
+  RBTree *tree = rb_tree_initialize(30);
+
+  tree = rb_tree_insert(tree, 20);
+  tree = rb_tree_insert(tree, 10);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->colour, is_equal_to(black));
+
+  assert_that(tree->left->value, is_equal_to(10));
+  assert_that(tree->left->colour, is_equal_to(red));
+
+  assert_that(tree->right->value, is_equal_to(30));
+  assert_that(tree->right->colour, is_equal_to(red));
+
+  assert_that(rb_tree_is_valid(tree), is_equal_to(true));
+}
+
+Ensure(rb_tree_insert_performs_a_left_rotation) {
+  /*
+  (10)                 (20:b)
+     \                 /    \
+     (20)     ->  (10:r)    (30:r)
+       \
+       (30)
+  */
+
+  RBTree *tree = rb_tree_initialize(10);
+  tree = rb_tree_insert(tree, 20);
+  tree = rb_tree_insert(tree, 30);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->colour, is_equal_to(black));
+  assert_that(tree->left->value, is_equal_to(10));
+  assert_that(tree->left->colour, is_equal_to(red));
+  assert_that(tree->right->value, is_equal_to(30));
+  assert_that(tree->right->colour, is_equal_to(red));
+
+  assert_that(rb_tree_is_valid(tree), is_equal_to(true));
+}
+
+Ensure(rb_tree_insert_repaints_the_new_node) {
+  /*
+       (20:b)                   (20:b)
+       /    \                  /     \
+    (10:r)  (30:r)  -->   (10:b)    (30:b)
+    /                     /
+  (5:r)                 (5:r)
+  */
+
+  RBTree *tree = rb_tree_initialize(20);
+  tree = rb_tree_insert(tree, 10);
+  tree = rb_tree_insert(tree, 30);
+  tree = rb_tree_insert(tree, 5);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(20));
+  assert_that(tree->colour, is_equal_to(black));
+
+  assert_that(tree->left->value, is_equal_to(10));
+  assert_that(tree->left->colour, is_equal_to(black));
+
+  assert_that(tree->left->left->value, is_equal_to(5));
+  assert_that(tree->left->left->colour, is_equal_to(red));
+
+  assert_that(tree->right->value, is_equal_to(30));
+  assert_that(tree->right->colour, is_equal_to(black));
+
+  assert_that(rb_tree_is_valid(tree), is_equal_to(true));
+}
+
+Ensure(rb_tree_insert_handles_large_trees) {
+  RBTree *tree = NULL;
+  int n = 100;
+
+  for (int i = n; i > 0; i--)
+    tree = rb_tree_insert(tree, i);
+
+  assert_that(tree, is_not_equal_to(NULL));
+  assert_that(tree->value, is_equal_to(69));
+  assert_that(tree->colour, is_equal_to(black));
+
+  assert_that(rb_tree_size(tree), is_equal_to(n));
+  assert_that(rb_tree_is_valid(tree), is_equal_to(true));
+}
+
+Ensure(equals_returns_false_when_tree_is_NULL) {
+  assert_that(rb_equals(NULL, rb_tree_initialize(10)), is_equal_to(false));
+}
+
+Ensure(equals_returns_false_when_other_tree_is_NULL) {
+  assert_that(rb_equals(rb_tree_initialize(10), NULL), is_equal_to(false));
+}
+
+Ensure(equals_returns_true_when_both_trees_are_NULL) {
+  assert_that(rb_equals(NULL, NULL), is_equal_to(true));
+}
+
+Ensure(equals_returns_false_when_tree_has_one_node) {
+  RBTree *tree = rb_tree_initialize(20);
+  RBTree *other_tree = rb_tree_initialize(10);
+
+  assert_that(rb_equals(tree, other_tree), is_equal_to(false));
+}
+
+Ensure(equals_returns_false_when_tree_has_one_node_with_different_colours) {
+  RBTree *tree = rb_tree_initialize(20);
+  RBTree *other_tree = rb_tree_initialize(20);
+
+  tree->colour = black;
+  other_tree->colour = red;
+
+  assert_that(rb_equals(tree, other_tree), is_equal_to(false));
+}
+
+Ensure(equals_returns_true_when_tree_has_one_node) {
+  RBTree *tree = rb_tree_initialize(20);
+  RBTree *other_tree = rb_tree_initialize(20);
+
+  assert_that(rb_equals(tree, other_tree), is_equal_to(true));
+}
+
+Ensure(equals_returns_true_when_root_and_left_subtree_are_equal) {
+  RBTree *tree = rb_tree_initialize(20);
+  tree = rb_tree_insert(tree, 10);
+
+  RBTree *other_tree = rb_tree_initialize(20);
+  other_tree = rb_tree_insert(other_tree, 10);
+
+  assert_that(rb_equals(tree, other_tree), is_equal_to(true));
+}
+
+Ensure(equals_returns_false_when_root_and_left_subtree_are_not_equal) {
+  RBTree *tree = rb_tree_initialize(20);
+  tree = rb_tree_insert(tree, 10);
+
+  RBTree *other_tree = rb_tree_initialize(20);
+  other_tree = rb_tree_insert(other_tree, 15);
+
+  assert_that(rb_equals(tree, other_tree), is_equal_to(false));
+}
+
+Ensure(equals_returns_false_when_root_and_right_subtree_are_not_equal) {
+  RBTree *tree = rb_tree_initialize(20);
+  tree = rb_tree_insert(tree, 30);
+
+  RBTree *other_tree = rb_tree_initialize(20);
+  other_tree = rb_tree_insert(other_tree, 25);
+
+  assert_that(rb_equals(tree, other_tree), is_equal_to(false));
+}
+
+Ensure(equals_returns_false_when_parent_is_not_equal) {
+  RBTree *tree = rb_tree_initialize(20);
+  tree = rb_tree_insert(tree, 30);
+
+  RBTree *other_tree = rb_tree_initialize(20);
+  other_tree = rb_tree_insert(other_tree, 30);
+
+  other_tree->right->parent = NULL;
+
+  assert_that(rb_equals(tree, other_tree), is_equal_to(false));
+  assert_that(rb_equals(other_tree, tree), is_equal_to(false));
+}
+
+Ensure(is_valid_returns_false_when_root_is_red) {
+  RBTree *tree = rb_tree_initialize(20);
+  tree->colour = red;
+
+  assert_that(rb_tree_is_valid(tree), is_equal_to(false));
+}
+
+Ensure(is_valid_returns_false_when_red_node_has_red_child) {
+  RBTree *tree = NULL;
+
+  for (int i = 10; i > 0; i--)
+    tree = rb_tree_insert(tree, i);
+
+  tree->left->colour = red;
+  tree->left->left->colour = red;
+
+  assert_that(rb_tree_is_valid(tree), is_equal_to(false));
+}
+
+Ensure(
+    is_valid_returns_false_when_each_path_to_leaves_does_not_contain_the_same_number_of_black_nodes) {
+  RBTree *tree = NULL;
+
+  for (int i = 10; i > 0; i--)
+    tree = rb_tree_insert(tree, i);
+
+  tree->left->left->colour = black;
+  assert_that(rb_tree_is_valid(tree), is_equal_to(false));
+}
+
+Ensure(is_valid_return_true) {
+  RBTree *tree = NULL;
+
+  for (int i = 0; i < 100; ++i)
+    tree = rb_tree_insert(tree, i);
+
+  assert_that(rb_tree_is_valid(tree), is_equal_to(true));
+}
+
+Ensure(height_returns_one) {
+  assert_that(rb_tree_height(NULL), is_equal_to(1));
+}
+
+Ensure(height_returns_three_when_left_subtree_is_present) {
+  RBTree *tree = rb_tree_initialize(10);
+  tree = rb_tree_insert(tree, 5);
+
+  assert_that(rb_tree_height(tree), is_equal_to(3));
+}
+
+Ensure(height_returns_three_when_right_subtree_is_present) {
+  RBTree *tree = rb_tree_initialize(10);
+  tree = rb_tree_insert(tree, 15);
+
+  assert_that(rb_tree_height(tree), is_equal_to(3));
+}
+
+TestSuite *rb_tree_tests() {
+  TestSuite *x = create_test_suite();
+
+  add_test(x, initialize_returns_a_new_tree);
+
+  add_test(x, insert_returns_a_new_tree_when_null);
+  add_test(x, insert_adds_a_new_item_to_right_subtree);
+  add_test(x, insert_adds_a_new_item_to_left_subtree);
+  add_test(x, rb_tree_insert_performs_a_right_rotation);
+  add_test(x, rb_tree_insert_performs_a_left_rotation);
+  add_test(x, rb_tree_insert_repaints_the_new_node);
+  add_test(x, rb_tree_insert_handles_large_trees);
+
+  add_test(x, equals_returns_false_when_tree_is_NULL);
+  add_test(x, equals_returns_false_when_other_tree_is_NULL);
+  add_test(x, equals_returns_true_when_both_trees_are_NULL);
+  add_test(x, equals_returns_false_when_tree_has_one_node);
+  add_test(x,
+           equals_returns_false_when_tree_has_one_node_with_different_colours);
+  add_test(x, equals_returns_true_when_tree_has_one_node);
+  add_test(x, equals_returns_true_when_root_and_left_subtree_are_equal);
+  add_test(x, equals_returns_false_when_root_and_left_subtree_are_not_equal);
+  add_test(x, equals_returns_false_when_root_and_right_subtree_are_not_equal);
+  add_test(x, equals_returns_false_when_parent_is_not_equal);
+
+  add_test(x, is_valid_returns_false_when_root_is_red);
+  add_test(x, is_valid_returns_false_when_red_node_has_red_child);
+  add_test(
+      x,
+      is_valid_returns_false_when_each_path_to_leaves_does_not_contain_the_same_number_of_black_nodes);
+  add_test(x, is_valid_return_true);
+
+  add_test(x, height_returns_one);
+  add_test(x, height_returns_three_when_left_subtree_is_present);
+  add_test(x, height_returns_three_when_right_subtree_is_present);
+  return x;
+}
src/03/README.md
@@ -0,0 +1,1011 @@
+# Learning Profile for Assignment #3
+## Computer Science 272: Data Structures and Algorithms
+
+* Name: Mo Khan
+* Student ID: 3431709
+* https://github.com/mokhan/comp-272/tree/master/src/03/README.md
+
+## Question 1
+### Problem Statement
+
+Illustrate that the nodes of any AVL tree T can be
+colored "red" and "black" so that T becomes a
+red-black tree.
+
+```plaintext
+       AVL Tree                   Red-Black Tree
+        (20:3)                      (20:b)
+        /    \          -->         /    \
+    (15:2)    (30:2)           (15:b)    (30:b)
+    /    \        \            /   \         \
+(10:1) (17:1)     (35:1)  (10:r) (17:r)      (35:r)
+```
+
+* perform pre order traversal
+* assign colour of Red/Black node based on height of each AVL node
+
+```plaintext
+Step 1:
+          (20:b)
+
+Step 2:
+          (20:b)
+          /
+      (15:b)
+
+Step 3:
+          (20:b)
+          /
+      (15:b)
+      /
+  (10:r)
+
+Step 4:
+          (20:b)
+          /
+      (15:b)
+      /   \
+  (10:r) (17:r)
+
+Step 5:
+          (20:b)
+          /     \
+      (15:b)    (30:b)
+      /   \
+  (10:r) (17:r)
+
+Step 6:
+          (20:b)
+          /    \
+      (15:b)    (30:b)
+      /   \         \
+  (10:r) (17:r)      (35:r)
+```
+
+### Description of the Code
+
+The function `avl_tree_to_rb_tree` provides an
+implementation of this. To accomplish this
+the code makes two passes down the tree. The
+first pass it used to build a clone of the
+AVL tree as a Red-Black tree with all nodes coloured
+black. The second pass traverses the red-black
+tree and applies the appropriate colour to
+each node in the function `change_colour`.
+
+If the height of the left subtree is less
+than the height of hte right subtree or
+the height is odd then the left child is
+coloured black otherwise red.
+
+The same is applied to the right subtree.
+
+```c
+change_colour(tree->left, left_height < right_height || is_odd(left_height) ? black : red);
+change_colour(tree->right, right_height < left_height || is_odd(right_height) ? black : red);
+```
+
+
+## Question 2
+### Problem Statement
+
+Illustrate that via AVL single rotation, any binary search tree T1 can be
+transformed into another search tree T2 (with the same items).
+
+Left rotation:
+
+```plaintext
+  (10)                  (20)
+    \                  /    \
+    (20)      ->    (10)    (30)
+      \
+      (30)
+```
+
+Right rotation:
+
+```plaintext
+     (30)            (20)
+     /              /   \
+   (20)     -->   (10)  (30)
+   /
+(10)
+```
+
+Left-Right rotation:
+
+```plaintext
+   (30)         (20)
+   /           /    \
+(10)     -> (10)    (30)
+   \
+   (20)
+```
+
+Right-Left rotation:
+
+```plaintext
+(10)             (20)
+    \            /  \
+    (30)  --> (10)  (30)
+   /
+(20)
+```
+
+Give an algorithm to perform this transformation using O(N log N) rotation on average.
+
+See `./avl_tree.c`.
+
+## Question 3
+### Problem Statement
+
+Suppose you are given two sequences S1 and S2 of `n` elements, possibly
+containing duplicates, on which a total order relation is defined.
+
+1. Describe an efficient algorithm for determining if S1 and S2 contain the same set of elements.
+
+Since S1 and S2 has a total order relation defined this means
+that the data is sorted in both sequences.
+
+To tell if the S1 and S2 contain the same set of elements we can use two pointers
+to walk through each item in each sequence one step at a time to compare the values
+at each index to ensure they are a match. As soon as we detect a mismatch
+we know that the sequences do not contain the same set of elements. If we can
+iterate to the end of both sequences at the same time then we have a match.
+
+1. Analyze the running time of this method.
+
+The time complexity is dependent on the size of `n` elements and is
+therefore a linear time algorithm `O(n)`.
+
+The space complexity is constant, `O(1)`, because only two pointers
+are needed to walk through both sequences. The amount of space required
+to perform this algorithm does not change as the input size of `n` changes.
+
+## Question 4
+### Problem Statement
+
+Given sequence 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, sort the sequence using the
+following algorithms, and illustrate the details of the execution of the
+algorithms:
+
+a. merge-sort algorithm.
+
+```plaintext
+[3,1,4,1,5,9,2,6,5,3,5,]
+[3,1,4,1,5,9,]
+[3,1,4,]
+[3,1,]
+[3,]
+[3,1,]
+[1,3,4,]
+[1,3,4,1,5,9,]
+[1,3,4,1,5,]
+[1,3,4,1,]
+[1,3,4,1,5,]
+[1,3,4,1,5,9,]
+[1,1,3,4,5,9,2,6,5,3,5,]
+[1,1,3,4,5,9,2,6,5,]
+[1,1,3,4,5,9,2,6,]
+[1,1,3,4,5,9,2,]
+[1,1,3,4,5,9,2,6,]
+[1,1,3,4,5,9,2,6,5,]
+[1,1,3,4,5,9,2,5,6,3,5,]
+[1,1,3,4,5,9,2,5,6,3,]
+[1,1,3,4,5,9,2,5,6,3,5,]
+```
+
+b. quick-sort algorithm.
+* Choose a partitioning strategy you like to pick a pivot element from the sequence.
+* Analyze how different portioning strategies may impact on the performance of the sorting algorithm.
+
+For choosing a pivot I chose to use the value in the last element of the sequence.
+Alternative, strategies include choosing a random pivot in each sub-sequence.
+
+Using the last item in the sub-sequence as the pivot:
+
+```plaintext
+[3,1,4,1,5,9,2,6,5,3,]
+[3,1,4,1,2,]
+[1,1,]
+[1,]
+[]
+[1,]
+[1,1,]
+[1,1,2,3,4,]
+[1,1,2,]
+[1,1,2,3,3,]
+[1,1,2,3,3,4,5,6,5,9,]
+[1,1,2,3,3,4,]
+[1,1,2,3,3,4,5,5,5,9,]
+[1,1,2,3,3,4,5,5,]
+[1,1,2,3,3,4,5,5,5,6,]
+```
+
+## Question 5
+### Problem Statement
+
+Given the graph shown below, answer the following questions:
+
+1. Illustrate the sequence of vertices of this graph visited using depth-first search traversal starting at vertex `g`.
+1. Illustrate the sequence of vertices of this graph visited using breadth-first search traversal starting at vertex `b`.
+1. Illustrate adjacency list representation and adjacency matrix representation, respectively, for this graph.
+  * What are the advantages and disadvantages of those two representations?
+1. Describe an algorithm to find in the graph a path illustrated below that goes through every edge exactly once in each direction.
+
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+#### Depth First Traversal
+
+Order: g, h, o, p, l, k, n, i, m, j, f, c, d, b, a, e
+
+1. [g]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+2. [g, h]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+3. [g, h, o]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(*)---(p)
+```
+
+4. [g, h, o, p]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(*)---(*)
+```
+
+5. [g, h, o, p, l]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (*)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(*)---(*)
+```
+
+6. [g, h, o, p, l, k]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(*)---(*)
+```
+
+7. [g, h, o, p, l, k, n]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(*)---(*)---(*)
+```
+
+8. [g, h, o, p, l, k, n, i]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(j)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(*)---(*)---(*)
+```
+
+9. [g, h, o, p, l, k, n, i, m]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(j)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+10. [g, h, o, p, l, k, n, i, m, j]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+11. [g, h, o, p, l, k, n, i, m, j, f]
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+12. [g, h, o, p, l, k, n, i, m, j, f, c]
+```plaintext
+(a)---(b)---(*)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+13. [g, h, o, p, l, k, n, i, m, j, f, c, d]
+```plaintext
+(a)---(b)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(e)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+14. [g, h, o, p, l, k, n, i, m, j, f, c, d, b]
+```plaintext
+(a)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(e)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+15. [g, h, o, p, l, k, n, i, m, j, f, c, d, b, a]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(e)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+16. [g, h, o, p, l, k, n, i, m, j, f, c, d, b, a, e]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+#### Breadth First Traversal
+
+Order: [b, a, f, c, e, j, d, i, g, m, n, h, k, o, p, l]
+
+1. [b]
+```plaintext
+(a)---(*)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+2. [b, a]
+```plaintext
+(*)---(*)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+3. [b, a, f]
+```plaintext
+(*)---(*)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(*)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+4. [b, a, f, c]
+```plaintext
+(*)---(*)---(*)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(*)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+5. [b, a, f, c, e]
+```plaintext
+(*)---(*)---(*)---(d)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+6. [b, a, f, c, e, j]
+```plaintext
+(*)---(*)---(*)---(d)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(*)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+7. [b, a, f, c, e, j, d]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(*)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+8. [b, a, f, c, e, j, d, i]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+9. [b, a, f, c, e, j, d, i, g]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+10. [b, a, f, c, e, j, d, i, g, m]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(n)---(o)---(p)
+```
+
+11. [b, a, f, c, e, j, d, i, g, m, n]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(o)---(p)
+```
+
+12. [b, a, f, c, e, j, d, i, g, m, n, h]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(o)---(p)
+```
+
+13. [b, a, f, c, e, j, d, i, g, m, n, h, k]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (l)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(o)---(p)
+```
+
+14. [b, a, f, c, e, j, d, i, g, m, n, h, k, o]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (l)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(p)
+```
+
+15. [b, a, f, c, e, j, d, i, g, m, n, h, k, o, p]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (l)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+16. [b, a, f, c, e, j, d, i, g, m, n, h, k, o, p, l]
+```plaintext
+(*)---(*)---(*)---(*)
+ | \       /     /
+ |  \     /     /
+(*)  \(*)/  (*)/--(*)
+ |     |   / |    /
+ |     |  /  |   /
+(*)---(*)/  (*) / (*)
+ | \         | /   |
+ |  \        |/    |
+(*)  \(*)---(*)---(*)
+```
+
+#### Adjacency List
+
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+
+(a) -> [b, e, f]
+(b) -> [a, f]
+(c) -> [b, d, f]
+(d) -> [c, g]
+(e) -> [a, i]
+(f) -> [a, c, j]
+(g) -> [d, h, j, k]
+(h) -> [g, o]
+(i) -> [e, j, m, n]
+(j) -> [f, g, i]
+(k) -> [g, o]
+(l) -> [p]
+(m) -> [i]
+(n) -> [i, o]
+(o) -> [k, n, p]
+(p) -> [l, o]
+```
+
+Good:
+
+* Space efficient because no space is wasted for edges that do not exist.
+
+Bad:
+
+* A lookup to determine if two vertexes are connected requires a linear time lookup due to the size of the list for a single edge. `O(n)`.
+
+#### Adjacency Matrix
+
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+```plaintext
+-----------------------------------
+| |a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|
+|a|0|1|0|0|1|1|0|0|0|0|0|0|0|0|0|0|
+|b|1|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|c|0|1|0|1|0|1|0|0|0|0|0|0|0|0|0|0|
+|d|0|0|1|0|0|0|1|0|0|0|0|0|0|0|0|0|
+|e|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|
+|f|1|0|1|0|0|0|0|0|0|1|0|0|0|0|0|0|
+|g|0|0|0|1|0|0|0|1|0|1|1|0|0|0|0|0|
+|h|0|0|0|0|0|0|1|0|0|0|0|0|0|0|1|0|
+|i|0|0|0|0|1|0|0|0|0|1|0|0|1|1|0|0|
+|j|0|0|0|0|0|1|1|0|1|0|0|0|0|0|0|0|
+|k|0|0|0|0|0|0|1|0|0|0|0|0|0|0|1|0|
+|l|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|
+|m|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|
+|n|0|0|0|0|0|0|0|0|1|0|0|0|0|0|1|0|
+|o|0|0|0|0|0|0|0|0|0|0|1|0|0|1|0|1|
+|p|0|0|0|0|0|0|0|0|0|0|0|1|0|0|1|0|
+-----------------------------------
+```
+
+Good:
+
+* constant time lookup to see if two vertexes are connected `O(1)`
+
+Bad:
+
+* space inefficient `O(n^2)`
+
+
+An adjacency matrix might be a better choice when space is less important
+than fast lookups. An adjacency list may be a better choice if space is
+a higher priority concern than time.
+
+#### Traverse Every Edge
+
+To traverse every edge in both directions we can use an adjacency matrix
+and iterate through every cell in the matrix. If the cell contains a 1 to
+indicate an edge than we know that we can traverse from the edge at
+that row and column. Both directions will be represented in different cells
+in the matrix.
+
+When we visit each cell in the matrix we can flip the 1 to a 0 to ensure that
+we do not revisit a visited edge.
+
+1. Start at any vertex
+1. Iterate through list of edges.
+1. If the vertex on the other end of the edge has not been visited yet then visit it and loop until all edges are exhausted for the vertex.
+1. Remove the edge from the matrix when visiting a node
+1. Backtrack to previous vertex, and remove the edge.
+1. Visit any edge where you can backtrack safely.
+
+An example of this algorithm can be found in `./matrix.c` with accompanying tests in `./matrix_test.c`.
+
+The graph to traverse is:
+
+```plaintext
+(a)---(b)---(c)---(d)
+ | \       /     /
+ |  \     /     /
+(e)  \(f)/  (g)/--(h)
+ |     |   / |    /
+ |     |  /  |   /
+(i)---(j)/  (k) / (l)
+ | \         | /   |
+ |  \        |/    |
+(m)  \(n)---(o)---(p)
+```
+
+We can build a matrix that will look like the following:
+
+```bash
+| |a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|
+|a|0|1|0|0|1|1|0|0|0|0|0|0|0|0|0|0|
+|b|1|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|c|0|1|0|1|0|1|0|0|0|0|0|0|0|0|0|0|
+|d|0|0|1|0|0|0|1|0|0|0|0|0|0|0|0|0|
+|e|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|
+|f|1|0|1|0|0|0|0|0|0|1|0|0|0|0|0|0|
+|g|0|0|0|1|0|0|0|1|0|1|1|0|0|0|0|0|
+|h|0|0|0|0|0|0|1|0|0|0|0|0|0|0|1|0|
+|i|0|0|0|0|1|0|0|0|0|1|0|0|1|1|0|0|
+|j|0|0|0|0|0|1|1|0|1|0|0|0|0|0|0|0|
+|k|0|0|0|0|0|0|1|0|0|0|0|0|0|0|1|0|
+|l|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|
+|m|0|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|
+|n|0|0|0|0|0|0|0|0|1|0|0|0|0|0|1|0|
+|o|0|0|0|0|0|0|0|0|0|0|1|0|0|1|0|1|
+|p|0|0|0|0|0|0|0|0|0|0|0|1|0|0|1|0|
+```
+
+The order of traversal will be:
+
+```plaintext
+->(a)->(b)->(c)->(d)->(g)->(h)->(o)->(k)->(g)->(j)->(f)->(a)->(e)->(i)->(m)-
+                                                                           |
+|---------------------------------------------------------------------------
+->(i)->(n)->(o)->(p)->(l)->(p)->(o)->(n)->(i)->(j)->(i)->(e)->(a)->(f)->(c)-
+                                                                           |
+|---------------------------------------------------------------------------
+->(f)->(j)->(g)->(k)->(o)->(h)->(g)->(d)->(c)->(b)->(a)
+```
+
+After the traversal the matrix will have zero edges.
+
+```bash
+| |a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|
+|a|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|b|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|c|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|d|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|e|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|f|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|g|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|h|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|i|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|j|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|k|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|l|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|m|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|n|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|o|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+|p|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+```
+
+## Question 6
+### Problem Statement
+
+Why does the method `remove(x)` in the `RedBlackTree` implementation
+perform the assignment `u:parent = w:parent?`
+Shouldn’t this already be done by the call to `splice(w)`?
+
+It is possible that more than one rotation needs to occur so assigning the new parent
+is necessary.
+
+```java
+boolean remove(T x)
+{
+  Node<T> u = findLast(x);
+  if (u == nil || compare(u.x, x) != 0)
+    return false;
+  Node<T> w = u.right;
+  if (w == nil) {
+    w = u;
+    u = w.left;
+  } else {
+    while (w.left != nil)
+      w = w.left;
+    u.x = w.x;
+    u = w.right;
+  }
+  splice(w);
+  u.colour += w.colour;
+  u.parent = w.parent;
+  removeFixup(u);
+  return true;
+}
+
+void removeFixup(Node<T> u) {
+  while (u.colour > black) {
+    if (u == r) {
+      u.colour = black;
+    } else if (u.parent.left.colour == red) {
+      u = removeFixupCase1(u);
+    } else if (u == u.parent.left) {
+      u = removeFixupCase2(u);
+    } else {
+      u = removeFixupCase3(u);
+    }
+  }
+  if (u != r) {
+    Node<T> w = u.parent;
+    if (w.right.colour == red && w.left.colour == black) {
+      flipLeft(w);
+    }
+  }
+}
+```
+Source [Open Data Structures](https://www.aupress.ca/app/uploads/120226_99Z_Morin_2013-Open_Data_Structures.pdf)
+
+## Question 7
+### Problem Statement
+
+Implement the `remove(u)` method, that removes the node `u` from a
+`MeldableHeap`. This method should run in `O(log n)` expected time.
+
+```java
+class MeldableHeap {
+  Node<T> merge(Node<T> h1, Node<T> h2) {
+    if (h1 == nil) return h2;
+    if (h2 == nil) return h1;
+    if (compare(h2.x, h1.x) < 0) return merge(h2, h1);
+
+    if (rand.nextBoolean()) {
+      h1.left = merge(h1.left, h2);
+      h1.left.parent = h1;
+    } else {
+      h1.right = merge(h1.right, h2);
+      h1.right.parent = h1;
+    }
+    return h1;
+  }
+
+  boolean add(T x) {
+    Node<T> u = newNode();
+    u.x = x;
+    r = merge(u, r);
+    r.parent = nil;
+    n++;
+    return true;
+  }
+
+  T remove() {
+    T x = r.x;
+    r = merge(r.left, r.right);
+    if (r != nil) r.parent = nil;
+    n--;
+    return x;
+  }
+}
+```
+[Source](https://www.aupress.ca/app/uploads/120226_99Z_Morin_2013-Open_Data_Structures.pdf)
+
+An implementation of `meldable_heap_remove(u)` can be found in `./meldable_heap.c`.
+
+## Question 8
+### Problem Statement
+
+Prove that a binary tree with `k` leaves has height at least `log k`.
+
+The proof can be derived with the following.
+Suppose we have a function `h` that takes input `k`
+and returns a tree with `k` leaves.
+
+For each positive natural number we can
+assert that the height of the tree must be greater
+than or equal to `log2(k)`.
+
+```plaintext
+for each positive natural number
+  assert(height(h(k)) >= log2(k))
+```
+
+An example test is provided in `btree_test.c` that
+asserts that this holds true for the first
+500 positive integers.
+
+```c
+for (int k = 0; k < 500; ++k)
+  assert_that(btree_height(btree_generate(k)) >= log2(k), is_equal_to(true));
+```
src/03/sort.c
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * Prints a visual dump of an array of
+ * items to stdout out for debugging.
+ *
+ * @param items The items to inspect
+ * @param n The total # of items in the array.
+ */
+static void dump(int *items, int n) {
+  printf("[");
+  for (int i = 0; i < n; ++i)
+    printf("%d,", items[i]);
+  printf("]\n");
+}
+
+/**
+ * Merges two subsequences of an array.
+ *
+ * @params items A pointer to the start of an array of items
+ * @param min The starting index of the left sub sequence.
+ * @param mid The starting index of the right sub sequence.
+ * @param max The ending index of the right sub sequence.
+ */
+static void _merge(int *items, int min, int mid, int max) {
+  int length = (max - min) + 1;
+  int tmp[length];
+  int j = min, k = mid;
+
+  for (int i = 0; i < length; i++) {
+    if (j < mid && k <= max)
+      if (items[j] < items[k])
+        tmp[i] = items[j++];
+      else
+        tmp[i] = items[k++];
+    else if (j >= mid)
+      tmp[i] = items[k++];
+    else
+      tmp[i] = items[j++];
+  }
+
+  for (int i = 0; i < length; i++)
+    items[min + i] = tmp[i];
+}
+
+/**
+ * Performs a recursive merge sort of items in an array.
+ *
+ * @param items An array of integers.
+ * @param min The starting index of a subsequence to sort
+ * @param max The ending index of a subsequence to sort
+ */
+static void _merge_sort(int *items, int min, int max) {
+  if (min >= max)
+    return;
+
+  int mid = min + (max - min) / 2;
+  _merge_sort(items, min, mid);
+  _merge_sort(items, mid + 1, max);
+  _merge(items, min, mid + 1, max);
+}
+
+/**
+ * Partitions a sequence into two subsequences.
+ *
+ * @param items An array of integers to partition
+ * @param min The starting index of the sequence to partition
+ * @param max The ending index of the sequence to partition
+ * @return Returns the index that can be used as the partition point for the
+ * sequence.
+ */
+static int partition(int *items, int min, int max) {
+  int pivot = items[max];
+  int index = min - 1;
+  int tmp;
+
+  for (int j = min; j < max; j++) {
+    if (items[j] < pivot) {
+      index++;
+      tmp = items[index];
+      items[index] = items[j];
+      items[j] = tmp;
+    }
+  }
+  tmp = items[index + 1];
+  items[index + 1] = items[max];
+  items[max] = tmp;
+
+  return index + 1;
+}
+
+/**
+ * Performs a recursive quick sort on an array of items.
+ *
+ * @param items An array of integers
+ * @param min The starting index of a subsequence to sort
+ * @param max The ending index of a subsequence to sort
+ */
+static void _quick_sort(int *items, int min, int max) {
+  if (min >= max)
+    return;
+
+  int index = partition(items, min, max);
+  _quick_sort(items, min, index - 1);
+  _quick_sort(items, index + 1, max);
+}
+
+/**
+ * Performs a merge sort on an array of integers.
+ *
+ * @param items An array of integers
+ * @param length The # of items in the array of integers
+ */
+void merge_sort(int *items, int length) {
+  if (!items || length <= 0)
+    return;
+
+  _merge_sort(items, 0, length - 1);
+}
+
+/**
+ * Performs a quick sort on an array of integers.
+ *
+ * @param items An array of integers
+ * @param length The # of items in the array of integers
+ */
+void quick_sort(int *items, int length) {
+  if (!items || length <= 0)
+    return;
+
+  _quick_sort(items, 0, length - 1);
+}
src/03/sort.h
@@ -0,0 +1,2 @@
+void merge_sort(int *items, int length);
+void quick_sort(int *items, int length);
src/03/sort_test.c
@@ -0,0 +1,136 @@
+#include "sort.h"
+#include <cgreen/cgreen.h>
+#include <string.h>
+
+Ensure(one_equals_one) { assert_that(1, is_equal_to(1)); }
+
+Ensure(merge_sort_sorts_a_null_list) { merge_sort(NULL, 0); }
+
+Ensure(merge_sort_sorts_an_empty_list) {
+  int items[] = {};
+
+  merge_sort(items, 0);
+
+  assert_that(sizeof(items), is_equal_to(0));
+}
+
+Ensure(merge_sort_sorts_a_list_with_one_item) {
+  int items[] = {100};
+
+  merge_sort(items, 1);
+
+  assert_that(sizeof(items), is_equal_to(sizeof(int)));
+  assert_that(items[0], is_equal_to(100));
+}
+
+Ensure(merge_sort_sorts_a_list_with_two_items) {
+  int items[] = {100, 10};
+
+  merge_sort(items, 2);
+
+  assert_that(items[0], is_equal_to(10));
+  assert_that(items[1], is_equal_to(100));
+}
+
+Ensure(merge_sort_sorts_three_unique_items) {
+  int items[] = {3, 1, 4};
+
+  merge_sort(items, sizeof(items) / sizeof(int));
+
+  assert_that(items[0], is_equal_to(1));
+  assert_that(items[1], is_equal_to(3));
+  assert_that(items[2], is_equal_to(4));
+}
+
+Ensure(merge_sort_sorts_many_items) {
+  int items[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
+
+  merge_sort(items, sizeof(items) / sizeof(int));
+
+  assert_that(items[0], is_equal_to(1));
+  assert_that(items[1], is_equal_to(1));
+  assert_that(items[2], is_equal_to(2));
+  assert_that(items[3], is_equal_to(3));
+  assert_that(items[4], is_equal_to(3));
+  assert_that(items[5], is_equal_to(4));
+  assert_that(items[6], is_equal_to(5));
+  assert_that(items[7], is_equal_to(5));
+  assert_that(items[8], is_equal_to(5));
+  assert_that(items[9], is_equal_to(6));
+  assert_that(items[10], is_equal_to(9));
+}
+
+Ensure(quick_sort_sorts_a_null_list) { quick_sort(NULL, 0); }
+
+Ensure(quick_sort_sorts_an_empty_list) {
+  int items[] = {};
+
+  quick_sort(items, 0);
+
+  assert_that(sizeof(items), is_equal_to(0));
+}
+
+Ensure(quick_sort_sorts_a_list_with_one_item) {
+  int items[] = {100};
+
+  quick_sort(items, 1);
+
+  assert_that(items[0], is_equal_to(100));
+}
+
+Ensure(quick_sort_sorts_a_list_with_two_items) {
+  int items[] = {100, 10};
+
+  quick_sort(items, 2);
+
+  assert_that(items[0], is_equal_to(10));
+  assert_that(items[1], is_equal_to(100));
+}
+
+Ensure(quick_sort_sorts_three_unique_items) {
+  int items[] = {3, 1, 4};
+
+  quick_sort(items, sizeof(items) / sizeof(int));
+
+  assert_that(items[0], is_equal_to(1));
+  assert_that(items[1], is_equal_to(3));
+  assert_that(items[2], is_equal_to(4));
+}
+
+Ensure(quick_sort_sorts_many_items) {
+  int items[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
+
+  quick_sort(items, sizeof(items) / sizeof(int));
+
+  assert_that(items[0], is_equal_to(1));
+  assert_that(items[1], is_equal_to(1));
+  assert_that(items[2], is_equal_to(2));
+  assert_that(items[3], is_equal_to(3));
+  assert_that(items[4], is_equal_to(3));
+  assert_that(items[5], is_equal_to(4));
+  assert_that(items[6], is_equal_to(5));
+  assert_that(items[7], is_equal_to(5));
+  assert_that(items[8], is_equal_to(5));
+  assert_that(items[9], is_equal_to(6));
+  assert_that(items[10], is_equal_to(9));
+}
+
+TestSuite *sort_tests() {
+  TestSuite *x = create_test_suite();
+  add_test(x, one_equals_one);
+
+  add_test(x, merge_sort_sorts_a_null_list);
+  add_test(x, merge_sort_sorts_an_empty_list);
+  add_test(x, merge_sort_sorts_a_list_with_one_item);
+  add_test(x, merge_sort_sorts_a_list_with_two_items);
+  add_test(x, merge_sort_sorts_three_unique_items);
+  add_test(x, merge_sort_sorts_many_items);
+
+  add_test(x, quick_sort_sorts_a_null_list);
+  add_test(x, quick_sort_sorts_an_empty_list);
+  add_test(x, quick_sort_sorts_a_list_with_one_item);
+  add_test(x, quick_sort_sorts_a_list_with_two_items);
+  add_test(x, quick_sort_sorts_three_unique_items);
+  add_test(x, quick_sort_sorts_many_items);
+  return x;
+}
Makefile
@@ -12,3 +12,4 @@ test :
 
 fmt :
 	clang-format -i src/**/**/*.c
+	clang-format -i src/**/*.c