/homework/hw5/main.cpp
https://bitbucket.org/noahgoldman/data_structures · C++ · 310 lines · 193 code · 54 blank · 63 comment · 39 complexity · def236a610f139964a1fdf7356853db0 MD5 · raw file
- // CSCI 1200 Data Structures
- // Homework 5: Multi-Linked Lists
- // NOTE: You should not need to make any changes to this file, except
- // to add your own test cases at the bottom of the file where
- // indicated.
- #include <iostream>
- #include <cmath>
- #include <string>
- #include <list>
- #include <vector>
- #include <cassert>
- #include <cstdlib>
- #include "multi_linked_list.h"
- // ================================================================================
- // A simple function to test if two STL lists contain the "same" elements
- // returns true if it contains the same number of elements in the same order
- // otherwise returns false
- template <class T> bool same(const std::list<T> &a, const std::list<T> &b) {
- if (a.size() != b.size()) return false;
- typename std::list<T>::const_iterator a_itr = a.begin();
- typename std::list<T>::const_iterator b_itr = b.begin();
- while (a_itr != a.end()) {
- if (*a_itr != *b_itr) return false;
- a_itr++;
- b_itr++;
- }
- return true;
- }
- template <class T> bool same(MultiLL<T> &m1, MultiLL<T> &m2) {
- if (m1.size() != m2.size()) return false;
- typename MultiLL<T>::iterator i1 = m1.begin_chronological();
- typename MultiLL<T>::iterator i2 = m2.begin_chronological();
- while (i1 != m1.end_chronological()) {
- if (*i1 != *i2) return false;
- i1++;
- i2++;
- }
- return true;
- }
- // ================================================================================
- // This program stress tests the templated MultiLL container class
- int main() {
- // The test data (stored in STL lists)
- std::list<std::string> songs;
- songs.push_back("hound dog");
- songs.push_back("poker face");
- songs.push_back("brown eyed girl");
- songs.push_back("let it be");
- songs.push_back("walk like an egyptian");
- songs.push_back("man in the mirror");
- songs.push_back("stairway to heaven");
- songs.push_back("dancing in the street");
- songs.push_back("every breath you take");
- songs.push_back("hotel california");
- // the same data, sorted!
- std::list<std::string> sorted_songs(songs);
- sorted_songs.sort();
- // create an empty multi-linked list and fill it with the test data
- MultiLL<std::string> my_list;
- for (std::list<std::string>::iterator itr = songs.begin(); itr != songs.end(); itr++) {
- my_list.add(*itr);
- }
- assert (songs.size() == my_list.size());
- // -------------------
- // iterator tests
- // test the chronological iterator (forwards)
- std::cout << "chronological order" << std::endl;
- std::list<std::string> chrono_order;
- MultiLL<std::string>::iterator itr = my_list.begin_chronological();
- while (itr != my_list.end_chronological()) {
- std::cout << " " << *itr << std::endl;
- chrono_order.push_back(*itr);
- itr++;
- }
- std::cout << std::endl;
- assert (same(songs,chrono_order));
- // test the sorted order iterator (forwards)
- std::cout << "sorted order" << std::endl;
- std::list<std::string> sorted_order;
- itr = my_list.begin_sorted();
- while (itr != my_list.end_sorted()) {
- std::cout << " " << *itr << std::endl;
- sorted_order.push_back(*itr);
- itr++;
- }
- std::cout << std::endl;
- assert (same(sorted_songs,sorted_order));
- // test the random order iterator
- std::cout << "random order" << std::endl;
- std::list<std::string> random_order;
- itr = my_list.begin_random();
- for (int i = 0; i < my_list.size(); i++,itr++) {
- std::cout << " " << *itr << std::endl;
- random_order.push_back(*itr);
- }
- std::cout << std::endl;
- // loop through the elements a second time (the order should be the same!)
- std::list<std::string>::iterator itr2 = random_order.begin();
- for (int i = 0; i < my_list.size(); i++,itr++,itr2++) {
- // verify that the elements repeat the order
- assert (*itr == *itr2);
- }
- std::list<std::string> random_order_check(random_order);
- random_order_check.sort();
- // verify that all of the elements appeared in the initial loop
- assert (same(sorted_songs,random_order_check));
- // test the re-randomization by creating a new random iterator
- std::cout << "random order 2" << std::endl;
- std::list<std::string> random_order2;
- itr = my_list.begin_random();
- for (int i = 0; i < my_list.size(); i++,itr++) {
- std::cout << " " << *itr << std::endl;
- random_order2.push_back(*itr);
- }
- std::cout << std::endl;
- // with over 3 million different possible permutations of 10
- // elements, it is highly unlikely they will be the same!
- assert (!same(random_order,random_order2));
-
- // -------------------
- // erase tests
- // erase the first element inserted
- itr = my_list.begin_chronological();
- assert (*itr == "hound dog");
- itr = my_list.erase(itr);
- assert (*itr == "poker face");
- assert (my_list.size() == 9);
- std::cout << "erased: hound dog" << std::endl;
- // erase the second to last element in sorted order
- itr = my_list.begin_sorted();
- for (int i = 0; i < 7; i++) { itr++; }
- assert (*itr == "stairway to heaven");
- itr = my_list.erase(itr);
- assert (*itr == "walk like an egyptian");
- assert (my_list.size() == 8);
- std::cout << "erased: stairway to heaven" << std::endl;
- // erase the third element in the random order
- itr = my_list.begin_random();
- itr++;
- itr++;
- std::string tmp = *itr;
- // note that the return value of erase with a random iterator is undefined
- my_list.erase(itr);
- std::cout << "erased: " << tmp << std::endl;
- assert (my_list.size() == 7);
- assert (!my_list.empty());
- my_list.clear();
- assert (my_list.empty());
- assert (my_list.size() == 0);
- std::cout << "cleared the whole list!" << std::endl << std::endl;
- // ---------------------------
- // ADD YOUR OWN TEST CASES BELOW
-
- // be sure to test:
- // copy constructor
- // assignment operator
- // destructor
- // all corner cases of erase
- // decrement operator for the chronological & sorted iterators
- // pre vs. post increment & decrement operations for iterators
- // MultiLL containing types other than std::string
- // anything else that is necessary
- // Test copy constructor
- MultiLL<std::string> string_ml;
- string_ml.add("hound dog");
- string_ml.add("poker face");
- string_ml.add("brown eyed girl");
- string_ml.add("let it be");
- string_ml.add("walk like an egyptian");
- string_ml.add("man in the mirror");
- string_ml.add("stairway to heaven");
- string_ml.add("dancing in the street");
- string_ml.add("every breath you take");
- string_ml.add("hotel california");
- MultiLL<std::string> string2(string_ml);
- assert(same(string2, string_ml));
- string2.clear();
- assert(string2.empty());
- std::cout << "Copy constructor passes correctly\n" << std::endl;
- // Test Assignment operator
- MultiLL<std::string> string3;
- string3 = string_ml;
- assert(same(string3, string_ml));
- string3.clear();
- assert(string3.empty());
- std::cout << "Assignment operator passes correctly\n" << std::endl;
- // Test destructor
- MultiLL<std::string> *string_dyn = new MultiLL<std::string>(string_ml);
- assert(same(*string_dyn, string_ml));
- delete string_dyn;
- std::cout << "Destructor works correctly\n" << std::endl;
- // Test erase
- MultiLL<std::string> e_string(string_ml);
- assert(same(e_string, string_ml));
- MultiLL<std::string>::iterator eitr = e_string.begin_chronological();
- eitr = e_string.erase(eitr);
- assert(e_string.size() == 9);
- for (int c = 0; c < e_string.size() - 1; c++) {
- eitr++;
- }
- eitr = e_string.erase(eitr);
- assert(e_string.size() == 8);
- /*
- eitr = e_string.erase(eitr);
- eitr = e_string.erase(eitr);
- eitr = e_string.erase(eitr);
- eitr = e_string.erase(eitr);
- eitr = e_string.erase(eitr);
- eitr = e_string.erase(eitr);
- eitr = e_string.erase(eitr);
- assert(eitr == e_string.end_chronological());
- assert(e_string.begin_chronological() == e_string.end_chronological());
- e_string.clear();
- assert(e_string.empty());
- */
- std::cout << "Erase seems to work correctly with all edge cases\n" << std::endl;
- // Test preincrement/postincrement operators
- MultiLL<std::string> p_string;
- p_string = string_ml;
- assert(same(p_string, string_ml));
- MultiLL<std::string>::iterator pitr = p_string.begin_sorted();
- pitr++;
- std::string original = *pitr;
- pitr++;
- ++pitr;
- --pitr;
- pitr--;
- assert(original == *pitr);
- pitr = p_string.erase(pitr);
- original = *pitr;
- pitr++;
- ++pitr;
- --pitr;
- pitr--;
- assert(original == *pitr);
- std::cout << "Post and pre increment work correctly\n" << std::endl;
- // Test alternate data types
- MultiLL<int> t_int;
- t_int.clear();
- t_int.add(123);
- t_int.add(235);
- t_int.add(23);
- t_int.add(562);
- t_int.add(63);
- t_int.add(7632);
- t_int.add(12);
- t_int.add(52451);
- assert(t_int.size() == 8);
- MultiLL<int>::iterator aitr = t_int.begin_chronological();
- aitr++;
- aitr = t_int.erase(aitr);
- assert(t_int.size() == 7);
- t_int.clear();
- assert(t_int.empty());
-
- std::cout << "Alternate data type (int) works\n" << std::endl;
- }