Steven Zeil October 14, 2013
Outline 1 Static & Dynamic Allocation Static Allocation Dynamic Allocation 2 Partially Filled Arrays Adding Elements Searching for Elements Removing Elements 3 Arrays and Templates 4 Vectors 5 Multi-Dimension Arrays Arrays of Arrays
Static & Dynamic Allocation Outline I 1 Static & Dynamic Allocation Static Allocation Dynamic Allocation 2 Partially Filled Arrays Adding Elements Searching for Elements Removing Elements 3 Arrays and Templates 4 Vectors 5 Multi-Dimension Arrays Arrays of Arrays
Static & Dynamic Allocation Static Allocation Static Allocation const i n t MaxItems = 1 00; // Names o f i t e m s s t d : : s t r i n g itemnames [ MaxItems ] ; Simple Best suited to situations where we know the number of items at compile time s t r i n g monthnames [ 1 2 ] ;
Static & Dynamic Allocation Static Allocation How Many Elements Do We Need? If we don t know how many elements we really need, we need to guess Too few, and the program crashes Too many, and we waste space (and maybe time)
Static & Dynamic Allocation Dynamic Allocation Dynamic Allocation Use pointer to array Allocated on heap Needs to be deleted afterwards
Static & Dynamic Allocation Dynamic Allocation Example: bidders.h extern i n t n B i d d e r s ; extern Bidder b i d d e r s ; void r e a d B i d d e r s ( s t d : : i s t r e a m& i n ) ;
Static & Dynamic Allocation Dynamic Allocation Example: bidders.cpp bidders.cpp ❶ Here we read the desired size of the arrays from the input ❷ Here we use that value to actually allocate arrays of the desired size ❸ Once that is done, we can access the arrays in the usual manner using the [ ].
Static & Dynamic Allocation Dynamic Allocation Dynamic Array Declarations are Confusing extern Bidder b i d d e r s ; We can t tell by looking at this declaration whether it is intended to point to a single bidder, or an array of bidders Need to rely on documentation
Static & Dynamic Allocation Dynamic Allocation Why Are Arrays Different? Because arrays are "really" pointers... array1 = array2; does not copy the array When arrays are passed to functions, we are actually passing a pointer passing arrays is fast and efficient changes to the array can be seen by the caller i n t x ; i n t a r r [ 1 0 0 ] ; void. foo ( i n t i, i n t a ) ; foo ( x,. a ) ; void foo ( i n t i, i n t a ) { i = i + 1 ; // does not a f f e c t x a [ 0 ] = i ; // does a f f e c t a r r }
Partially Filled Arrays Outline I 1 Static & Dynamic Allocation Static Allocation Dynamic Allocation 2 Partially Filled Arrays Adding Elements Searching for Elements Removing Elements 3 Arrays and Templates 4 Vectors 5 Multi-Dimension Arrays Arrays of Arrays
Partially Filled Arrays Partially Filled Arrays To work with a partially filled array, we generally need to have access to the array itself an integer counter indicating how many elements are currently in the array the size or length of the list an integer counter indicating the maximum nmber of elements we can have without overflowing the array the capacity of the list
Partially Filled Arrays Adding Elements Adding Elements Variations include adding to the end adding in the middle adding in order
Partially Filled Arrays Adding Elements Add to the end void addtoend ( s t d : : s t r i n g a r r a y, i n t& s i z e, s t d : : s t r i n g { a r r a y [ s i z e ] = v a l u e ; ++s i z e ; } Assumes that we have a separate integer indicating how many elements are in the array and that the "true" size of the array is at least one larger than the current value of that counter
Partially Filled Arrays Adding Elements Add to the middle addelement (array, size, index, value) Adds value into array[index], shifting all elements already in positions index..size-1 up one, to make room. Increments the size variable If we have this and we do addelement ( a r r a y, 3, 1, " Smith " ) ; we should get this.
Partially Filled Arrays Adding Elements Add to the middle: implementation addelement.cpp You can try out the addtoend and addelement functions here. Try them out with different inputs until you understand how they work.
Partially Filled Arrays Adding Elements Add in order int addinorder (array, size, value) Assume the elements of the array are already in order Find the position where value could be added to keep everything in order, and insert it there. Return the position where it was inserted If we have this and we do addinorder ( a r r a y, 3, " C l a r k e " ) ; we should get this
Partially Filled Arrays Adding Elements Add in order implementation This works: i n t addinorder ( s t d : : s t r i n g a r r a y, i n t& s i z e, s t d : : s t r i n g v a l u e ) { // Find where to i n s e r t i n t pos = 0 ; while ( pos < s i z e && v a l u e > a r r a y [ pos ] ) ++pos ; addelement ( a r r a y, s i z e, pos, v a l u e ) ; return pos ; }
Partially Filled Arrays Adding Elements Add in order (streamlined) This is a bit faster: i n t addinorder ( ( s t d : : s t r i n g a r r a y, i n t& s i z e, s t d : : s t r i n g v a l u e ) { // Make room f o r the i n s e r t i o n i n t tobemoved = s i z e 1 ; while ( tobemoved >= 0 && v a l u e < a r r a y [ tobemoved ] ) { a r r a y [ tobemoved+1] = a r r a y [ tobemoved ] ; tobemoved ; } // I n s e r t the new v a l u e a r r a y [ tobemoved+1] = v a l u e ; ++s i z e ; return tobemoved +1; } Try This: You can try out the two addinorder functions here.
Partially Filled Arrays Searching for Elements Sequential Search Search an array for a given value, returning the index where found or -1 if not found. seqsearch.cpp How many elements does this visit in the worst case? How many elements does this visit on average? if searchitem is in the array? if searchitem is not in the array?
Partially Filled Arrays Searching for Elements Sequential Search 2 Search an array for a given value, returning the index where found or -1 if not found. i n t s e q S e a r c h ( const i n t l i s t [ ], i n t l i s t L e n g t h, i n t s e a r c { i n t l o c ; f o r ( l o c = 0 ; l o c < l i s t L e n g t h ; l o c++) i f ( l i s t [ l o c ] == s e a r c h I t e m ) return l o c ; } return 1;
Partially Filled Arrays Searching for Elements Sequential Search (Ordered Data) Search an array for a given value, returning the index where found or -1 if not found. If data is in order, we can stop early as soon as list[loc] > searchitem
Partially Filled Arrays Searching for Elements seqorderedsearch i n t s e qorderedsearch ( const i n t l i s t [ ], i n t l i s t L e n g t h, i n { i n t l o c = 0 ; } while ( l o c < l i s t L e n g t h && l i s t [ l o c ] < s e a r c h I t e m ) { ++l o c ; } i f ( l o c < l i s t L e n g t h && l i s t [ l o c ] == s e a r c h I t e m ) return l o c ; e l s e return 1; How many elements does this visit in the worst case? How many elements does this visit on average? if searchitem is in the array? if searchitem is not in the array?
Partially Filled Arrays Removing Elements Removing Elements removeelement (std::string* array, int& size; int index) void removeelement ( s t d : : s t r i n g a r r a y, i n t& s i z e, i n t i n d e x ) { i n t tobemoved = i n d e x + 1 ; while ( tobemoved < s i z e ) { a r r a y [ tobemoved 1] = a r r a y [ tobemoved ] ; ++tobemoved ; } s i z e ; } Try This: You can try out the removeelement function here.
Arrays and Templates Outline I 1 Static & Dynamic Allocation Static Allocation Dynamic Allocation 2 Partially Filled Arrays Adding Elements Searching for Elements Removing Elements 3 Arrays and Templates 4 Vectors 5 Multi-Dimension Arrays Arrays of Arrays
Arrays and Templates arrayutils - first draft The functions we have developed in this section can be used in many different programs, so it might be useful to collect them into an "Array Utilities" module. Header: arrayutils0.h Compilation unit: arrayutils0.cpp Test driver: testarrayutils0.cpp Question: The main function will not compile. Why?
Arrays and Templates Overloading One solution is to provide different versions of each function for each kind of array: // Search an o r d e r e d a r r a y f o r a g i v e n value, r e t u r n i n g // found or 1 i f not found. i n t s e qorderedsearch ( const i n t l i s t [ ], i n t l i s t L e n g t h, i n i n t s e qorderedsearch ( const char l i s t [ ], i n t l i s t L e n g t h, i n t s e qorderedsearch ( const double l i s t [ ], i n t l i s t L e n g t h i n t s e qorderedsearch ( const f l o a t l i s t [ ], i n t l i s t L e n g t h, i n t s e qorderedsearch ( const s t d : : s t r i n g l i s t [ ], i n t l i s t L e with nearly identical function bodies for each one. called overloading the function name Tedious Not possible to cover all possible data types
Arrays and Templates Function Templates A function template is a pattern for an infinite number of possible functions. Contains special symbols called template parameters that function like blank spaces in a form Symbols can be replaced to "fill out" the form Called instantiating the template
Arrays and Templates A Simple Template swap.cpp The template header announces that is a template. Without this, it would look like an ordinary function The header lists the template parameters for this pattern. These will be replaced when the template is used (instantiated). Can have more than one (comma-separated) Each preceded by the word typename or class Each template parameter must appear as a type somewhere in the function s parameter list The swap template is declared in the std library header <algorithm>
Arrays and Templates Using A Function Template Import it from the appropriate header (if not declared locally) Call it with the desired parameters Compiler figures out what substitutions to make #i n c l u de <a l g o r i t h m > using. namespace s t d ; s t r i n g a = " abc " ; s t r i n g b = " bcde " ; swap ( a, b ) ; // c o m p i l e r r e p l a c e s "T" by " s t r i n g " i n t i = 0 ; i n t j = 2 ; swap ( i, j ) ; // c o m p i l e r r e p l a c e s "T" by " i n t "
Arrays and Templates Some Other std Function Templates min(x,y) returns the smaller of two values max(x,y) returns the larger of two values fill_n(array, N, value) fills array[0]..array[n-1] with value
Arrays and Templates Building a Library of Array Templates Second try, using templates: Header: arrayutils.h Test driver: testarrayutils.cpp
Arrays and Templates Function Templates Are Not Functions Is it a problem that we have the bodies in a.h file?
Arrays and Templates Function Templates Are Not Functions Is it a problem that we have the bodies in a.h file? No, because function templates are not functions, they are patterns for functions.
Arrays and Templates Patterns versus Instances In the same way that This is not an admission application. But this is an admission application. These are not functions. The code generated by the compiler in response to our calls are the functions.
Vectors Outline I 1 Static & Dynamic Allocation Static Allocation Dynamic Allocation 2 Partially Filled Arrays Adding Elements Searching for Elements Removing Elements 3 Arrays and Templates 4 Vectors 5 Multi-Dimension Arrays Arrays of Arrays
Vectors Keeping Information Together One criticism of functions like void addtoend ( s t d : : s t r i n g a r r a y, i n t& s i z e, s t d : : s t r i n g v a l u e ) ; i n t addinorder ( s t d : : s t r i n g a r r a y, i n t& s i z e, s t d : : s t r i n g v a l u e ) ; is that they separate the array, the size, and the capacity Easy for programmers to lose track of which integer counter applies to which array Complicates functions to pass this information separately.
Vectors Wrapping arrays within structs One solution: use a struct to gather the related elements together: /// A c o l l e c t i o n o f i t e m s s t r u c t ItemSequence { s t a t i c const i n t c a p a c i t y = 500; i n t s i z e ; Item data [ c a p a c i t y ] ; } ;
Vectors A Better Version Using dynamic allocation, we can be more flexible about the capacity: s t r u c t ItemSequence { i n t c a p a c i t y ; i n t s i z e ; Item data ; } ; ItemSequence ( i n t cap ) ; void addtoend ( Item item ) ;
Vectors Implementing the Sequence ItemSequence : : ItemSequence ( i n t cap ) : c a p a c i t y ( cap ), s i z e ( 0 ) { data = new Item [ c a p a c i t y ] ; } void ItemSequence : : addtoend ( Item item ) { i f ( s i z e < c a p a c i t y ) { data [ s i z e ] = item ; ++s i z e ; } e l s e c e r r << " E r r o r : ItemSequence i s f u l l " << e n d l ; }
Vectors Vectors the Un-Array The vector is an array-like structure provided in the std header <vector>. Think of it as an array that can grow at the high end actually another kind of template, a class template
Vectors Declaring Vectors s t d : : v e c t o r <int > v i ; // a v e c t o r o f 0 i n t s s t d : : v e c t o r <s t d : : s t r i n g > vs ( 1 0 ) ; // a v e c t o r o f 10 // empty s t r i n g s s t d : : v e c t o r <f l o a t > v f ( 5, 1. 0 ) ; // a v e c t o r o f 5 // f l o a t s, a l l 1. 0 The type name inside the < > describes the elements contained inside the vector
Vectors Accessing Elements in a Vector Use the [ ] just as with an array: v e c t o r <int > v ( 1 0 ) ; f o r ( i n t i = 0 ; i < 1 0 ; ++i ) { i n t j ; c i n >> j ; v [ i ] = j + 1 ; cout << v [ i ] << e n d l ; }
Vectors Size of a Vector void foo (vector<int>& v) { } for (int i = 0; i < { } int j; cin >> j; v[i] = j + 1; cout << v[i] << endl; v.size() ; ++i) Vectors remember their own size Accessed via size() With vectors, we do not over-allocate extra spaces in the vector and use a separate counter
Vectors Adding to a Vector Adding to the end: This is how we "grow" a vector. v. push_back ( x ) ;
Vectors Adding to the Middle template <c l a s s Vector, c l a s s T> void addelement ( Vector& v, i n t index, T v a l u e ) { // Make room f o r the i n s e r t i o n i n t tobemoved = v. s i z e ( ) 1 ; v. push_back ( v a l u e ) ; // expand v e c t o r by 1 s l o t while ( tobemoved >= i n d e x ) { v [ tobemoved+1] = v [ tobemoved ] ; tobemoved ; } // I n s e r t the new v a l u e v [ i n d e x ] = v a l u e ; }
Vectors Adding to the Middle: v2 Actually, vector s provide a built-in operation for inserting into the middle: s t r i n g a ; // a r r a y o f s t r i n g s v e c t o r <s t r i n g > v ; i n t k, n ;. v. i n s e r t ( v. b e g i n ()+k, " H e l l o " ) ; addelement ( a, n, k, " H e l l o " ) ; The last two statements do the same thing. But insert is a built-in member function of vectors The way of specifying the position is a bit odd. v.begin() is a pointer to the start of the vector Like a is a pointer to the start of the array v.begin() + k is a pointer to v[k] Like a + k is a pointer to the a[k]
Vectors Add in Order to Vector template <c l a s s Vector, c l a s s T> i n t addinorder ( Vector& v, T v a l u e ) { // Make room f o r the i n s e r t i o n i n t tobemoved = v. s i z e ( ) 1 ; v. push_back ( v a l u e ) ; // expand v e c t o r by 1 s l o t while ( tobemoved >= 0 && v a l u e < v [ tobemoved ] ) { v [ tobemoved+1] = v [ tobemoved ] ; tobemoved ; } // I n s e r t the new v a l u e v [ tobemoved+1] = v a l u e ; return tobemoved +1; }
Vectors Advantages of Vectors Can grow as necessary Need not worry about pointers, allocation, delete Vectors can copy: v1 = v2;
Vectors Disadvantages of Vectors A bit slower than arrays push_back is sometimes very slow Can waste a lot of storage but so can arrays if we have to guess at max Harder to work with in a debugger
Multi-Dimension Arrays Outline I 1 Static & Dynamic Allocation Static Allocation Dynamic Allocation 2 Partially Filled Arrays Adding Elements Searching for Elements Removing Elements 3 Arrays and Templates 4 Vectors 5 Multi-Dimension Arrays Arrays of Arrays
Multi-Dimension Arrays Multi-Dimension Arrays Used in situations where we would arrange data into a table rather than a list. If we know how many rows and columns, Allocate array as i n t a r r a y [ numrows ] [ numcols ] ; Access as array[i][j] 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2 3,0 3,1 3,2
Multi-Dimension Arrays Example test2dimfixed.cpp
Multi-Dimension Arrays Arrays of Arrays Arrays of Arrays If we do not know (at compile time) how many rows and columns, Declare array as i n t a r r a y ; Allocate as an array of pointers: a r r a y = new i n t [ numrows ] ; Each row must then be allocated as an array a r r a y [ i ] = new i n t [ numcols ] ; Access as array[i][j] Example: test2dimrowscols.cpp 0 1 2 3 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2 3,0 3,1 3,2
Multi-Dimension Arrays Arrays of Arrays Linearized Arrays We can map 2-D arrays onto a linear structure i n t i n d e x ( i n t i, j, numcols ) { return j + i numcolss ; } 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2 3,0 3,1 3,2
Multi-Dimension Arrays Arrays of Arrays Linearized Array Code 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2 3,0 3,1 3,2 Declare array as i n t a r r a y ; Allocate as a 1-D array a r r a y = new i n t [ numrows numcols ] ; Access as array[index(i,j,numcols)]