200 likes | 497 Views
Overview of Concrete Data Types There are two kinds of data types: Simple (or atomic ) – represents a single data item int holds one integer value char holds one character value Structured – represents a collection of items and has:
E N D
Overview of Concrete Data Types • There are two kinds of data types: • Simple(or atomic) – represents a single data item • int holds one integer value • char holds one character value • Structured – represents a collection of items and has: • domain - component data items each of which may be simple or another structured data type • structure - rules defining the relations between the components • operations - a set of operations or behaviors
Linear vs. non-linear • Linear: There is a unique first and unique last element and every other element has a unique predecessor and a unique successor, except for the first and last • an array is a linear data structure • there is a first (0th) element and a last element • every other element has an k-1st and a k+1st element • Non-linear: Any data structure that is not linear • a set is a non-linear data structure • there is no unique first or last element • there is no obvious ordering of the elements
Direct-access vs. sequential access • Linear data structures can be further classified as: • Direct access: elements can be accessed at random, in any order, for example: • an array is direct access • any element can be accessed at any time • Sequential access: elements must be accessed in some specified order, for example: • a queue is sequential access • element can only be accessed one after the other
Homogeneous vs. heterogeneous • Some data structures can further be classified as: • Homogeneous: all the elements in the structure are of the same data type • an array • Heterogeneous (non-homogeneous): the elements in the structure are of different data types • a record or struct in C++
Structs vs. classes in C++ • A struct is just like a class with the exception that, by default, the members are public not private. • struct date{ int day; string month; int year;}; • We tend to use • a struct for concrete data types (CDT) • a class for abstract data types (ADT) • Both can have methods and public, private (and protected) members
Concrete Data Types vs. Abstract Data Types Concrete Data Types (CDTs) are direct implementations of fairly simple structures. Abstraction and information hiding are not employed when designing CDTs. Abstract Data Types (ADTs) offer a high-level, easy-to-use interface that is independent of the ADT’s implementation. Example: We can implement a student record either as a CDT or an ADT: CDT: implement it as a struct where all the data is public: struct student{ string name; int idNum;};
Example (cont’d): We can implement a student record either as a CDT or an ADT: ADT: implement it as a class where the data is private but a set of public operations is defined that allow the client to operate on the data. class student{ private: string name; int idNum; public: string getName() const; void setName( string ); int getIdNum() const; void setIdNum( int ); };
RecordsA record is linear, direct access, heterogeneous, concrete data structure that groups data of potentially differing data types into a single unit • in C++ records are implemented using a struct • Domain: a collection of fields (items) of potentially different data types and a set of names for the fields in each record • Structure: objects are stored in consecutive memory locations and each object has a unique name • Operations: the “.” operator provides access to each field in a record
Example: struct Course{ string dept; int number;}; Course compCourse; compCourse.dept = “CPSC”;compCourse.number = 252; Note that we have direct access to the individual data members using the “.” operator No attempt is made to “hide” the data behind a set of public operations
Arrays An array is a linear, direct access, homogeneous, concrete data structure Domain: a collection of n items of the same data type and a set of indexes in the range [ 0, n-1 ] Structure: items are stored in consecutive locations each having a unique index Operations: the indexing operator “[]” gives read and write access to the item at the specified index
Arrays and pointers in C++ • There is a strong connection between arrays and pointers • The declaration • int data1[ 3 ]; • allocates memory for three integers • associates the name data1 with the address of the 1st byte of this memory • data1 can be thought of as a constant pointer • The declaration • int* data2 = new int[ 3 ]; • allocates memory for 1 pointer and also 3 integers • data2 is a pointer that is not constant data1 data2
Pointer Arithmetic • The operators “+”, “–”, “++” and “––” are overloaded to operate on pointers: • data + 2 • is a pointer to the 3rd integer in the array data • Thus • *(data + 2) = 7; • and • data[ 2 ] = 7; • mean exactly the same thing and they can be used interchangeably
data 4 bytes data + 1 4 bytes data + 2 4 bytes Notice that there is something rather subtle going on here. By adding the integer 2 to data, we do not produce an address that is 2 bytes higher than the one stored in data. We in fact produce an address that is 8 bytes higher (assuming that each integer occupies 4 bytes): So, when we increment or decrement a pointer, the address is changed by an amount equal to the size of the object pointed to! This is very useful, it means that as programmers we do not have to concern ourselves with the size of an object when performing pointer arithmetic. Thus: &data[i] is equivalent to ( data + i )
More about arrays and pointers in C++ • The following code again illustrates the connection between indexing into an array and pointer arithmetic: • int data[ 4 ] = { 4, 3, 2, 1 }; • for( int index = 0; index < 4; index++ ) cout << *( data + index ) << “ ”; • Arrays can be passed as parameters to functions • The function printArray() can be declared to accept an array of integers as a parameter in either of the following ways: • void printArray( int data[], int size ); • or as • void printArray( int* data, int size );
Regardless of the way in which the function is declared, it can be implemented in either of the following ways: { for( int index = 0; index < size; index++ ) cout << index << “ ” << data[index] << endl; } or { for( int index = 0; index < size; index++ ) cout << index << “ ” << *(data + index) << endl; }
Multidimensional arrays as arrays • Suppose we want to store the average rainfall during each hour for a period of one week. We can do so conveniently using a two-dimensional array: • float rainfall[ 7 ][ 24 ]; • We can think of the two-dimensional array as a table having 7 rows (one for each day) and 24 columns (one for each hour). To set the rainfall on the first day for the hour between noon and 1pm: • rainfall[ 0 ][ 12 ] = 1.5; • What if we want to use dynamic memory allocation?
Multidimensional arrays as pointers • We can declare an array of pointers to each row in the table and dynamically allocate memory to each row: • int* data[ 3 ]; • data[ 0 ] = new int[ 3 ];data[ 1 ] = new int[ 2 ];data[ 2 ] = new int[ 4 ]; • We can index into the array just as before: • data[ 2 ][ 1 ] = 4; • Notice that this has given us the flexibility of having a two dimensional array where the rows are of different lengths! • We are still have the restriction that if we change the number of rows, we have to re-compile because the dimension of the array of pointers must be a constant
Multidimensional arrays as pointers to pointers • We can gain the most flexibility by declaring data to be a pointer to a pointer to an integer • We can then declare the array of pointers dynamically as well as dynamically allocating memory to each row: • int** data; • data = new int*[ 2 ]; • data[ 0 ] = new int[ 4 ];data[ 1 ] = new int[ 3 ]; • Again, we can index into the array just as before: • data[ 1 ][ 2 ] = 5;
Tradeoffs between arrays and pointers • Advantages of arrays • simple structures, no dynamic memory • Disadvantages of arrays • size is fixed • Advantages of pointers • size of memory pointed to can vary • Disadvantages of pointers • must explicitly invoke new and delete