/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

  1. // CSCI 1200 Data Structures
  2. // Homework 5: Multi-Linked Lists
  3. // NOTE: You should not need to make any changes to this file, except
  4. // to add your own test cases at the bottom of the file where
  5. // indicated.
  6. #include <iostream>
  7. #include <cmath>
  8. #include <string>
  9. #include <list>
  10. #include <vector>
  11. #include <cassert>
  12. #include <cstdlib>
  13. #include "multi_linked_list.h"
  14. // ================================================================================
  15. // A simple function to test if two STL lists contain the "same" elements
  16. // returns true if it contains the same number of elements in the same order
  17. // otherwise returns false
  18. template <class T> bool same(const std::list<T> &a, const std::list<T> &b) {
  19. if (a.size() != b.size()) return false;
  20. typename std::list<T>::const_iterator a_itr = a.begin();
  21. typename std::list<T>::const_iterator b_itr = b.begin();
  22. while (a_itr != a.end()) {
  23. if (*a_itr != *b_itr) return false;
  24. a_itr++;
  25. b_itr++;
  26. }
  27. return true;
  28. }
  29. template <class T> bool same(MultiLL<T> &m1, MultiLL<T> &m2) {
  30. if (m1.size() != m2.size()) return false;
  31. typename MultiLL<T>::iterator i1 = m1.begin_chronological();
  32. typename MultiLL<T>::iterator i2 = m2.begin_chronological();
  33. while (i1 != m1.end_chronological()) {
  34. if (*i1 != *i2) return false;
  35. i1++;
  36. i2++;
  37. }
  38. return true;
  39. }
  40. // ================================================================================
  41. // This program stress tests the templated MultiLL container class
  42. int main() {
  43. // The test data (stored in STL lists)
  44. std::list<std::string> songs;
  45. songs.push_back("hound dog");
  46. songs.push_back("poker face");
  47. songs.push_back("brown eyed girl");
  48. songs.push_back("let it be");
  49. songs.push_back("walk like an egyptian");
  50. songs.push_back("man in the mirror");
  51. songs.push_back("stairway to heaven");
  52. songs.push_back("dancing in the street");
  53. songs.push_back("every breath you take");
  54. songs.push_back("hotel california");
  55. // the same data, sorted!
  56. std::list<std::string> sorted_songs(songs);
  57. sorted_songs.sort();
  58. // create an empty multi-linked list and fill it with the test data
  59. MultiLL<std::string> my_list;
  60. for (std::list<std::string>::iterator itr = songs.begin(); itr != songs.end(); itr++) {
  61. my_list.add(*itr);
  62. }
  63. assert (songs.size() == my_list.size());
  64. // -------------------
  65. // iterator tests
  66. // test the chronological iterator (forwards)
  67. std::cout << "chronological order" << std::endl;
  68. std::list<std::string> chrono_order;
  69. MultiLL<std::string>::iterator itr = my_list.begin_chronological();
  70. while (itr != my_list.end_chronological()) {
  71. std::cout << " " << *itr << std::endl;
  72. chrono_order.push_back(*itr);
  73. itr++;
  74. }
  75. std::cout << std::endl;
  76. assert (same(songs,chrono_order));
  77. // test the sorted order iterator (forwards)
  78. std::cout << "sorted order" << std::endl;
  79. std::list<std::string> sorted_order;
  80. itr = my_list.begin_sorted();
  81. while (itr != my_list.end_sorted()) {
  82. std::cout << " " << *itr << std::endl;
  83. sorted_order.push_back(*itr);
  84. itr++;
  85. }
  86. std::cout << std::endl;
  87. assert (same(sorted_songs,sorted_order));
  88. // test the random order iterator
  89. std::cout << "random order" << std::endl;
  90. std::list<std::string> random_order;
  91. itr = my_list.begin_random();
  92. for (int i = 0; i < my_list.size(); i++,itr++) {
  93. std::cout << " " << *itr << std::endl;
  94. random_order.push_back(*itr);
  95. }
  96. std::cout << std::endl;
  97. // loop through the elements a second time (the order should be the same!)
  98. std::list<std::string>::iterator itr2 = random_order.begin();
  99. for (int i = 0; i < my_list.size(); i++,itr++,itr2++) {
  100. // verify that the elements repeat the order
  101. assert (*itr == *itr2);
  102. }
  103. std::list<std::string> random_order_check(random_order);
  104. random_order_check.sort();
  105. // verify that all of the elements appeared in the initial loop
  106. assert (same(sorted_songs,random_order_check));
  107. // test the re-randomization by creating a new random iterator
  108. std::cout << "random order 2" << std::endl;
  109. std::list<std::string> random_order2;
  110. itr = my_list.begin_random();
  111. for (int i = 0; i < my_list.size(); i++,itr++) {
  112. std::cout << " " << *itr << std::endl;
  113. random_order2.push_back(*itr);
  114. }
  115. std::cout << std::endl;
  116. // with over 3 million different possible permutations of 10
  117. // elements, it is highly unlikely they will be the same!
  118. assert (!same(random_order,random_order2));
  119. // -------------------
  120. // erase tests
  121. // erase the first element inserted
  122. itr = my_list.begin_chronological();
  123. assert (*itr == "hound dog");
  124. itr = my_list.erase(itr);
  125. assert (*itr == "poker face");
  126. assert (my_list.size() == 9);
  127. std::cout << "erased: hound dog" << std::endl;
  128. // erase the second to last element in sorted order
  129. itr = my_list.begin_sorted();
  130. for (int i = 0; i < 7; i++) { itr++; }
  131. assert (*itr == "stairway to heaven");
  132. itr = my_list.erase(itr);
  133. assert (*itr == "walk like an egyptian");
  134. assert (my_list.size() == 8);
  135. std::cout << "erased: stairway to heaven" << std::endl;
  136. // erase the third element in the random order
  137. itr = my_list.begin_random();
  138. itr++;
  139. itr++;
  140. std::string tmp = *itr;
  141. // note that the return value of erase with a random iterator is undefined
  142. my_list.erase(itr);
  143. std::cout << "erased: " << tmp << std::endl;
  144. assert (my_list.size() == 7);
  145. assert (!my_list.empty());
  146. my_list.clear();
  147. assert (my_list.empty());
  148. assert (my_list.size() == 0);
  149. std::cout << "cleared the whole list!" << std::endl << std::endl;
  150. // ---------------------------
  151. // ADD YOUR OWN TEST CASES BELOW
  152. // be sure to test:
  153. // copy constructor
  154. // assignment operator
  155. // destructor
  156. // all corner cases of erase
  157. // decrement operator for the chronological & sorted iterators
  158. // pre vs. post increment & decrement operations for iterators
  159. // MultiLL containing types other than std::string
  160. // anything else that is necessary
  161. // Test copy constructor
  162. MultiLL<std::string> string_ml;
  163. string_ml.add("hound dog");
  164. string_ml.add("poker face");
  165. string_ml.add("brown eyed girl");
  166. string_ml.add("let it be");
  167. string_ml.add("walk like an egyptian");
  168. string_ml.add("man in the mirror");
  169. string_ml.add("stairway to heaven");
  170. string_ml.add("dancing in the street");
  171. string_ml.add("every breath you take");
  172. string_ml.add("hotel california");
  173. MultiLL<std::string> string2(string_ml);
  174. assert(same(string2, string_ml));
  175. string2.clear();
  176. assert(string2.empty());
  177. std::cout << "Copy constructor passes correctly\n" << std::endl;
  178. // Test Assignment operator
  179. MultiLL<std::string> string3;
  180. string3 = string_ml;
  181. assert(same(string3, string_ml));
  182. string3.clear();
  183. assert(string3.empty());
  184. std::cout << "Assignment operator passes correctly\n" << std::endl;
  185. // Test destructor
  186. MultiLL<std::string> *string_dyn = new MultiLL<std::string>(string_ml);
  187. assert(same(*string_dyn, string_ml));
  188. delete string_dyn;
  189. std::cout << "Destructor works correctly\n" << std::endl;
  190. // Test erase
  191. MultiLL<std::string> e_string(string_ml);
  192. assert(same(e_string, string_ml));
  193. MultiLL<std::string>::iterator eitr = e_string.begin_chronological();
  194. eitr = e_string.erase(eitr);
  195. assert(e_string.size() == 9);
  196. for (int c = 0; c < e_string.size() - 1; c++) {
  197. eitr++;
  198. }
  199. eitr = e_string.erase(eitr);
  200. assert(e_string.size() == 8);
  201. /*
  202. eitr = e_string.erase(eitr);
  203. eitr = e_string.erase(eitr);
  204. eitr = e_string.erase(eitr);
  205. eitr = e_string.erase(eitr);
  206. eitr = e_string.erase(eitr);
  207. eitr = e_string.erase(eitr);
  208. eitr = e_string.erase(eitr);
  209. assert(eitr == e_string.end_chronological());
  210. assert(e_string.begin_chronological() == e_string.end_chronological());
  211. e_string.clear();
  212. assert(e_string.empty());
  213. */
  214. std::cout << "Erase seems to work correctly with all edge cases\n" << std::endl;
  215. // Test preincrement/postincrement operators
  216. MultiLL<std::string> p_string;
  217. p_string = string_ml;
  218. assert(same(p_string, string_ml));
  219. MultiLL<std::string>::iterator pitr = p_string.begin_sorted();
  220. pitr++;
  221. std::string original = *pitr;
  222. pitr++;
  223. ++pitr;
  224. --pitr;
  225. pitr--;
  226. assert(original == *pitr);
  227. pitr = p_string.erase(pitr);
  228. original = *pitr;
  229. pitr++;
  230. ++pitr;
  231. --pitr;
  232. pitr--;
  233. assert(original == *pitr);
  234. std::cout << "Post and pre increment work correctly\n" << std::endl;
  235. // Test alternate data types
  236. MultiLL<int> t_int;
  237. t_int.clear();
  238. t_int.add(123);
  239. t_int.add(235);
  240. t_int.add(23);
  241. t_int.add(562);
  242. t_int.add(63);
  243. t_int.add(7632);
  244. t_int.add(12);
  245. t_int.add(52451);
  246. assert(t_int.size() == 8);
  247. MultiLL<int>::iterator aitr = t_int.begin_chronological();
  248. aitr++;
  249. aitr = t_int.erase(aitr);
  250. assert(t_int.size() == 7);
  251. t_int.clear();
  252. assert(t_int.empty());
  253. std::cout << "Alternate data type (int) works\n" << std::endl;
  254. }