Data Structures CSCI 132, Spring 2014 Lecture 22 Searching 1 Advantages of linked lists Advantages: • Dynamic memory allocation--Use only as much memory as needed (But links themselves take up space). • Can change or insert or delete items in middle of the list fairly quickly. Traversing the list to find the position can be faster than shifting many large list items (as you would in contiguous lists). Disadvantages: • Linked lists are not good for random access--when you want to access entries from many different positions in the list. 2 Linked vs. Contiguous lists Use contiguous lists when: • Entries are small • Size of list is known when program is written. • Few insertions and deletions occur except at the end of the list. • Random access is important. Use linked lists when: • Entries are large. • The size of the list is not known in advance. • Flexibility in inserting, deleting or rearranging elements is necessary. 3 Finding Data in a List •Many computer programs must find data in a list of items. •Often, one piece of information is known and we want to retrieve information associated with it. For example, the name is known, and we want the associated phone number. •The piece of information we know (and are searching for) is called the key. •The associated information is contained in a record. 4 Assumptions and requirements •Every record is associated with one key. •Keys can be compared for equality or relative ordering. •Records can be compared to each other or to keys by converting a record to its associated key. •We are (for purposes of analyzing run times) working with contiguous lists. 5 The Key class // Definition of a Key class: class Key{ public: // Add any constructors and methods for key data. private: // Add declaration of key data members here. }; // Declare overloaded comparison operators for keys. bool operator == (const Key &x, const Key &y); bool operator > (const Key &x, const Key &y); bool operator < (const Key &x, const Key &y); bool operator >= (const Key &x, const Key &y); bool operator <= (const Key &x, const Key &y); bool operator != (const Key &x, const Key &y); 6 The Record class // Definition of a Record class: class Record{ public: Record( ); //constructor operator Key( ); // implicit conversion from Record to Key. // Add any constructors and methods for Record objects. private: // Add data components. }; 7 Example of Record and Key class Key { public: Key (int x = 0); int the_key( ) const; //Return value of key private: int key; }; class Record { public: Record(Key aKey, int data1, int data2); operator Key( ); private: Key theKey; int some_data; int some_other_data; }; 8 Implementing Key and Record Key::Key (int x ) { key = x; } int Key:: the_key( ) const { return key; } Record::Record(Key aKey, int data1, int data2){ theKey = aKey; some_data = data1; some_other_data = data2; } Record::operator Key( ) { return theKey; } 9 Implementing boolean operator overrides. class Key { public: Key (int x = 0); int the_key( ) const; //Return value of key private: int key; }; //in the key.h file bool operator == (const Key &x, const Key &y); //Other comparisons here //Implementation of overloaded comparison, in key.cc file bool operator == (const Key &x, const Key &y) { return x.the_key( ) == y.the_key( ); } 10 Sequential Search Error_code sequential_search(const List<Record> &the_list, const Key &target, int &position) /* Post: If an entry in the_list has key equal to target, then return success and the output parameter position locates such an entry within the list. Otherwise return not_present and position becomes invalid. */ { //we will work this out in class } 11 Sequential Search Error_code sequential_search(const List<Record> &the_list, const Key &target, int &position) /* Post: If an entry in the_list has key equal to target, then return success and the output parameter position locates such an entry within the list. Otherwise return not_present and position becomes invalid. */ { int s = the_list.size( ); for (position = 0; position < s; position++) { Record data; the_list.retrieve(position, data); if (data == target) return success; } return not_present; } 12 Running time of sequential search • The running time of a search is approximately proportional to the number of comparisons needed to perform the search. •The running time of a sequential search depends on where the item is located in the list. •If the item is at the beginning, the number of comparisons needed is 1. •If the item is at the end of a list of length n, the number of comparisons is n. • On average, the running time is proportional to n/2 (we will show this in class). 13 Ordered Lists More efficient searches can be performed when the items are arranged in order within the list--an ordered list. class Ordered_list: public List<Record>{ public: Ordered_list( ); //Make sure insert and replace keep list ordered. //An overloaded function has the same name, //but different parameters as follows Error_code insert(const Record &data); //A function in the child class with the same name and //the same parameters as one in the parent class //overrides the parent class function as follows Error_code insert(int position, const Record &data); Error_code replace(int position, const Record &data); }; 14 Overloading the insert function Error_code Ordered_list :: insert(const Record &data) { int s = size( ); int position; for (position = 0; position < s; position++) { Record list_data; retrieve(position, list_data); if (list_data >= data) break; } return List<Record> :: insert(position, data); } 15