// // // simplified Account list class // // Based on Simplified List Template Class // Described in Chapter 9 of // Data Structures in C++ using the STL // Published by Addison-Wesley, 1997 // Written by Tim Budd, budd@cs.orst.edu // Oregon State University // // // MAR 4/4/00 - Avoided templates because couldn't get // Budd's code to compile under Microsoft Visual Studio v6.0 #include "Account-new.h" #include "AccountListLink.h" #include "AccountListList-new.h" // copy constructor - I think this should create a copy of the input // list as the real list library does AccountList::AccountList (AccountList & toCopy) { // start with empty list lastLink = 0; firstLink = 0; // loop through the list copying each account in turn and allocating // storage and building the list for (AccountLink * ptr = toCopy.firstLink; ptr != 0; ptr = ptr->nextLink) { // create a copy of the Account to be copied Account newEl(ptr->GetValue() ); // push the copy onto the new list being created push_back(newEl); } } int AccountList::size () // count number of elements in collection { int counter = 0; for (AccountLink * ptr = firstLink; ptr != 0; ptr = ptr->nextLink) counter++; return counter; } void AccountList::ShowList () { // MAR 4/4/00 - show list in order int counter = 0; for (AccountLink * ptr = firstLink; ptr != 0; ptr = ptr->nextLink) { cout << *ptr << endl; } return; } void AccountList::push_front (Account & newValue) // add a new value to the front of a list { AccountLink * newLink = new AccountLink (newValue); if (empty()) { lastLink = newLink; firstLink = newLink; } else { firstLink->prevLink = newLink; newLink->nextLink = firstLink; firstLink = newLink; } } // MAR 4/4/00 - add a new value to the back of a list void AccountList::push_back (Account & newValue) { // create a new node (link in Budd jargon) containing the account AccountLink * newLink = new AccountLink (newValue); // if the list is empty, the new node is both first and last if (empty()) { lastLink = newLink; firstLink = newLink; } // otherwise stick on end else { // last previous one now points on to new one lastLink->nextLink = newLink; // new one points back to previous last one newLink->prevLink = lastLink; // now the last element in the list is the one just added lastLink = newLink; } } void AccountList::pop_front() // remove first element from linked list { AccountLink * save = firstLink; firstLink = firstLink->nextLink; if (firstLink != 0) firstLink->prevLink = 0; else lastLink = 0; delete save; } // MAR 4/4/00 - remove last element from linked list void AccountList::pop_back() { // keep point to account being removed so can still refer to it AccountLink * save = lastLink; // bump the pointer to the last element back to the previous one // (students: if hadn't done the first statement, now we would not // know where the one being removed was anymore) lastLink = lastLink->prevLink; // if the element being removed was not the only one then set the // new last element's next pointer to nothing if (lastLink != 0) lastLink->nextLink = 0; else // element removed was the only one - so don't have to do previous statement // instead make sure the pointer to the first element is set to nothing so // it will be correct firstLink = 0; // gave memory for the element being removed back to the operating system delete save; } AccountList::~AccountList () // remove each element from the list { AccountLink * first = firstLink; while (first != 0) { AccountLink * next = first->nextLink; delete first; first = next; } } // MAR here iterator could be replaced by a pointer to a link void AccountList::insert (AccountLink * itr, Account & value) // insert a new element into the middle of a linked list { AccountLink * newLink = new AccountLink(value); //AccountLink * current = itr->currentLink; // would basically already have current passed as a param AccountLink * current = itr; newLink->nextLink = current; newLink->prevLink = current->prevLink; current->prevLink = newLink; current = newLink->prevLink; if (current != 0) current->nextLink = newLink; } // MAR here iterators replaced by a pointer to a link void AccountList::erase (AccountLink * start, AccountLink * stop) // remove values from the range of elements { // AccountLink * first = start.currentLink; AccountLink * first = start; AccountLink * prev = first->prevLink; // AccountLink * last = stop.currentLink; AccountLink * last = stop; if (prev == 0) { // removing initial portion of list firstLink = last; if (last == 0) lastLink = 0; else last->prevLink = 0; } else { prev->nextLink = last; if (last == 0) lastLink = prev; else last->prevLink = prev; } // now delete the values /* while (start != stop) { // MAR has to be changed without iterators listIterator next = start; ++next; delete start.currentLink; start = next; } */ while (start != stop) { AccountLink * next = start; next = next->nextLink; delete start; start = next; } } // remove a given account from list // return whether it was found or not bool AccountList::remove (const Account & toRemove) { bool found = false; AccountLink * curr = firstLink; // loop until end of list or element found while ((curr != 0) && (!found)) { // found if acct num and balance are the same if ((curr->GetValue().GetAcctNum() == toRemove.GetAcctNum() ) && (curr->GetValue().GetBal() == toRemove.GetBal() ) ) { // found - mark found and erase from list - and force exit from loop found = true; erase(curr); curr = 0; } else { // not found yet - move to next element curr = curr->Next(); } } // end while return found; } // return an account from the list - by number - account returned is a copy, not a reference // counting starts with 0, so if n is the list size or higher we have a problem Account AccountList::GetNthAccount(int n) { int num = size(); if (n >= num) { cerr << "Trying to Get an Account past end of list" << endl; return Account(); } else { // should be ok - start with beginning AccountLink * curr = firstLink; // loop that far for (int cnt = 0; cnt < n; cnt++) { curr = curr->Next(); } Account toReturn = curr->GetValue(); return toReturn; } } // return a pointer to an accountLink (node) from the list - by number // counting starts with 0, so if n is the list size or higher we have a problem AccountLink * AccountList::GetNthAccountLinkPtr(int n) { int num = size(); if (n >= num) { // indicate nothing found cerr << "Trying to Get an Account past end of list" << endl; return 0; } else { // should be ok - start with beginning AccountLink * curr = firstLink; // loop that far for (int cnt = 0; cnt < n; cnt++) { curr = curr->Next(); } return curr; } } // sort the list of accounts based on how operators < > evaluate the accounts // (currently by balance) // basically the strategy is to each time around worry about getting the nth largest in order // rather than sorting inplace, I think the best thing to do is to work with an initially // empty list - building it up one element at a time, then replacing the existing list with the new one void AccountList::sort() { // start with empty new list AccountList newList; // loop until empty out old list while (! empty() ) { // initialize first largest to first element and current to the next one AccountLink * largest = firstLink; AccountLink * curr = firstLink->Next(); // loop through remaining in current list for ( ; curr != 0; curr = curr->Next() ){ // if larger than largest so far - new largest if (curr->GetValue() > largest->GetValue() ) { largest = curr; } } // when exit loop largest points to the largest account // add it to the new list and remove it from the old list newList.push_back(largest->GetValue()); erase(largest); } // end while // stick newList in place of old firstLink = newList.firstLink; lastLink = newList.lastLink; // when newList goes out of scope it will take any of its elements with it // so clear it out before returning newList.firstLink = 0; newList.lastLink = 0; return; } // append an AccountList to the end of the current AccountList accountLink (node) from the list - by number // counting starts with 0, so if n is the list size or higher we have a problem void AccountList::operator += (AccountList & toAppend) { // find out how many elements in list to be appended int num = toAppend.size(); // start at beginning of list AccountLink * curr = toAppend.firstLink; for (int cnt = 0; cnt < num; cnt++) { // add to end of current list then bump to next element Account toAdd = curr->GetValue(); push_back(toAdd); curr = curr->Next(); } return; }