The algorithmThe idea behind a quicksort is that we have a list of numbers, and like any sorting algorithm, we have to pick a value to put in the right place. In a bubble sort and selection sort, you search the whole array for the largest value and then put that at the end, decreasing the size of the unordered array by one each time. In a quicksort, your goal is to pick the middle value and set it at the right spot in there.
2 6 5 9 3 1 8 4 7Just guess that the middle value in the list is the middle index of the array. This value is 3. Swap the last value and that middle value, and put a pointer starting at the left, and one at the right. Compare each of the values with the 'middle' value. If the value in the left pointer is less than the middle value, then move it to the next value. If not, stop it where it is. For the right pointer, compare its value to the middle value, and if it is greater, then continue. Otherwise stop. If you happen to have both pointers stop, then swap the values of those two pointers and then move both pointers forawrd. Once the left and right meet,you know that's where your middle value needs to be, so put it back in.
Once you've done this, you recursively do the sort again on the two unordered lists to the left and right of the middle value. Both of these are ~1/2 the size of the original list if we get lucky. Keep recursively doing this until you reach your base case of a list of size 1, which is trivially sorted.
2 6 5 9 3 1 8 4 7Swap 3 value in middle with end value
2 6 5 9 1 8 4 7 3 | | left rightHere 2 is less than 3, so move its pointer forward.
2 6 5 9 1 8 4 7 3 | | left right6 is greater than 3, so stop the left, and check the right one. 7 is greater than 3, so move its pointer left one.
2 6 5 9 1 8 4 7 3 | | left right4 is also greater than 3, so move it again.
2 6 5 9 1 8 4 7 3 | | left right8 is also greater than 3, so move it again.
2 6 5 9 1 8 4 7 3 | | left rightNow 1 is less than 3, so swap the left and right, and move the pointers forward by 1.
2 1 5 9 6 8 4 7 3 | \ left right5 is greater than 3, so stop the left one. 9 is greater than 3, so move the right one over one.
2 1 5 9 6 8 4 7 3 |\ left rightNow left and right are pointing to the same value. Since 5 is greater than 3, we can just swap it with the end.
2 1 3 9 6 8 4 7 5 \_/ \_________/We've now put 3 in its proper spot, so we've broken the problem down into doing quicksort on two smaller lists.
Practice questionsThe main reason why this algorithm works is not just that you're putting the pviot in the right place, but mainly because when you pin the pivot in its right place, you have all the left values less than you, and all the right values greater than you. By doing this you are properly breaking down the problem into two smaller subproblems. If some numbers on the left belong on the right of the pivot, then sorting the two smaller lists would not solve the large problem of creating the
NOw we're going to do a few practice problems, the first being pathLength. This returns the length of the path from the root to a specified value.
/* returns number of edges between root and node with specified data value * * returns -1 if value isn't found */ public int pathLength (Comparable c) { return find (root, c); //need to recursively solve this } public int find (BSTNode root, Comparable c) { if (root == null) return -1; //not found int diff = root.getData().compareTo(c); if (diff == 0) return 0; //found it! return 0 to show it if (diff < 0) { //if < 0 check right int edgeCount = find(root.getRight()); if (edgeCount < 0) //if edgeCount returns -1 then you failed.. //show this by also returning -1. return -1; else //otherwise you were successful.. add 1 to the previous edgeCount //to add yourself into the count. return 1 + edgeCount; } //same thing for the left subtree if (diff > 0) { int edgeCount = find(root.getLeft()); if (edgeCount < 0) return -1; else return 1 + edgeCount; }
Now we're going to try another, to see whether a tree has the Heap Order Property. Remember that this means the parents must be less than children at all points in the tree.
public boolean hasHeapOrder() { return hasHeapOrder(root); //as in most cases with trees.. easiest to do recursively } public boolean hasHeapOrder (BSTNode root) { if (root == null) return true; //empty tree trivially has the property. if ((root.getLeft() == null) && (root.getRight() == null)) return true; //same for a tree that only has a root. //recursively check for heap order on left.. if it returns //false then also return false.. also make sure that the //left node is greater than the parent. if (!hasHeapOrder(root.getLeft()) || root.getLeft().getData().compareTo(root.getData()) < 0) return false; //do same for right subtree.. if (!hasHeapOrder(root.getRight() || root.getRight().getData().compareTo(root.getData()) < 0) return false; //if you never returned false here.. then both subtrees have //heap order property and are less than you, so also return true return true; } }