Week 3 – Sorting Machine, Stacks, Recursion, and Partial Maps Jimmy Voss Disclaimer: Not all material is original. Some is taken from the official course slides, and some is taken from Anna’s slides. Sorting Machine Idea • Container class for sorting arbitrary Items. • Should work with any sorting algorithm. • Works in 2 stages: – Insertion phase – place items into a sorting machine. While in insertion phase, inserting is true. – Extraction phase – remove sorted items from Sorting Machine. • Note: We make Sorting Machine a Separate component / class. Why A Separate Component? • Sorting_Machine will be templated – Allows for basic logic of a particular sort to be implemented regardless of the type being operated on. (Template functions require messier notation for client). – Many different sorting functions are commonly used. – Allows use of Utility functions for Comparison based sorting algorithms. (General_Are_In_Order) Sorting_Machine • Insert(x) – requires: inserting • Change_To_Extraction_Phase() – requires: inserting • Remove_First(x) – requires: not inserting, |self| > 0 • Remove_Any(x) – requires: not inserting, |self| > 0 • Size() • Is_In_Extraction_Phase() Sorting Machine Usage • Typical program flow: 1. Insert all objects you want sorted one at a time. 2. Call Change_To_Extraction_Phase() • • A boolean flag maintains whether this has been called. After this has been called, insertion phase is done. 3. Repeatedly call Remove_First() to get elements in sorted order. Sorting Machine Templates abstract_template < concrete_instance class Item, concrete_instance utility_class Item_Are_In_Order /*! implements abstract_instance General_Are_In_Order <Item> !*/ > class Sorting_Machine_Kernel { /* Declarations and Specs */ }; Example: Integer Sorting Machine #include “/CT/Sorting_Machine/Kernel_1_C.h” #include “/CI/Integer/Integer_Are_In_Order.h” class Integer_Sorting_Machine : instantiates Sorting_Machine_Kernel_1a_C< Integer, Integer_Are_In_Order_1 > { }; Note: Integer_Are_In_Order_1 is not actually in the Resolve Library Example: Integer Sorting Machine #include “/CT/Sorting_Machine/Kernel_1_C.h” #include “/CI/Integer/Integer_Are_In_Order.h” class Integer_Sorting_Machine : instantiates Sorting_Machine_Kernel_1a_C< Integer, Integer_Are_In_Order_1 > Uses a utility class { }; Note: Integer_Are_In_Order_1 is not actually in the Resolve Library Exercise • Suppose you have access to a sorting_machine object instantiated to work with text objects named “sorter”. Write code for the following: global_procedure Lex_Sort(alters Queue_Of_Text& sort_me); /*! ensures sort_me = permutation of #sort_me and for every a, b, c: string of string of character, i, j: string of character where (sort_me = a * <i> * b * <j> * c) (|i| <= |j| and if |i| = |j| then i < j) !*/ Exercise global_procedure Lex_Sort(alters Queue_Of_Text& sort_me) { while ( sort_me.Length() > 0 ) { object catalyst Text x; sort_me.Dequeue( x ); sorter.Insert( x ); } sorter.Change_To_Extraction_Phase(); while ( sorter.Size() > 0 ) { object catalyst Text x; sorter.Remove_First( x ); sort_me.Enqueue( x ); } } Concept of Recursion • In mathematics, recursion refers to a way of defining functions. • Example: Fibonacci sequence: Base Cases: ๐1 = 1 ๐2 = 1 Recursive Definition: ๐๐ = ๐๐−2 + ๐๐−1 Resulting sequence: 1, 1, 2, 3, 5, 8, 13, . . . Recursion in Programming • Functions are said to be recursive if: – The function calls itself -- OR -– Function ๐1 calls function ๐2 which after a series of function calls results in calling ๐1 again. and the function terminates. Recursion in Programming • A recursive function typically refers to a function which calls itself. • Base cases – there is some “small” case which the recursive function handles without making a recursive call. • Recursive step – The step that reduces the problem to a “smaller” problem, and uses the results of the smaller problem to solve the larger problem. Exercise (Fibonacci) • Fill in the following function which returns the ๐๐กโ Fibonacci number ๐๐ with the base cases ๐1 = ๐2 = 1. • Assume in the below that FibonacciFunc is a math function that returns the ๐๐กโ Fibonacci number. global_function Integer Fibonacci( preserves Integer n ); /*! requires n >= 1 ensures f_n = FibonacciFunc( #n ) !*/ Exercise (Solution) global_function Integer Fibonacci( preserves Integer n ); { if ( n <= 2 ) { // base cases return 1; } else { // recursive case return Fibonacci( n-1 ) + Fibonacci( n-2 ); } } Question: Is this very efficient? Stacks • Intuitively like a stack of objects. • LIFO – Last in first out. • Purest form has 2 operations: – Push – add an object to the stack – Pop – Take an object off the top of the stack. • Implemented as a template container class. Stacks (Operations) • Push ( x ) – consumes x • Pop( x ) – produces x • Accessor, i.e. [current] – Look at the top element of the stack. • Length() Stack (Mathematical Model) • Modeled as a string of Item. • Push adds an Item to the front of the string. • Pop removes an Item from the front of the string. • Accessor can be used to access the Item at the front of the string. Stacks are Important Memory Addr • Program Layout in Virtual Memory • Program stack allocates space for function / procedure calls. • Very Easy to implement at a low level (Assembly level programming). 0 Reserved Program Code Stack Heap Large Number Exercise: Reversing a Stack • Give a recursive implementation for the following procedure: global_procedure Reverse_Queue( alters Queue_Of_Integer & myQueue ) { // fill in code here } • What is the base case? • How does one reduce the size of the problem? • Give a second implementation without recursion. Hint: use a stack. Exercise (Recursive Solution) global_procedure Reverse_Queue( alters Queue_Of_Integer & myQueue ) { // Base Case if ( myQueue.Length() <= 1 ) { // Do nothing } // Recursive Case else { object catalyst Integer x; myQueue.Dequeue( x ); Reverse_Queue( myQueue ); myQueue.Enqueue( x ); } } Exercise (Recursive Solution Trace) myQueue = <4, 3, 2, 1> myQueue = <1, 2, 3, 4> X=1 Reverse_Queue( myQueue) myQueue = <4, 3, 2> myQueue = <2, 3, 4> X=2 Reverse_Queue( myQueue) myQueue = <4, 3> myQueue = <3, 4> X=3 Reverse_Queue( myQueue) myQueue = <4> myQueue = <4> Exercise global_procedure Reverse_Queue( alters Queue_Of_Integer & myQueue ) { object catalyst Stack_Of_Integer S; while ( myQueue.Length() > 0 ) { object catalyst Integer temp; myQueue.Dequeue( temp ); S.Push( temp ); } while ( S.Length() > 0 ) { object catalyst Integer temp; S.Pop( temp ); myQueue.Enqueue( temp ); } } Partial Map • A map is a data structure which maps an d_item to an r_item. • d_items are unique. • Both the index and the item mapped to are template types. • Example: Webster’s Dictionary maps each word to a set of definitions. Examples of maps • Mathematical model: a map is a set of points (d_item, r_item) such that d_item is the index and r_item the item mapped to. Which of these are maps? • {(1, 2), (2, 2), (3, 2)} • {(1, 2), (1, 3), (3, 3)} • {(“hi”, “a greeting”), (“Tom”, “a name”), (“Tom”, “my best friend”)} • {(“hi”, {“a greeting”}), (“Tom”, {“a name”, “my best friend”})} Examples of maps • • • • Answers: {(1, 2), (2, 2), (3, 2)} – Yes {(1, 2), (1, 3), (3, 3)} – No, 1 is a d_item twice {(“hi”, “a greeting”), (“Tom”, “a name”), (“Tom”, “my best friend”)} – No, “Tom” is a d_item twice. • {(“hi”, {“a greeting”}), (“Tom”, {“a name”, “my best friend”})} – Yes requires d ∉ self d ∈ self |self| > 0 d ∈ self d_item type r_item type