Lecture 7 - ECE 2574 Introduction to Data Structures and...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: ECE 2574 Introduction to Data Structures and Algorithms Lecture 7: ADTs and Classes cont. Reading: Chapter 3 and parts of Chapter 8 Chris Wyatt Electrical and Computer Engineering and School of Biomedical Engineering and Sciences Virginia Tech Wednesday Schedule Generic Classes: templates Operator overloading List ADT In class exercise Standard Library: vector Containers Containers are objects that hold objects Containers have a common and consistent interface Provide iterator mechanism consistent across those containers that support iteration conceptually Generic Containers Many of the data structures we will implement are containers. Containers may or may not have ordering of the contents. The algorithms for inserting, deleting, and searching often do not depend on what type is in the container. Example: is there really any functional difference between a list of intgers and a list of Triangles? In C++, generics are implemented using templates. template <class T> class SomeContainer { public: // custom constructor, initializing to value // of type T SomeContainer(T value) { data = value; }; private: // internal data is of type T T data; }; Template Caveats The simplest approach to templates is to define and implement them in the same .h file You can also create a .txx file and include it at the bottom of the .h file for consistency with normal class implementations (I like this better) Example Operator Overloading In C++ you can extend the standard operators (+, -, ++, --, <<, etc) to custom types (classes). Example: for objects a,b,c that define operators a + b is actually a.operator+(b) c[4] is actually c.operator(4) d("hi", 4) is actually d.operator("hi", 4) Only overload operators that make sense! Example overloading= Consider the following: MyClass a; MyClass b; b = a; The operator overload signature is MyClass & MyClass::operator=(const MyClass & rhs); Remember b.operator=(a) It returns a reference to allow chaining d = c = b = a; Operator=, watch for self assignment In classes that allocate memory, you must test if you are assigning to yourself, or you leak memory. Example Another example: operator TYPE & operator(size_t index); const TYPE & operator(size_t index); Why should both be included? List ADT implemented as an array List data: an array of type T List operations: Create an empty list Destroy a list Copy a list Determine if a list is empty Get the current length of the list Insert an item at a given position in the list Delete an item at a certain position in the list Get a copy of the item at a certain position in the list In class exercise Implement and test the List ADT in C++ using dynamic arrays for a generic type T (i.e. use a template). List data: an array of type T List operations to implement: Create an empty list Destroy a list Determine if a list is empty Insert an item at a given position in the list using Get the current allocated length of the list Copy a list The standard library valarray valarray is a template, used for numerical arrays #include <valarray> using std::valarray; // integer array of 100 elements equal to 0 valarray<int> iarray(100); // double array of 50 elements equal to 3.14 valarray<double> darray1(3.14, 50) // placeholder for a double array valarray<double> darray2; // copy darray1 to darray2 darray2 = darray1; Using valarray // initialization using an array int v[3] = {7,4,6}; valarray<int> vec3(v,3); vec3.size(); // size of vec3 is 3 vec3[1]; // the second element of vec3, 4 vec3[1] = 0; // change the second element to 0 vec3.sum(); // the sum of elements (13) // many other operations, see a C++ reference Standard Library Class Vector #include <vector> std::vector<T> Examples: std::vector<int> v1(100); std::vector<double> v2(35); std::vector<unsigned short> * v3 = \ new std::vector<unsigned short>(45); Tip for using the standard library The type names tend to get long. Previous Example: std::vector<unsigned short> * v3 = \ new std::vector<unsigned short>(45); Solution: use typedefs typedef std::vector<unsigned short> VectorType; VectorType * v3 = new VectorType(45); Vector constructors vector(); vector( const vector& c ); vector( size_type num, const TYPE& val = TYPE() ); vector( input_iterator start, input_iterator end ); ~vector(); Vector operators TYPE& operator( size_type index ); const TYPE& operator( size_type index ) const; vector operator=(const vector& c2); bool operator==(const vector& c1, const vector& c2); bool operator!=(const vector& c1, const vector& c2); bool operator<(const vector& c1, const vector& c2); bool operator>(const vector& c1, const vector& c2); bool operator<=(const vector& c1, const vector& c2); bool operator>=(const vector& c1, const vector& c2); Vector operators Comparison or assigning one vector to another takes linear time. The operator is constant time. Two vectors are equal if: 1. Their size is the same, and 2. Each member in location i in one vector is equal to the the member in location i in the other vector. Comparisons are lexicographical. Vector element access Random access in constant time and () subscripting, no range check at() does range checking, throws out_of_range front() and back() return references to the first and last element respectively. size() and max_size() returns how many are currently in the vector, and how many can the vector hold. There are a few other operations, see your C++ reference. Vector support iterators Iterators are a generic mechanism to traverse a container They act superficially like pointers (but they are not!) Forward Iterators begin() end() Reverse Iterators rend() rbegin() Using iterators with vector typedef std::vector<double> VectorType; VectorType v(100); // get iterator at the beginning VectorType::iterator it = v.begin(); double x = 1.0; // while the current iterator is not at the // end while( it != v.end() ) { *it = x; // put x into the vector // at the current iterator x += 0.1; ++it; } // move iterator to next position Summary: In general valarray and vector is preferred over arrays. Memory management of arrays is complex. You cannot pass arrays by value. Arrays do not have built in bounds checking (vector has both) Use valarray for numerical arrays (1D, 2D, etc) Use vector for arrays of other types ...
View Full Document

This note was uploaded on 04/01/2008 for the course ECE 2574 taught by Professor Chuang during the Fall '08 term at Virginia Tech.

Ask a homework question - tutors are online