diff --git a/a2/src/edu/wmich/cs3310/a2/Controller.java b/a2/src/edu/wmich/cs3310/a2/Controller.java
index c372e44674a1d784533254bef2b325d949f8d53b..86db3c6aeb1345be71b8855e19686013d761def2 100644
--- a/a2/src/edu/wmich/cs3310/a2/Controller.java
+++ b/a2/src/edu/wmich/cs3310/a2/Controller.java
@@ -19,16 +19,16 @@ public class Controller {
     private String nameString;
     private Random random = new Random();
     private Scanner reader = new Scanner(System.in);
-    char[] bubbleArray;
-    char[] selectArray;
-    char[] mergeArray;
-    char[] insertArray;
-    char[] bInsertArray;
-    CharQueue bubbleList = new CharQueue();
-    CharQueue selectList = new CharQueue();
-    CharQueue mergeList = new CharQueue();
-    CharQueue insertList = new CharQueue();
-    CharQueue bInsertList = new CharQueue();
+    private char[] bubbleArray;
+    private char[] selectArray;
+    private char[] mergeArray;
+    private char[] insertArray;
+    private char[] bInsertArray;
+    private CharQueue bubbleList = new CharQueue();
+    private CharQueue selectList = new CharQueue();
+    private CharQueue mergeList = new CharQueue();
+    private CharQueue insertList = new CharQueue();
+    private CharQueue bInsertList = new CharQueue();
 
     //endregion Variables
 
@@ -58,6 +58,7 @@ public class Controller {
         nameString = GetUserInput("Enter a name: ");
 
         PopulateData();
+        PrintAllDataStructures();
         SortAllDataStructures();
         PrintAllDataStructures();
     }
@@ -115,65 +116,519 @@ public class Controller {
      * Calls sorting on all available data structures.
      */
     protected void SortAllDataStructures() {
+        System.out.println("Sorting...");
         ArrayBubbleSort();
         ListBubbleSort();
         ArraySelectionSort();
         ListSelectionSort();
-        ArrayMergeSort();
-        ListMergeSort();
+        ArrayMergeSort(0, (charNumber - 1));
+        mergeList = ListMergeSort(mergeList,0, (charNumber - 1));
         ArrayInsertionSort();
         ListInsertionSort();
         ArrayBinaryInsertionSort();
         ListBinaryInsertionSort();
     }
 
-    protected void ArrayBubbleSort() {
 
+    /**
+     * Calls bubble sort on appropriate array.
+     */
+    protected void ArrayBubbleSort() {
+        int index = 0;
+        int maxIndex = charNumber;
+        boolean wasSorted = true;
+        char tempChar;
+
+        // Loop until one iteration does NOT change values.
+        while (wasSorted) {
+            wasSorted = false;
+
+            // Loop through all unsorted values.
+            while (index < (maxIndex - 1)) {
+                // Check current and next values.
+                if (bubbleArray[index] > bubbleArray[index + 1]) {
+                    tempChar = bubbleArray[index];
+                    bubbleArray[index] = bubbleArray[index + 1];
+                    bubbleArray[index + 1] = tempChar;
+                    wasSorted = true;
+                }
+                index++;
+            }
+            index = 0;
+            maxIndex--;
+        }
     }
 
 
+    /**
+     * Calls bubble sort on appropriate linked list.
+     */
     protected void ListBubbleSort() {
-
+        boolean wasSorted = true;
+        char tempChar;
+        CharNode currentNode = bubbleList.headNode();
+        CharNode lastUnsortedNode = bubbleList.tailNode();
+
+        // Loop until one iteration does NOT change values.
+        while (wasSorted) {
+            wasSorted = false;
+
+            // Loop through all unsorted values.
+            while (currentNode != lastUnsortedNode) {
+                // Check current and next values.
+                if (currentNode.myData() > currentNode.nextNode().myData()) {
+                    tempChar = currentNode.myData();
+                    currentNode.myData(currentNode.nextNode().myData());
+                    currentNode.nextNode().myData(tempChar);
+                    wasSorted = true;
+                }
+                currentNode = currentNode.nextNode();
+            }
+            currentNode = bubbleList.headNode();
+            lastUnsortedNode = lastUnsortedNode.prevNode();
+        }
     }
 
 
+    /**
+     * Calls selection sort on appropriate linked list.
+     */
     protected void ArraySelectionSort() {
+        int index;
+        int currentIndex;
+        int selectedIndex;
+        int lastUnsortedIndex = (charNumber - 1);
+        char tempChar;
+        char[] tempArray = new char[charNumber];
+
+        // Loop until all values are sorted.
+        while (lastUnsortedIndex > 0) {
+            selectedIndex = 0;
+            currentIndex = 1;
+
+            // Find index of "highest" letter.
+            for (index = 0; index < lastUnsortedIndex; index++) {
+
+                // Compare values.
+                if (selectArray[currentIndex] > selectArray[selectedIndex]) {
+                    selectedIndex = currentIndex;
+                }
+                currentIndex++;
+            }
 
+            // Move found value to end of "unsorted" values.
+            tempChar = selectArray[lastUnsortedIndex];
+            selectArray[lastUnsortedIndex] = selectArray[selectedIndex];
+            selectArray[selectedIndex] = tempChar;
+            lastUnsortedIndex--;
+        }
     }
 
 
+    /**
+     * Calls selection sort on appropriate linked list.
+     */
     protected void ListSelectionSort() {
+        int currentIndex;
+        int selectedIndex;
+        CharNode tempNode;
+        CharNode currentNode;
+        CharNode selectedNode;
+        CharQueue tempQueue = new CharQueue();
+
+        // Loop until all values are sorted.
+        while (selectList.headNode() != null) {
+            selectedIndex = 0;
+            currentIndex = 1;
+            selectedNode = selectList.headNode();
+            currentNode = selectedNode.nextNode();
+
+            // Find node of "highest" letter.
+            while(currentNode != null) {
+
+                // Compare values.
+                if (currentNode.myData() < selectedNode.myData()) {
+                    selectedIndex = currentIndex;
+                    selectedNode = currentNode;
+                }
+                currentIndex++;
+                currentNode = currentNode.nextNode();
+            }
 
+            // Remove found node and add to new "sorted" list.
+            tempNode = selectList.Delete(selectedIndex);
+            tempQueue.Enqueue(tempNode.myData());
+        }
+
+        selectList = tempQueue;
     }
 
 
-    protected void ArrayMergeSort() {
+    /**
+     * Calls merge sort on appropriate linked list.
+     */
+    protected void ArrayMergeSort(int lowIndex, int highIndex) {
+        // Base case. If equal or less, back out of recursion.
+        if (highIndex <= lowIndex) {
+            return;
+        }
 
+        // Divide in half and recursively call self on each half. Merge together when done.
+        int midIndex = (lowIndex + highIndex) / 2;
+        ArrayMergeSort(lowIndex, midIndex);
+        ArrayMergeSort((midIndex + 1), highIndex);
+        MergeArray(lowIndex, midIndex, highIndex);
     }
 
 
-    protected void ListMergeSort() {
+    /**
+     * Handles actually merging array parts back together.
+     * @param lowIndex Starting index of first half.
+     * @param midIndex Ending index of first half/starting index of second half.
+     * @param highIndex Ending index of second half.
+     */
+    protected void MergeArray(int lowIndex, int midIndex, int highIndex) {
+        int index;
+        int leftHolder = lowIndex;
+        int rightHolder = midIndex + 1;
+        char[] tempArray = new char[charNumber];
+
+        // Duplicate array.
+        for (index = lowIndex; index <= highIndex; index++) {
+            tempArray[index] = mergeArray[index];
+        }
 
+        // Loop until all passed indexes have been looked at.
+        for (index = lowIndex; index <= highIndex; index++) {
+
+            // Check if left side is done but right is not.
+            if (leftHolder > midIndex) {
+                mergeArray[index] = tempArray[rightHolder];
+                rightHolder++;
+            } else {
+                // Check if right side is done but left is not.
+                if (rightHolder > highIndex) {
+                    mergeArray[index] = tempArray[leftHolder];
+                    leftHolder++;
+                } else {
+                    // Both sides not done. Compare left and right holder values.
+                    if (tempArray[leftHolder] > tempArray[rightHolder]) {
+                        mergeArray[index] = tempArray[rightHolder];
+                        rightHolder++;
+                    } else {
+                        mergeArray[index] = tempArray[leftHolder];
+                        leftHolder++;
+                    }
+                }
+            }
+        }
     }
 
 
-    protected void ArrayInsertionSort() {
+    /**
+     * Calls merge sort on appropriate linked list.
+     * @param unsortedQueue Queue to sort.
+     * @param lowIndex Lowest index for given queue section.
+     * @param highIndex Highest index for given queue section.
+     * @return
+     */
+    protected CharQueue ListMergeSort(CharQueue unsortedQueue, int lowIndex, int highIndex) {
+        int index;
+        int midIndex;
+        CharNode tempNode;
+        CharQueue firstHalf = new CharQueue();
+        CharQueue secondHalf = new CharQueue();
+        CharQueue sortedQueue;
 
+        // Base Case. If list is only one node large, back out of recursion.
+        if ((unsortedQueue.headNode() == null) || (unsortedQueue.headNode().nextNode() == null)) {
+            return unsortedQueue;
+        }
+
+        // Divide in half and recursively call self on each half. Merge together when done.
+        midIndex = (lowIndex + highIndex) / 2;
+
+        // Left half.
+        tempNode = mergeList.Retrieve(lowIndex);
+        for (index = 0; index < ((midIndex + 1) - lowIndex); index++) {
+
+            firstHalf.Enqueue(tempNode.myData());
+            tempNode = tempNode.nextNode();
+        }
+
+        // Right half.
+        tempNode = mergeList.Retrieve(midIndex + 1);
+        for (index = 0; index < (highIndex - midIndex); index++) {
+            secondHalf.Enqueue(tempNode.myData());
+            tempNode = tempNode.nextNode();
+        }
+        firstHalf = ListMergeSort(firstHalf, lowIndex, midIndex);
+        secondHalf = ListMergeSort(secondHalf, (midIndex + 1), highIndex);
+        sortedQueue = MergeList(firstHalf, secondHalf, lowIndex, midIndex, highIndex);
+
+        return  sortedQueue;
     }
 
 
-    protected void ListInsertionSort() {
+    /**
+     * Handles actually merging list parts back together.
+     * @param firstHalf First queue section to merge.
+     * @param secondHalf Second queue section to merge.
+     * @param lowIndex Starting index of first half.
+     * @param midIndex Ending index of first half/starting index of second half.
+     * @param highIndex Ending index of second half.
+     */
+    protected CharQueue MergeList(CharQueue firstHalf, CharQueue secondHalf, int lowIndex, int midIndex, int highIndex) {
+        CharNode tempNode;
+        CharQueue sortedQueue = new CharQueue();
+
+        // Loop until all passed values have been looked at.
+        while ((firstHalf.headNode()) != null || (secondHalf.headNode() != null)) {
+
+            // Check if left side is done but right is not.
+            if (firstHalf.headNode() == null) {
+                tempNode = secondHalf.Dequeue();
+                sortedQueue.Enqueue(tempNode.myData());
+            } else {
+                // Check if right side is done but left is not.
+                if (secondHalf.headNode() == null) {
+                    tempNode = firstHalf.Dequeue();
+                    sortedQueue.Enqueue(tempNode.myData());
+                } else {
+                    // Both sides not done. compare left and right values.
+                    if (firstHalf.headNode().myData() > secondHalf.headNode().myData()) {
+                        tempNode = secondHalf.Dequeue();
+                        sortedQueue.Enqueue(tempNode.myData());
+                    } else {
+                        tempNode = firstHalf.Dequeue();
+                        sortedQueue.Enqueue(tempNode.myData());
+                    }
+                }
+            }
+        }
 
+        return sortedQueue;
+    }
+
+
+    /**
+     * Calls insertion sort on appropriate linked list.
+     */
+    protected void ArrayInsertionSort() {
+        int currentIndex;
+        int tempIndex;
+        int highestIndex = 0;
+        char tempChar;
+
+        // Loop until all values are sorted.
+        for (currentIndex = 1; currentIndex < charNumber; currentIndex++) {
+
+            // Compare values. Continually loop until 0 index is reached or proper order is found.
+            tempIndex = highestIndex;
+            while ((currentIndex > 0) && (insertArray[currentIndex] < insertArray[tempIndex])) {
+                tempChar = insertArray[currentIndex];
+                insertArray[currentIndex] = insertArray[tempIndex];
+                insertArray[tempIndex] = tempChar;
+                tempIndex--;
+                currentIndex--;
+            }
+            highestIndex++;
+            currentIndex = highestIndex;
+        }
     }
 
 
+    /**
+     * Calls insertion sort on appropriate linked list.
+     */
+    protected void ListInsertionSort() {
+        int currentIndex;
+        char tempChar;
+        CharNode currentNode = insertList.headNode().nextNode();
+        CharNode tempNode;
+        CharNode highestNode = insertList.headNode();
+
+        // Loop until all values are sorted.
+        for (currentIndex = 1; currentIndex < charNumber; currentIndex++) {
+            // Compare values. Continually loop until null pointer or proper order is found.
+            tempNode = highestNode;
+            while ((currentNode.prevNode() != null) && (currentNode.myData() < tempNode.myData())) {
+                tempChar = currentNode.myData();
+                currentNode.myData(tempNode.myData());
+                tempNode.myData(tempChar);
+                tempNode = tempNode.prevNode();
+                currentNode = currentNode.prevNode();
+            }
+            highestNode = highestNode.nextNode();
+            currentNode = highestNode.nextNode();
+        }
+    }
+
+
+    /**
+     * Calls binary insertion sort on appropriate linked list.
+     */
     protected void ArrayBinaryInsertionSort() {
+        int currentIndex;
+        int highestIndex = 0;
+
+        // Loop until all values are sorted.
+        for (currentIndex = 1; currentIndex < charNumber; currentIndex++) {
 
+            // Compare values. If difference is found, call binary insert.
+            if (bInsertArray[currentIndex] < bInsertArray[highestIndex]) {
+                ArrayBinaryInsert(0, currentIndex);
+            }
+            highestIndex++;
+        }
     }
-    
 
+
+    /**
+     * Binary search and insert for putting current value into sorted values.
+     * Note that the high index should actually be the value to insert.
+     * @param lowIndex The lower bound for array section.
+     * @param highIndex The higher bound for array section.
+     */
+    protected void ArrayBinaryInsert(int lowIndex, int highIndex) {
+        int tempIndex;
+        int midIndex;
+        char tempChar;
+
+        // Check if end of search.
+        if (lowIndex >= highIndex) {
+
+            // End of search.
+            tempChar = bInsertArray[highIndex];
+            tempIndex = highIndex;
+
+            // Insert value at appropriate location.
+            if (bInsertArray[lowIndex] > tempChar) {
+                bInsertArray[tempIndex] = bInsertArray[lowIndex];
+                tempIndex--;
+            }
+            bInsertArray[tempIndex] = tempChar;
+
+        } else {
+
+            // Still more values to search. Handle accordingly.
+            midIndex = (lowIndex + highIndex) / 2;
+
+            // Check for value match.
+            if (bInsertArray[midIndex] == bInsertArray[highIndex]) {
+                tempChar = bInsertArray[highIndex];
+                tempIndex = highIndex;
+                while (tempIndex > midIndex) {
+                    bInsertArray[tempIndex] = bInsertArray[tempIndex - 1];
+                    tempIndex--;
+                }
+                bInsertArray[midIndex] = tempChar;
+
+            } else {
+                if (bInsertArray[midIndex] > bInsertArray[highIndex]) {
+
+                    // Move all prior values down by one since second half of list was eliminated.
+                    tempIndex = highIndex;
+                    tempChar = bInsertArray[highIndex];
+                    while (tempIndex > midIndex) {
+                        bInsertArray[tempIndex] = bInsertArray[tempIndex - 1];
+                        tempIndex--;
+                    }
+                    bInsertArray[midIndex] = tempChar;
+                    ArrayBinaryInsert(lowIndex, midIndex);
+
+                } else {
+                    ArrayBinaryInsert((midIndex + 1), highIndex);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Calls binary insertion sort on appropriate linked list.
+     */
     protected void ListBinaryInsertionSort() {
+        int currentIndex;
+        CharNode currentNode = bInsertList.headNode().nextNode();
+        CharNode highestNode = bInsertList.headNode();
+
+        // Loop until all values are sorted.
+        for (currentIndex = 1; currentIndex < charNumber; currentIndex++) {
+            // Compare values. Continually loop until null pointer or proper order is found.
+            if (currentNode.myData() < highestNode.myData()) {
+                ListBinaryInsert(bInsertList.headNode(), currentNode, 0, currentIndex);
+            }
+            highestNode = highestNode.nextNode();
+            currentNode = highestNode.nextNode();
+        }
+    }
+
 
+    /**
+     * Binary search and insert for putting current value into sorted values.
+     * Note that the high index should actually be the value to insert.
+     * @param lowNode The lower bound for list section.
+     * @param highNode The upper bound for list section.
+     * @param lowIndex The node number of the lower bound.
+     * @param highIndex The node number of the upper bound.
+     */
+    protected void ListBinaryInsert(CharNode lowNode, CharNode highNode, int lowIndex, int highIndex) {
+        int index;
+        int midIndex;
+        char tempChar;
+        CharNode midNode;
+
+        // Check if end of search.
+        if (lowNode == highNode) {
+
+            // End of search.
+            tempChar = highNode.myData();
+
+            // Insert value at appropriate location.
+            if (lowNode.myData() > tempChar) {
+                lowNode.nextNode().myData(lowNode.myData());
+                highNode = highNode.prevNode();
+            }
+            highNode.myData(tempChar);
+
+        } else {
+
+            // Still more values to search. Handle accordingly.
+            midIndex = (lowIndex + highIndex) / 2;
+            midNode = lowNode;
+            for (index = lowIndex; index < midIndex; index++) {
+                midNode = midNode.nextNode();
+            }
+
+            // Check for value match.
+            if (midNode.myData() == highNode.myData()) {
+
+                tempChar = highNode.myData();
+                while (highNode != midNode.nextNode()) {
+                    highNode.myData(highNode.prevNode().myData());
+                    highNode = highNode.prevNode();
+                }
+                midNode.nextNode().myData(tempChar);
+                ListBinaryInsert(lowNode, midNode, lowIndex, midIndex);
+
+            } else {
+                if (midNode.myData() > highNode.myData()) {
+
+                    // Move all prior values down by one since second half of list was eliminated.
+                    tempChar = highNode.myData();
+                    while (highNode != midNode) {
+                        highNode.myData(highNode.prevNode().myData());
+                        highNode = highNode.prevNode();
+                    }
+                    midNode.myData(tempChar);
+                    ListBinaryInsert(lowNode, midNode, lowIndex, midIndex);
+
+                } else {
+                    ListBinaryInsert((midNode.nextNode()), highNode, (midIndex + 1), highIndex);
+                }
+            }
+        }
     }
 
     //endregion Sorting Methods
@@ -226,13 +681,13 @@ public class Controller {
         index = 0;
         tempNode = bubbleList.headNode();
         System.out.println("Bubble Sorts:");
-        System.out.print("Array: ");
+        System.out.print(" Array: ");
         while (index < charNumber) {
             System.out.print(" " + bubbleArray[index]);
             index++;
         }
         System.out.println();
-        System.out.print("List:  ");
+        System.out.print(" List:  ");
         while (tempNode != null) {
             System.out.print(" " + tempNode.myData());
             tempNode = tempNode.nextNode();
@@ -244,13 +699,13 @@ public class Controller {
         index = 0;
         tempNode = selectList.headNode();
         System.out.println("Selection Sorts:");
-        System.out.print("Array: ");
+        System.out.print(" Array: ");
         while (index < charNumber) {
             System.out.print(" " + selectArray[index]);
             index++;
         }
         System.out.println();
-        System.out.print("List:  ");
+        System.out.print(" List:  ");
         while (tempNode != null) {
             System.out.print(" " + tempNode.myData());
             tempNode = tempNode.nextNode();
@@ -262,13 +717,13 @@ public class Controller {
         index = 0;
         tempNode = mergeList.headNode();
         System.out.println("Merge Sorts:");
-        System.out.print("Array: ");
+        System.out.print(" Array: ");
         while (index < charNumber) {
             System.out.print(" " + mergeArray[index]);
             index++;
         }
         System.out.println();
-        System.out.print("List:  ");
+        System.out.print(" List:  ");
         while (tempNode != null) {
             System.out.print(" " + tempNode.myData());
             tempNode = tempNode.nextNode();
@@ -280,13 +735,13 @@ public class Controller {
         index = 0;
         tempNode = insertList.headNode();
         System.out.println("Insertion Sorts:");
-        System.out.print("Array: ");
+        System.out.print(" Array: ");
         while (index < charNumber) {
             System.out.print(" " + insertArray[index]);
             index++;
         }
         System.out.println();
-        System.out.print("List:  ");
+        System.out.print(" List:  ");
         while (tempNode != null) {
             System.out.print(" " + tempNode.myData());
             tempNode = tempNode.nextNode();
@@ -298,13 +753,13 @@ public class Controller {
         index = 0;
         tempNode = bInsertList.headNode();
         System.out.println("Binary Insertion Sorts:");
-        System.out.print("Array: ");
+        System.out.print(" Array: ");
         while (index < charNumber) {
             System.out.print(" " + bInsertArray[index]);
             index++;
         }
         System.out.println();
-        System.out.print("List:  ");
+        System.out.print(" List:  ");
         while (tempNode != null) {
             System.out.print(" " + tempNode.myData());
             tempNode = tempNode.nextNode();