Advertisement
Cinestra

Project 2 before Carey ruins everything par 2

Mar 3rd, 2023
26
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.89 KB | None | 0 0
  1. #include "Set.h"
  2. #include <iostream>
  3.  
  4. void Set::initializeEmptySet()
  5. {
  6. m_size = 0;
  7.  
  8. m_head = nullptr;
  9. m_tail = m_head;
  10. }
  11.  
  12. Set::Set()
  13. {
  14. initializeEmptySet();
  15. }
  16.  
  17. // Before we can actually insert the node, we need to implement the insert before function
  18. void Set::insertNewHead(const ItemType& value)
  19. {
  20.  
  21. Node* new_head = new Node;
  22. new_head->m_value = value;
  23.  
  24. if (m_head == nullptr)
  25. {
  26. m_head = new_head;
  27. m_head->m_next = nullptr;
  28. m_head->m_prev = nullptr;
  29. m_tail = m_head;
  30. m_size++;
  31. return;
  32. }
  33.  
  34. m_head->m_prev = new_head;
  35. new_head->m_prev = nullptr;
  36. new_head->m_next = m_head;
  37. m_head = new_head;
  38.  
  39. m_size++;
  40. }
  41.  
  42. void Set::insertNewTail(const ItemType& value)
  43. {
  44. Node* new_tail = new Node;
  45. m_tail->m_next = new_tail;
  46. new_tail->m_value = value;
  47. new_tail->m_prev = m_tail;
  48. new_tail->m_next = nullptr;
  49. m_tail = new_tail;
  50.  
  51. m_size++;
  52. }
  53.  
  54. void Set::insertBefore(Node* p, const ItemType& value)
  55. {
  56. //Create a new node
  57.  
  58. Node* new_pointer = new Node;
  59. new_pointer->m_value = value;
  60.  
  61. if (p == m_head)
  62. {
  63. insertNewHead(value);
  64. return;
  65. }
  66.  
  67. // Set the new pointer's previous pointer equal to p's previous pointer
  68. // Then set the new pointer's next pointer equal to p
  69. new_pointer->m_prev = p->m_prev;
  70. new_pointer->m_next = p;
  71.  
  72. // We must now make the previous nodes point to this new node
  73. // Then we must make the next node have its previous point to this node.
  74. new_pointer->m_prev->m_next = new_pointer;
  75. new_pointer->m_next->m_prev = new_pointer;
  76.  
  77. m_size++;
  78. }
  79.  
  80. // I have no idea how to write these function parameters
  81. // Why is there a Set:: before declaring a node pointer?
  82. // Is it because we can only define what a node pointer is after defining it's from the Set class?
  83. Set::Node* Set::findClosestLocation(const ItemType& value) const
  84. {
  85. Node* traversalNode = m_head;
  86.  
  87. while (traversalNode->m_next != nullptr && traversalNode->m_value < value)
  88. traversalNode = traversalNode->m_next;
  89.  
  90. return traversalNode;
  91. }
  92.  
  93. bool Set::insert(const ItemType& value)
  94. {
  95.  
  96. // First case to consider is if the set is empty to begin with
  97. // The initialized set actually starts with a node, but with no value inside it and a size of 0
  98. // So we will simply overwrite the value inside it and update its size
  99. if (m_head == nullptr)
  100. {
  101. insertNewHead(value);
  102. return true;
  103. }
  104.  
  105. // Second check if we already have that value in our linked list
  106. // We checked if the set was empty first so that we don't try checking node's value if there isn't any to begin with
  107. Node* closestNode = findClosestLocation(value);
  108.  
  109. if (closestNode->m_value == value)
  110. return false;
  111.  
  112. // Then if it's closest node is the tail, we'll check if it should go before or after the tail
  113. // If we need to create a new tail, then we'll run that function
  114. // If not, we can actually just insert it before the tail (and run it like everything else)
  115. else if (closestNode == m_tail)
  116. {
  117. if (value > m_tail->m_value)
  118. {
  119. insertNewTail(value);
  120. return true;
  121. }
  122. }
  123.  
  124. // insertBefore command actually checks if it should be a new head
  125. insertBefore(closestNode, value);
  126. return true;
  127. }
  128.  
  129. void Set::actualErase(Node* p)
  130. {
  131. // There are 4 cases to consider
  132. // If there is only a single node, then we will delete it and set its next and prev to nullptr
  133. // This is different from deleting a node in the middle because we don't have to link surrounding nodes together after deletion
  134. if (m_size == 1)
  135. {
  136. p->m_next = p->m_prev = nullptr;
  137. m_head = nullptr;
  138. m_tail = nullptr;
  139. }
  140.  
  141. // If we are deleting the head, then we must allocate a new head
  142. else if (p == m_head)
  143. {
  144. m_head = m_head->m_next;
  145. p->m_next->m_prev = nullptr;
  146. }
  147.  
  148. // If we are deleting the tail, then we must allocate a new tail
  149. else if (p == m_tail)
  150. {
  151. m_tail = m_tail->m_prev;
  152. p->m_prev->m_next = nullptr;
  153. }
  154.  
  155. // Because we are deleting a node in the middle, we need to make sure that we are linking the surrounding nodes together
  156. else
  157. {
  158. p->m_prev->m_next = p->m_next;
  159. p->m_next->m_prev = p->m_prev;
  160. }
  161.  
  162. delete p;
  163. m_size--;
  164. }
  165.  
  166. bool Set::erase(const ItemType& value)
  167. {
  168. if (m_size == 0)
  169. return false;
  170.  
  171. Node* closestNode = findClosestLocation(value);
  172.  
  173. if (closestNode->m_value != value)
  174. return false;
  175.  
  176. actualErase(closestNode);
  177. return true;
  178. }
  179.  
  180. Set::~Set()
  181. {
  182. while (m_size > 0)
  183. actualErase(m_head);
  184. }
  185.  
  186. void Set::printLinkedList()
  187. {
  188. Node* traversalNode = m_head;
  189.  
  190. while (traversalNode != nullptr)
  191. {
  192. std::cout << traversalNode->m_value << " ";
  193. traversalNode = traversalNode->m_next;
  194. }
  195.  
  196. std::cout << "\n";
  197. }
  198.  
  199. bool Set::contains(const ItemType& value) const
  200. {
  201. if (m_size == 0)
  202. {
  203. return false;
  204. }
  205.  
  206. Node* closestNode = findClosestLocation(value);
  207. return (closestNode->m_value == value);
  208. }
  209.  
  210. bool Set::get(int i, ItemType& value) const
  211. {
  212. if (i < 0 || i >= m_size)
  213. return false;
  214.  
  215. Node* traversalNode;
  216.  
  217. // Closer to head
  218. if (i < (m_size / 2))
  219. {
  220. traversalNode = m_head;
  221. for (int j = 0; j != i; j++)
  222. {
  223. traversalNode = traversalNode->m_next;
  224. }
  225. }
  226.  
  227. // Closer to tail
  228. else
  229. {
  230. traversalNode = m_tail;
  231. for (int j = m_size - 1; j != i; j--)
  232. traversalNode = traversalNode->m_prev;
  233. }
  234.  
  235. value = traversalNode->m_value;
  236. return true;
  237. }
  238.  
  239. void Set::swap(Set& other)
  240. {
  241. Node* tempHead = other.m_head;
  242. other.m_head = m_head;
  243. m_head = tempHead;
  244.  
  245. int tempSize = other.m_size;
  246. other.m_size = m_size;
  247. m_size = tempSize;
  248.  
  249. Node* tempTail = other.m_tail;
  250. other.m_tail = m_tail;
  251. m_tail = tempTail;
  252. }
  253.  
  254. Set::Set(const Set& other)
  255. {
  256. initializeEmptySet();
  257.  
  258. Node* traversalNode = other.m_head;
  259.  
  260. for (int i = 0; i < other.m_size; i++)
  261. {
  262. insert(traversalNode->m_value);
  263. traversalNode = traversalNode->m_next;
  264. }
  265. }
  266.  
  267. Set& Set::operator=(const Set& other)
  268. {
  269. // Trying to avoid aliasing, which is when we use two different pointers/ references to acess the same variable
  270. // This is a problem if we try to first delete the data of the original before reassigning it to itself
  271. // Our solution it see if the parameter has the same object address as the target object
  272. if (this == &other)
  273. {
  274. return *this;
  275. }
  276.  
  277. // Typically, we could simply delete the elements inside the array now, but Carey doesn't want us to use a for loop
  278. // Thus, we will do the Smallberg method of using a copy constructor and a swap method
  279.  
  280. // Call the copy constructor to recreate the other set and then swap elements between the original set and the copied set
  281. // Temporary array will actually deconstruct itself
  282. Set temp(other);
  283. swap(temp);
  284.  
  285. // Return the dereferenced contents of the Sets
  286. // Now works for a = b = c as well
  287. return *this;
  288. }
  289.  
  290. void unite(const Set& s1, const Set& s2, Set& result)
  291. {
  292. // We have to worry about aliasing, which is when we use two different pointers/ references to acess the same variable
  293. // The big worry here is if inputted result is actually s1 or s2
  294.  
  295. // If s1, s2, and result are all the same-- then the result is already the union
  296. // If the result is s1, insert s2's elements into the result
  297. // If the result is s2, insert s1's elements into the result
  298. // If the result is its own distinct set, we will first assign it s1's contents, then check if s2 is the same as s1, and if they are different then we will insert s2 into s1
  299.  
  300. // Naturally we will try to insert S2 into S1
  301. const Set* insertedSet = &s2;
  302.  
  303. // First let's check if s1, s2, and result are all the same
  304. if (&result == &s1 && &result == &s2)
  305. {
  306. return;
  307. }
  308.  
  309. // If result is the same as S2, we will make the insertedNode into s1
  310. else if (&result == &s2)
  311. {
  312. insertedSet = &s1;
  313. }
  314.  
  315. // Now that we have determined that result is not s2 and that s1, s2, and result are not all the same
  316. // We will assign result to be equal to s1
  317. // Then we will check if s1 and s2 are the same
  318. // If they are, then we will simply return the set
  319. else
  320. {
  321. result = s1;
  322. if (&s1 == &s2)
  323. {
  324. return;
  325. }
  326. }
  327.  
  328. // If s1 and s2 are not the same, then we will insert one into the other
  329. // If result was the same address as s2, then we will
  330.  
  331. int size_of_insertedSet = insertedSet->size();
  332. ItemType x;
  333.  
  334. for (int i = 0; i < size_of_insertedSet; i++)
  335. {
  336. insertedSet->get(i, x);
  337. result.insert(x);
  338. }
  339. }
  340.  
  341. void butNot(const Set& s1, const Set& s2, Set& result)
  342. {
  343. // We run into aliasing issues if s2 is the same as result
  344. // There will be an issue if we try removing s2 from result when s2 is the same as result
  345. // Because then result w
  346.  
  347. // So we will actually just make a local copy of s2
  348. Set s2LocalCopy(s2);
  349. int size_of_local_copy = s2LocalCopy.size();
  350.  
  351. // Then we will use the assignment operator to make the result equal to s1 (which implicitly checks for aliasing)
  352. // The problem asks us to remove elements from s1 that are shared with s2 and put them in s2
  353. // So we won't actually run into issues removing elements from s1 when trying to get the result
  354. // So we won't run into aliasing issues with s1 and result being the same
  355. result = s1;
  356.  
  357. for (int i = 0; i < size_of_local_copy; i++)
  358. {
  359. ItemType x;
  360. s2LocalCopy.get(i, x);
  361. result.erase(x);
  362. }
  363.  
  364. }
  365.  
  366. void Set::printDetailedLinkedList()
  367. {
  368. Node* traversalNode = m_head;
  369.  
  370. std::cout << "Size is: " << m_size << "\n";
  371. if (m_head != nullptr)
  372. {
  373. std::cout << "Head is: " << m_head->m_value << "\n";
  374. std::cout << "Tail is: " << m_tail->m_value << "\n";
  375. }
  376.  
  377. for (int i = 0; i < m_size; i++)
  378. {
  379. std::cout << "The " << i << " Node is: " << traversalNode->m_value << "\n";
  380. std::cout << "Its previous location is: " << &(traversalNode->m_prev) << "\n";
  381. if (traversalNode->m_prev == nullptr)
  382. std::cout << "The previous location is a null pointer. \n";
  383. std::cout << "Its next location is: " << &(traversalNode->m_next) << "\n";
  384. if (traversalNode->m_next == nullptr)
  385. std::cout << "The next location is a null pointer. \n";
  386.  
  387. traversalNode = traversalNode->m_next;
  388. }
  389.  
  390. std::cout << "\n";
  391. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement