320 likes | 400 Views
List Abstract Data Types. We have reached the point where we can customize our own versions of list types that do not encounter the problems we normally associate with traditional C++ arrays. We’d like to be able to do the following: Pass a list by value to a function!
E N D
List Abstract Data Types • We have reached the point where we can customize our own versions of list types that do not encounter the problems we normally associate with traditional C++ arrays. • We’d like to be able to do the following: • Pass a list by value to a function! • Have a function that returns a list! • Assign a list a new value with an assignment statement! • Insert a new element in the list at a particular location, and have the list make room for the new element! • Remove an element from the list, and have the list adjust the subsequent elements so there’s no gap between elements! • Access a list element at a particular position without “crashing” if the index is inappropriate! • Access the first element at position #1 and the last element at position #length! CS 150
To Start Out: A New PhoneListing Class ///////////////////////////////////////////////////// // phoneListing.h // // The class definition for the PhoneListing class // ///////////////////////////////////////////////////// #ifndef PHONE_LISTING_H #include <iostream> #include <string> using namespace std; class PhoneListing { public: // Constructor PhoneListing(); PhoneListing(string newName, string newPhoneNumber); // Member functions void setName(string newName); void setPhoneNumber(string newPhoneNumber); // Overloaded operators PhoneListing& operator = (const PhoneListing &listing); bool operator == (PhoneListing listing); bool operator < (PhoneListing listing); bool operator <= (PhoneListing listing); bool operator > (PhoneListing listing); bool operator >= (PhoneListing listing); bool operator != (PhoneListing listing); CS 150
phoneListing.h (Continued) // Accessor functions string getName() const; string getPhoneNumber() const; // Friend functions friend istream& operator >> (istream &sourceFileStream, PhoneListing &listing); friend ostream& operator << (ostream &destinationFileStream, const PhoneListing &listing); private: // Data members string name; string phoneNumber; }; #define PHONE_LISTING_H #endif CS 150
phoneListing.cpp ////////////////////////////////////////////////////////// // phoneListing.cpp // // The class implementation for the PhoneListing class. // ////////////////////////////////////////////////////////// #include <iostream> #include <string> #include "phoneListing.h" using namespace std; // This default constructor sets up the data members with no values. // PhoneListing::PhoneListing() { } // This initializing constructor sets up the data members in the obvious way. // PhoneListing::PhoneListing(string newName, string newPhoneNumber) { name = newName; phoneNumber = newPhoneNumber; } // This member function sets the PhoneListing's name // // data member to the parameterized value. // void PhoneListing::setName(string newName) { name = newName; return; } CS 150
phoneListing.cpp (Continued) // This member function sets the PhoneListing's phoneNumber // // data member to the parameterized value. // void PhoneListing::setPhoneNumber(string newPhoneNumber) { phoneNumber = newPhoneNumber; return; } // Assignment operator: sets both data members of *this to copies // // of their counterparts in the parameterized PhoneListing. // PhoneListing& PhoneListing::operator = (const PhoneListing &listing) { name = listing.name; phoneNumber = listing.phoneNumber; return *this; } // Equality operator: based upon equality between PhoneListings' name values. // bool PhoneListing::operator == (PhoneListing listing) { return (name == listing.name); } // Less-than operator: based upon whether name value of *this // // is less than name value of parameterized PhoneListing. // bool PhoneListing::operator < (PhoneListing listing) { return (name < listing.name); } CS 150
phoneListing.cpp (Continued) // Less-than-or-equal-to operator: based upon whether name value of *this // // is less than or equal to name value of parameterized PhoneListing. // bool PhoneListing::operator <= (PhoneListing listing) { return (name <= listing.name); } // Greater-than operator: based upon whether name value of *this // // is greater than name value of parameterized PhoneListing. // bool PhoneListing::operator > (PhoneListing listing) { return (name > listing.name); } // Greater-than-or-equal-to operator: based upon whether name value of *this // // is greater than or equal to name value of parameterized PhoneListing. // bool PhoneListing::operator >= (PhoneListing listing) { return (name >= listing.name); } // Inequality operator: based upon inequality between PhoneListings' name values. // bool PhoneListing::operator != (PhoneListing listing) { return (name != listing.name); } CS 150
phoneListing.cpp (Continued) // Accessor function for the value of the name data member. // string PhoneListing::getName() const { return name; } // Accessor function for the value of the phoneNumber data member. // string PhoneListing::getPhoneNumber() const { return phoneNumber; } // Input operator for the PhoneListing class: retrieves // // name value, followed by phoneNumber value. // istream& operator >> (istream &inputFileStream, PhoneListing &listing) { inputFileStream >> listing.name >> listing.phoneNumber; return inputFileStream; } // Output operator for the PhoneListing class: outputs // // name value, followed by phoneNumber value. // ostream& operator << (ostream &outputFileStream, const PhoneListing &listing) { outputFileStream << listing.name << ": " << listing.phoneNumber; return outputFileStream; } CS 150
Now Let’s Set Up Our Own List Class! ///////////////////////////////////////////// // list.h // // The class definition for the List class // ///////////////////////////////////////////// #ifndef LIST_H #include <iostream> #include <string> #include "phoneListing.h" using namespace std; const int MAX_LIST_SIZE = 100; typedef PhoneListing elementType; class List { public: // Class constructors List(); List(const List &lst); // Member functions int getLength() const; elementType& operator [ ] (int position); List& operator = (const List &lst); bool insert(int position, elementType elt); bool remove(int position); bool retrieve(int position, elementType &elt); protected: // Data members elementType entry[MAX_LIST_SIZE]; int length; // Member function int Index(int position) const;}; #define LIST_H #endif CS 150
list.cpp ////////////////////////////////////////////////// // list.cpp // // The class implementation for the List class. // ////////////////////////////////////////////////// #include <iostream> #include <string> #include <cassert> #include "list.h" #include "phoneListing.h" using namespace std; // This default constructor sets up the List as one with no elements. // List::List() { length = 0; } // This copy constructor sets up the *this List // // as a duplicate of the parameterized List. // List::List(const List &lst) { length = lst.getLength(); for (int i = 1; i <= length; i++) entry[Index(i)] = lst.entry[Index(i)]; } // This accessor function retrieves the value of the length data member. // int List::getLength() const { return length; } CS 150
list.cpp (Continued) // The subscript operator retrieves the element in the parameterized position // // of the entry data member. Note that the starting index for this operator // // is one, unlike the standard C++ starting index of zero. // elementType& List::operator [ ] (int position) { assert((position > 0) && (position <= length)); return entry[Index(position)]; } // The assignment operator gives the *this List duplicate // // values for each data member in the parameterized List. // List& List::operator = (const List &lst) { length = lst.getLength(); for (int i = 1; i <= length; i++) entry[Index(i)] = lst.entry[Index(i)]; return *this; } CS 150
list.cpp (Continued) // This member function inserts the parameterized element into the *this List // // at the parameterized position (if there's room and the position is kosher). // bool List::insert(int position, elementType elt) { if ((position < 1) || (position > length + 1) || (length >= MAX_LIST_SIZE)) return false; else { length++; for (int i = length; i > position; i--) entry[Index(i)] = entry[Index(i-1)]; entry[Index(position)] = elt; return true; } } // This member function removes the element at the parameterized // // position from the *this List (if the position is valid ). // bool List::remove(int position) { if ((position < 1) || (position > length)) return false; else { for (int i = position+1; i <= length; i++) entry[Index(i-1)] = entry[Index(i)]; length--; return true; } } CS 150
list.cpp (Continued) // This member function retrieves the element at the parameterized // // position from the *this List (if the position is kosher). // bool List::retrieve(int position, elementType &elt) { if ((position < 1) || (position > length)) return false; else { elt = entry[Index(position)]; return true; } } // This member function converts the parameterized position into the // // corresponding index of the array that is the entry data member. // int List::Index(int position) const { return position-1; } CS 150
Now Let’s Test The List Class ////////////////////////////////////////////////////////////// // phoneDriver.cpp // // // // This program file tests the List class by loading a List // // variable and searching it with a user-supplied value. // ////////////////////////////////////////////////////////////// #include <iostream> #include <fstream> #include <string> #include "list.h" #include "phoneListing.h" using namespace std; List queryUserForDirectory(); string queryUserForName(); bool searchDirectory(List directory, string personsName, PhoneListing &listing); void outputListing(PhoneListing listing); void outputNoListing(string personsName); CS 150
phoneDriver.cpp (Continued) /////////////////////////////////////////////////////////////////////////////// // The main function coordinates the user queries for the input file and the // // name being sought in the PhoneListing that is input. It also coordinates // // the output of the sought information (or its unavailability). // /////////////////////////////////////////////////////////////////////////////// void main() { List phoneBook; string soughtName; PhoneListing soughtPhoneListing; phoneBook = queryUserForDirectory(); soughtName = queryUserForName(); if (searchDirectory(phoneBook, soughtName, soughtPhoneListing)) outputListing(soughtPhoneListing); else outputNoListing(soughtName); return; } CS 150
phoneDriver.cpp (Continued) /////////////////////////////////////////////////////////////////////// // This function asks the user for the file name containing the List // // data, and then retrieves that data, using an end-of-file signal. // /////////////////////////////////////////////////////////////////////// List queryUserForDirectory() { ifstream directoryFile; char directoryFileName[50]; List directory; PhoneListing nextListing; int position = 1; cout << "Enter the file name of the telephone directory data: "; cin >> directoryFileName; directoryFile.open(directoryFileName); directoryFile >> nextListing; while (!directoryFile.eof()) { directory.insert(position, nextListing); position++; directoryFile >> nextListing; } directoryFile.close(); return directory; } CS 150
phoneDriver.cpp (Continued) ///////////////////////////////////////////////// // This function asks the user for a string // // value that will be used to search the List. // ///////////////////////////////////////////////// string queryUserForName() { string name; cout << "Enter the name of the party whose number you want: "; cin >> name; return name; } //////////////////////////////////////////////////////////////////////////////////// // This function searches the parameterized List for a PhoneListing with the // // parameterized personsName. If it finds it, it sets the PhoneListing parameter // // and returns the value true; otherwise, it merely returns the value false. // //////////////////////////////////////////////////////////////////////////////////// bool searchDirectory(List directory, string personsName, PhoneListing &listing) { PhoneListing dummyListing(personsName, ""); for (int i = 1; i <= directory.getLength(); i++) { directory.retrieve(i, listing); if (dummyListing == listing) return true; } return false; } CS 150
phoneDriver.cpp (Continued) ///////////////////////////////////////////////////////////////////////////// // This function outputs the PhoneListing found after a successful search. // ///////////////////////////////////////////////////////////////////////////// void outputListing(PhoneListing listing) { cout << "Your requested listing - " << listing << endl << endl; return; } ////////////////////////////////////////////////////////////////////////////////// // This function outputs a message indicating that the search was unsuccessful. // ////////////////////////////////////////////////////////////////////////////////// void outputNoListing(string personsName) { cout << "No listing with name: " << personsName << endl << endl; return; } CS 150
phoneDriver.cpp (Continued) ACCT 2633 AS 3180 ANTH 2744 ART 3071 BIOL 3927 BSED 2504 CHEM 2042 CE 2533 CMIS 2504 CS 2386 CNST 2088 CI 3082 DANC 2773 ESCI 3620 ECON 2542 EDUC 3277 EDAD 3277 ECE 2524 ENG 2060 ENVS 3311 FIN 2638 FL 3510 GEOG 2090 GRN 3454 HED 3252 HIST 2414 IE 3389 IT 3277 MGMT 2750 MS 2638 MKTG 3221 MC 2230 MATH 2382 ME 3389 MUS 3900 NURS 3956 PHIL 2250 PHYS 2472 POLS 3572 PROD 2638 PSYC 2202 PAPA 3762 SOCW 5758 SOC 3713 SPE 5423 SPC 3090 SPPA 3662 THEA 2773 WMST 5060 Sample Output Contents of phoneData.txt CS 150
The Sorted List Abstract Data Type • We will now develop a class that implements a list that is always kept sorted, using whatever definition of sorting is associated with the type of element held in the list. • We’d like to be able to do the following: • Insert a new element and have it automatically placed in its proper position in the list! • Use a binary search to find elements in the list, and to locate where new elements should go in the list! • Plus all of the other things we could do with our regular list! CS 150
Defining Our SortedList Class ////////////////////////////// // sortedList.h // // The class definition for // // the SortedList class // ////////////////////////////// #ifndef SORTED_LIST_H #include <iostream> #include <string> #include "phoneListing.h" using namespace std; const int MAX_LIST_SIZE = 100; typedef PhoneListing elementType; class SortedList { public: // Class constructors SortedList(); SortedList(const SortedList &srtLst); // Member functions int getLength() const; elementType& operator [ ] (int position); SortedList& operator = (const SortedList &srtLst); bool insert(elementType elt); bool remove(elementType elt); bool retrieve(elementType elt, int &position); protected: // Data members elementType entry[MAX_LIST_SIZE]; int length; // Member function int Index(int position) const; bool binarySearch(int firstPosition, int lastPosition, elementType soughtElt, int &position); }; #define SORTED_LIST_H #endif CS 150
sortedList.cpp //////////////////////////////////////////////////////// // sortedList.cpp // // The class implementation for the SortedList class. // //////////////////////////////////////////////////////// #include <iostream> #include <string> #include <assert.h> #include "sortedList.h" #include "phoneListing.h" using namespace std; // This default constructor sets up the SortedList as one with no elements. // SortedList::SortedList() { length = 0; } // This copy constructor sets up the *this SortedList // // as a duplicate of the parameterized SortedList. // SortedList::SortedList(const SortedList &lst) { length = lst.getLength(); for (int i = 1; i <= length; i++) entry[Index(i)] = lst.entry[Index(i)]; } // This accessor function retrieves the value of the length data member. // int SortedList::getLength() const { return length; } CS 150
sortedList.cpp (Continued) // The subscript operator retrieves the element in the parameterized position // // of the entry data member. Note that the starting index for this operator // // is one, unlike the standard C++ starting index of zero. // elementType& SortedList::operator [ ] (int position) { assert((position > 0) && (position <= length)); return entry[Index(position)]; } // The assignment operator gives the *this SortedList duplicate // // values for each data member in the parameterized List. // SortedList& SortedList::operator = (const SortedList &srtLst) { length = srtLst.getLength(); for (int i = 1; i <= length; i++) entry[Index(i)] = srtLst.entry[Index(i)]; return *this; } CS 150
sortedList.cpp (Continued) // This member function inserts the parameterized element // // into the *this SortedList at the appropriate position // // (if there's room). // bool SortedList::insert(elementType elt) { int position; if (length >= MAX_LIST_SIZE) return false; else { retrieve(elt, position); length++; for (int i=length; i > position; i--) entry[Index(i)] = entry[Index(i-1)]; entry[Index(position)] = elt; return true; } } // This member function removes the // // parameterized element from the *this // // SortedList (if it’s in the list). // bool SortedList::remove(elementType elt) { int position; if (!retrieve(elt, position)) return false; else { for (int i=position+1; i <= length; i++) entry[Index(i-1)] = entry[Index(i)]; length--; return true; } } CS 150
sortedList.cpp (Continued) // This member function retrieves the parameterized element // // from the *this SortedList (if it’s in the list), and sets // // the position parameter to its location in the list. // bool SortedList::retrieve(elementType elt, int &position) { return binarySearch(1, length, elt, position); } // This member function converts the parameterized position into the // // corresponding index of the array that is the entry data member. // int SortedList::Index(int position) const { return position-1; } CS 150
sortedList.cpp (Continued) // This member function performs a binary search on the SortedList for // // the soughtElt value. If it is successful, then parameter position // // will be assigned the location in the entry data member where the // // soughtElt was found; otherwise, it is assigned the location where // // it would be found if it were in the entry data member. // bool SortedList::binarySearch(int firstPosition, int lastPosition, elementType soughtElt, int &position) { int middlePosition = (firstPosition + lastPosition) / 2; if (lastPosition < firstPosition) { position = firstPosition; return false; } else if (entry[Index(middlePosition)] == soughtElt) { position = middlePosition; return true; } else if (entry[Index(middlePosition)] < soughtElt) return binarySearch(middlePosition+1, lastPosition, soughtElt, position); else return binarySearch(firstPosition, middlePosition-1, soughtElt, position); } CS 150
Testing The SortedList Class ////////////////////////////////////////////////////////////////////// // phoneDriver2.cpp // // // // This program file tests the SortedList class by loading a // // SortedList variable and searching it with a user-supplied value. // ////////////////////////////////////////////////////////////////////// #include <iostream> #include <fstream> #include <string> #include "sortedList.h" #include "phoneListing.h" using namespace std; SortedList queryUserForDirectory(); void outputDirectory(SortedList directory); string queryUserForName(); bool searchDirectory(SortedList directory, string personsName, PhoneListing &listing); void outputListing(PhoneListing listing); void outputNoListing(string personsName); CS 150
phoneDriver2.cpp (Continued) /////////////////////////////////////////////////////////////////////////////// // The main function coordinates the user queries for the input file and the // // name being sought in the PhoneListing that is input. It also coordinates // // the output of the sought information (or its unavailability). // /////////////////////////////////////////////////////////////////////////////// void main() { SortedList phoneBook; string soughtName; PhoneListing soughtPhoneListing; phoneBook = queryUserForDirectory(); outputDirectory(phoneBook); soughtName = queryUserForName(); if (searchDirectory(phoneBook, soughtName, soughtPhoneListing)) outputListing(soughtPhoneListing); else outputNoListing(soughtName); return; } CS 150
phoneDriver2.cpp (Continued) /////////////////////////////////////////////////////////////////////// // This function asks the user for the file name containing the List // // data, and then retrieves that data, using an end-of-file signal. // /////////////////////////////////////////////////////////////////////// SortedList queryUserForDirectory() { ifstream directoryFile; char directoryFileName[50]; SortedList directory; PhoneListing nextListing; cout << "Enter the file name of the telephone directory data: "; cin >> directoryFileName; directoryFile.open(directoryFileName); directoryFile >> nextListing; while (!directoryFile.eof()) { directory.insert(nextListing); directoryFile >> nextListing; } directoryFile.close(); return directory; } CS 150
phoneDriver2.cpp (Continued) //////////////////////////////////////////////////////////////// // This function outputs the entire parameterized SortedList. // //////////////////////////////////////////////////////////////// void outputDirectory(SortedList directory) { for (int i = 1; i <= directory.getLength(); i++) cout << directory[i] << endl; cout << endl; return; } //////////////////////////////////////////////////// // This function asks the user for a string value // // that will be used to search the SortedList. // //////////////////////////////////////////////////// string queryUserForName() { string name; cout << "Enter the name of the party whose number you want: "; cin >> name; return name; } CS 150
phoneDriver2.cpp (Continued) ///////////////////////////////////////////////////////////////////////////////////// // This function searches the parameterized SortedList for a PhoneListing with the // // parameterized personsName. If it finds it, it sets the PhoneListing parameter // // and returns the value true; otherwise, it merely returns the value false. // ///////////////////////////////////////////////////////////////////////////////////// bool searchDirectory(SortedList directory, string personsName, PhoneListing &listing) { int position; PhoneListing dummyListing(personsName, ""); if (directory.retrieve(dummyListing, position)) { listing = directory[position]; return true; } else return false; } ///////////////////////////////////////////////////////////////////////////// // This function outputs the PhoneListing found after a successful search. // ///////////////////////////////////////////////////////////////////////////// void outputListing(PhoneListing listing) { cout << "Your requested listing - " << listing << endl << endl; return; } CS 150
phoneDriver2.cpp (Continued) ///////////////////////////////////////////////////////////////////////////// // This function outputs the PhoneListing found after a successful search. // ///////////////////////////////////////////////////////////////////////////// void outputListing(PhoneListing listing) { cout << "Your requested listing - " << listing << endl << endl; return; } ////////////////////////////////////////////////////////////////////////////////// // This function outputs a message indicating that the search was unsuccessful. // ////////////////////////////////////////////////////////////////////////////////// void outputNoListing(string personsName) { cout << "No listing with name: " << personsName << endl << endl; return; } CS 150
phoneDriver2.cpp (Continued) CS 150