280 likes | 296 Views
Data Structures (… and their analysis). Computational Complexiy. int naive_multiply(int x, int y) { if (y == 0) return 0; if (y == 1) return x; if ((y % 2) == 0) return naive_multiply(x,y/2) + naive_multiply(x,y/2); return x + naive_multiply(x,y/2) + naive_multiply(x,y/2); }.
E N D
Computational Complexiy int naive_multiply(int x, int y) { if (y == 0) return 0; if (y == 1) return x; if ((y % 2) == 0) return naive_multiply(x,y/2) + naive_multiply(x,y/2); return x + naive_multiply(x,y/2) + naive_multiply(x,y/2); }
Computational Complexity Number of subproblems: 2 a=2 Size of subproblem = ½ b=2 Amount of work: constant (at most 8 => 3 ==, 1 %, 2 /, 2 +) k = 0 a vs b^k 2 vs 2 ^ 0 2 vs 1 a > b^k O(n^(log b a)=n^(log 2 2) = n^1) O(n)
Computational Complexiy int multiply(int x, int y) { if (y == 0) return 0; if (y == 1) return x; int value = multiply(x,y/2); if ((y % 2) == 0) return value + value; return x + value + value; }
Computational Complexity Number of subproblems: 1 a=1 Size of subproblem = ½ b=2 Amount of work: constant (at most 8 => 3 ==, 1 %, 2 /, 2 +) k = 0 a vs b^k 1vs 2 ^ 0 1 vs 1 a == b^k O(n^klg n = n^0 lg n = lg n) O(lg n)
Templates • Typical approach to writing functions: Work on one type of data void sort(int *a, int size) { for (int index = 0; index < size; index++) { int j = index; for (int k = index + 1; k < size; k++) // for each position in array { if (a[k] < a[j]) {j = k;} // find the smallest int temp = a[index]; a[index] = a[j]; a[j] = temp; // switch into appropriate place (first, second, third…) }} }
Templates • What if want to sort: • Doubles? • Strings? • Chars? • Rectangle objects? • Rewrite the function with different parameters. • Same algorithm, different data. • Not efficient for the programmer/code size (readability).
Templates • Template functions: • Allow arbitrary types to be used in the function • Syntax: • Add template <class Type> before the function definition • Replace all uses of a type in that function with Type
Templates: Example template <class Type> void sort(Type *a, int size) { for (int index = 0; index < size; index++) { int j = index; for (int k = index + 1; k < size; k++) // for each position in array { if (a[k] < a[j]) {j = k;} // find the smallest Type temp = a[index]; a[index] = a[j]; a[j] = temp; // switch into appropriate place (first, second, third…) }} }
Templates: Overloading Operators • Need to ensure that user-defined types implement appropriate operations for templated function • Sort: • Uses < (less than), = (assignment) • Need to be defined as appropriate for context • < for Rectangles might be dependent on area • Need to be defined as appropriate for data structure • Deep copy in assignment, copy constructor if necessary
Templates Syntax • Template Syntax: • Can have multiple types in template <> statement template <class SType, class UType> void doSomething(SType SData, UType uData) {}; • Can use type name in return type, parameters, and as the type of local variables within the function template <class Type> Type myFunction(Type input) { Type copy = input; return copy; }
Templated Functions • No change in calling templated functions – Compiler handles template creation for you void main() { double* myDoubleArray = new double[3]; int* myIntArray = new int[3]; // initialize with some random data insertionSort(myDoubleArray,3) insertionSort(myIntArray,3); } Will generate two chunks of code – one that does a double* insertionSort and one that does an int* insertionSort
Templated Functions • Think of templated functions as a function generator • As shown on previous slide, compiler will generate a function for each type needed in your program • If never called, never even compiled into final machine code.
Templates: Another Example Binary Search (currently implements integer search) int BinarySearch(int *list, const int input, const int left, const int right) { if (left < right) { int middle =(left + right) / 2; int value = list[middle]; if (input == value) return middle; else if (input < value) return BinarySearch(list, input, left, middle-1); else return BinarySearch(list,input,middle+1,right); } return – 1; }
Templates: Another Example Binary Search (templated) template <class Type> int BinarySearch(Type *list, const Type input, const int left, const int right) { if (left < right) { int middle =(left + right) / 2; Type value = list[middle]; if (input == value) return middle; else if (input < value) return BinarySearch(list, input, left, middle-1); else return BinarySearch(list,input,middle+1,right); } return – 1; }
Templates in Classes • Container class: • A class that represents a datastructure for storing and retrieving objects • Classical example: Array • Others: Linked Lists, Stacks, Queues • Templates allow for one container class to hold arbitrary object types (though limited to one type per instantiation) • Programmer develops methods for storing/retrieving • Doesn’t need to be concerned with how its later used.
Container Classes: Abstract View Rectangle1 Rectangle2 Rectangle3 Rectangle 4 int1 int2 int3 int4 double1 double2 double3 double4 Store/Insert Retrieve/Remove
Container Functionality • Four essential functions: • Create • Allocate space • Store • Add => Add new data to the container • Set => Update value of item in container • Retrieve • Delete => Remove data from the container • Get => Read data of item in container • Destroy • Free up used space
Container Functionality • What differentiates containers? • Specific rules for how create, store, retrieve, and destroy are implemented • Is there a specific ordering? • What does this look like in memory? • Multiple things at a time, or single items? • Computational Efficiency – in storage, retrieval
Bag Container Class • Simplest type of container: • Allows multiple occurrences of same element • No requirements on how elements are inserted, stored, or removed from the array. • Delete removes an arbitrary element – can’t specify what to remove • Implementation up to programmer: • C++ array – Insert at next available spot, Deletion in middle?
Bag Class Definition // Bag that can hold only integers. class Bag: { public: Bag(int MaxSize = DefaultSize) // constructor ~Bag(); // destructor, delete array void Add(int x); // add an element to the bag int* Delete(int& x); // delete an arbitrary element, store in x Boolean IsFull(); // return true if MaxSize elements Boolean IsEmpty(); // return true if zero elements private: void Full(); // error handling function void Empty(); // error handling function int *array; // storage of data int MaxSize; // largest possible size int top; // highest position in array (where to store) }
Update pass by value parameters to pass by reference because now can be arbitrarily large objects. Bag Class Definition Add template <class Type>to class definition, change real types to Type where appropriate template <class Type> class Bag: { public: Bag(int MaxSize = DefaultSize) // constructor ~Bag(); // destructor, delete array void Add(const Type& x); // add an element to the bag Type* Delete(Type &x); // delete an arbitrary element, store in x Boolean IsFull(); // return true if MaxSize elements Boolean IsEmpty(); // return true if zero elements private: void Full(); // error handling function void Empty(); // error handling function Type *array; // storage of data int MaxSize; // largest possible size int top; // highest position in array (where to store) }
Templated Bag Class • In Bag implementation, • Add template <class Type> in front of each function • Add <Type> to scope indicator • Replace real types with Type as needed template <class Type> void Bag<Type>::Add(const Type& x) { if (IsFull()) Full(); else { top = top + 1; array[top] = x; } }
Template Syntax • Creating objects of a templated class: • Add <type> to class name in variable declaration • Old way: // hardcoded to work with one specific type Bag myBagObject; • Templated version: // templated class Bag<int> myIntBagObject; Bag<double> myDoubleBagObject; Bag<GroceryItem> myGroceryBagObject;
Templates: Caveat • All templated information must be in the same file for the compiler. • Forces class definitions and implementations into one source file – the header file • Bag.h example • Compiler generates only those functions that are really called. • bagTester.cpp/bagTesterNoDelete.cpp example
Examples + Review • Another Container: Set • What are its properties? • How to define in terms of the 4 components of containers? • Create • Allocate some sized array / linked list • Store • Add => Verify item is not already in the set; If not, place in arbitrary position in the list (order doesn’t matter) • Retrieve • Delete, Get => Search the list for the item and remove it • Maybe we should consider order, as binary search would speed up search • Destroy • Free up used space – delete [] array, call LinkedList destructor
Ordered List Representations • So far, Bags and Sets and most of our other programs, have relied on arrays as the container mechanism. • Why? • Built in datastructure in C++ • Conceptually easy to understand • Fairly trivial management operations (new, delete, indexing)
Ordered List Representations • Properties of arrays that affect use as containers: • Sequential locations of data • Problems of rearranging data (adds, deletes in middle) • Sizing problems • Requirement to compute how much space to allocate • Wasted memory • Size bounds • Clumsy resizing • Since the rest of this class is essentially data structures, are arrays our best choice for “low-level containers”? • “low-level container” – a base storage mechanism that other containers use for their actual storage of data