Tree.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #ifndef __TREE_H
  2. #define __TREE_H
  3. #include <forward_list>
  4. // Tree is both a linked list and a binary tree.
  5. // A linked list is easy to loop through.
  6. // A binary tree is fast to search through.
  7. template <typename T>
  8. class TreeNode
  9. {
  10. public:
  11. T *Item;
  12. TreeNode<T> *Smaller;
  13. TreeNode<T> *Bigger;
  14. TreeNode()
  15. {
  16. Item = nullptr;
  17. Smaller = nullptr;
  18. Bigger = nullptr;
  19. }
  20. TreeNode(T *item)
  21. {
  22. Item = item;
  23. Smaller = nullptr;
  24. Bigger = nullptr;
  25. }
  26. ~TreeNode()
  27. {
  28. if (Item != nullptr) {
  29. delete Item;
  30. Item = nullptr;
  31. }
  32. if (Smaller != nullptr) {
  33. delete Smaller;
  34. Smaller = nullptr;
  35. }
  36. if (Bigger != nullptr) {
  37. delete Bigger;
  38. Bigger = nullptr;
  39. }
  40. }
  41. };
  42. template <typename T>
  43. class Tree
  44. {
  45. public:
  46. TreeNode<T> *SortedList; // This is a binary tree.
  47. std::forward_list<T*> List; // All the items in SortedList are also in List.
  48. void Clear()
  49. {
  50. while (!List.empty()) {
  51. List.pop_front(); // The item is not deleted because it's also being stored in the SortedList tree.
  52. }
  53. if (SortedList != nullptr) {
  54. delete SortedList;
  55. SortedList = nullptr;
  56. }
  57. }
  58. // Find a node or the next place it goes. Returns found status in found.
  59. TreeNode<T> *Find(T *item,int &found,int (*compareFunction)(T*,T*)) const
  60. {
  61. // If the node was found then found = 0 and the node is returned.
  62. // If the node was not found then found !=0 and the insert point is returned.
  63. // If found < 0 then add to ->Bigger.
  64. // If found > 0 then add to ->Smaller.
  65. // If the list is empty then found = 0 and nullptr is returned.
  66. // If found = 0 and nullptr is returned then the node was not found.
  67. TreeNode<T> *loop;
  68. TreeNode<T> *next;
  69. int compare;
  70. compare = 0;
  71. loop = SortedList;
  72. if (SortedList != nullptr) {
  73. while (true) {
  74. compare = compareFunction(loop->Item,item);
  75. if (compare < 0) {
  76. next = loop->Bigger;
  77. if (next == nullptr) {
  78. break;
  79. }
  80. loop = next;
  81. continue;
  82. }
  83. if (compare > 0) {
  84. next = loop->Smaller;
  85. if (next == nullptr) {
  86. break;
  87. }
  88. loop = next;
  89. continue;
  90. }
  91. break;
  92. }
  93. }
  94. found = compare;
  95. return loop;
  96. }
  97. // Returns all items in this tree that aren't in the other tree.
  98. // Assumes that the calling function has logic in place to not search empty lists.
  99. void Subtract(const Tree<T> &other,std::forward_list<T*> &difference,int (*compareFunction)(T*,T*))
  100. {
  101. int found;
  102. TreeNode<T> *search;
  103. for (auto loop = List.begin(); loop != List.end();++loop) {
  104. search = other.Find(*loop,found,compareFunction);
  105. if ((found != 0) && (search != nullptr)) {
  106. difference.push_front(*loop);
  107. }
  108. }
  109. }
  110. // Adds an item to this tree. Returns true if successful.
  111. // Sets *item to nullptr if the item is moved to the tree.
  112. bool Add(T **item,int (*compareFunction)(T*,T*)) {
  113. int found;
  114. TreeNode<T> *search;
  115. if ((item == nullptr) || (*item == nullptr)) {
  116. return false;
  117. }
  118. if (SortedList == nullptr) {
  119. SortedList = new TreeNode<T>(*item);
  120. if (SortedList == nullptr) {
  121. throw "Out of memory in Tree.Add";
  122. }
  123. List.push_front(*item);
  124. *item = nullptr;
  125. return true;
  126. }
  127. search = Find(*item,found,compareFunction);
  128. if (found < 0) {
  129. search->Bigger = new TreeNode<T>(*item);
  130. if (search->Bigger == nullptr) {
  131. throw "Out of memory in Tree.Add";
  132. }
  133. List.push_front(*item);
  134. *item = nullptr;
  135. }
  136. if (found > 0) {
  137. search->Smaller = new TreeNode<T>(*item);
  138. if (search->Smaller == nullptr) {
  139. throw "Out of memory in Tree.Add";
  140. }
  141. List.push_front(*item);
  142. *item = nullptr;
  143. }
  144. return true;
  145. }
  146. Tree()
  147. {
  148. SortedList = nullptr;
  149. }
  150. ~Tree()
  151. {
  152. Clear();
  153. }
  154. };
  155. #endif