| 1 | /** |
| 2 | * @file Tree.c |
| 3 | */ |
| 4 | |
| 5 | #include "cgds/Tree.h" |
| 6 | |
| 7 | //////////////// |
| 8 | // Tree logic // |
| 9 | //////////////// |
| 10 | |
| 11 | void _tree_init(Tree* tree, size_t dataSize) |
| 12 | { |
| 13 | tree->root = NULL; |
| 14 | tree->dataSize = dataSize; |
| 15 | tree->size = 0; |
| 16 | } |
| 17 | |
| 18 | Tree* _tree_new(size_t dataSize) |
| 19 | { |
| 20 | Tree* tree = (Tree*) safe_malloc(sizeof (Tree)); |
| 21 | _tree_init(tree, dataSize); |
| 22 | return tree; |
| 23 | } |
| 24 | |
| 25 | Tree* tree_copy(Tree* tree) |
| 26 | { |
| 27 | Tree* treeCopy = _tree_new(tree->dataSize); |
| 28 | if (tree->root == NULL) |
| 29 | return treeCopy; |
| 30 | _tree_set_root(treeCopy, tree->root->data); |
| 31 | |
| 32 | // Now parallel run on both trees (manual breadth-first walk) |
| 33 | TreeNode* treeNode = tree->root; |
| 34 | TreeNode* treeNodeCopy = treeCopy->root; |
| 35 | while (treeNode != NULL) |
| 36 | { |
| 37 | // process current children |
| 38 | TreeNode* child = treeNode->firstChild; |
| 39 | while (child != NULL) |
| 40 | { |
| 41 | _tree_add_child(treeCopy, treeNodeCopy, child->data); |
| 42 | child = child->next; |
| 43 | } |
| 44 | |
| 45 | // try to go to next sibling (NOTE: already added as child of parent) |
| 46 | if (treeNode->next != NULL) |
| 47 | { |
| 48 | treeNode = treeNode->next; |
| 49 | treeNodeCopy = treeNodeCopy->next; |
| 50 | continue; |
| 51 | } |
| 52 | |
| 53 | // try to go to next "cousin" on same level |
| 54 | if (treeNode->parent != NULL && treeNode->parent->next != NULL) |
| 55 | { |
| 56 | TreeNode* treeNodeParent = treeNode->parent->next; |
| 57 | TreeNode* treeNodeParentCopy = treeNodeCopy->parent->next; |
| 58 | while (treeNodeParent != NULL && tree_is_leaf(treeNodeParent)) |
| 59 | { |
| 60 | treeNodeParent = treeNodeParent->next; |
| 61 | treeNodeParentCopy = treeNodeParentCopy->next; |
| 62 | } |
| 63 | if (treeNodeParent != NULL) |
| 64 | { |
| 65 | treeNode = treeNodeParent->firstChild; |
| 66 | treeNodeCopy = treeNodeParentCopy->firstChild; |
| 67 | continue; |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | // try to go to next level, and move treeNodeCopy accordingly |
| 72 | while (treeNode->prev != NULL) |
| 73 | { |
| 74 | treeNode = treeNode->prev; |
| 75 | treeNodeCopy = treeNodeCopy->prev; |
| 76 | } |
| 77 | while (treeNode != NULL && tree_is_leaf(treeNode)) |
| 78 | { |
| 79 | treeNode = treeNode->next; |
| 80 | treeNodeCopy = treeNodeCopy->next; |
| 81 | } |
| 82 | if (treeNode != NULL) |
| 83 | { |
| 84 | treeNode = treeNode->firstChild; |
| 85 | treeNodeCopy = treeNodeCopy->firstChild; |
| 86 | } |
| 87 | } |
| 88 | return treeCopy; |
| 89 | } |
| 90 | |
| 91 | Bool tree_empty(Tree* tree) |
| 92 | { |
| 93 | return (tree->root == NULL); |
| 94 | } |
| 95 | |
| 96 | UInt tree_size(Tree* tree) |
| 97 | { |
| 98 | return tree->size; |
| 99 | } |
| 100 | |
| 101 | UInt _tree_height_rekursiv(TreeNode* treeNode) |
| 102 | { |
| 103 | if (tree_is_leaf(treeNode)) |
| 104 | return 1; |
| 105 | TreeNode* child = treeNode->firstChild; |
| 106 | UInt maxHeightChild = 0; |
| 107 | while (child != NULL) |
| 108 | { |
| 109 | UInt heightChild = _tree_height_rekursiv(child); |
| 110 | if (heightChild > maxHeightChild) |
| 111 | maxHeightChild = heightChild; |
| 112 | child = child->next; |
| 113 | } |
| 114 | return 1 + maxHeightChild; |
| 115 | } |
| 116 | |
| 117 | UInt tree_height(Tree* tree) |
| 118 | { |
| 119 | if (tree_empty(tree)) |
| 120 | return 0; |
| 121 | return _tree_height_rekursiv(tree->root); |
| 122 | } |
| 123 | |
| 124 | Bool tree_is_leaf(TreeNode* treeNode) |
| 125 | { |
| 126 | return (treeNode->firstChild == NULL); |
| 127 | } |
| 128 | |
| 129 | void _tree_set_root(Tree* tree, void* data) |
| 130 | { |
| 131 | tree->root = (TreeNode*) safe_malloc(sizeof (TreeNode)); |
| 132 | tree->root->data = safe_malloc(tree->dataSize); |
| 133 | memcpy(tree->root->data, data, tree->dataSize); |
| 134 | tree->root->parent = NULL; |
| 135 | tree->root->firstChild = NULL; |
| 136 | tree->root->lastChild = NULL; |
| 137 | tree->root->prev = NULL; |
| 138 | tree->root->next = NULL; |
| 139 | tree->size = 1; |
| 140 | } |
| 141 | |
| 142 | void* _tree_get(TreeNode* treeNode) |
| 143 | { |
| 144 | return treeNode->data; |
| 145 | } |
| 146 | |
| 147 | void _tree_set(Tree* tree, TreeNode* treeNode, void* data) |
| 148 | { |
| 149 | memcpy(treeNode->data, data, tree->dataSize); |
| 150 | } |
| 151 | |
| 152 | void _tree_add_child(Tree* tree, TreeNode* treeNode, void* data) |
| 153 | { |
| 154 | TreeNode* newChildNode = (TreeNode*) safe_malloc(sizeof (TreeNode)); |
| 155 | newChildNode->data = safe_malloc(tree->dataSize); |
| 156 | memcpy(newChildNode->data, data, tree->dataSize); |
| 157 | newChildNode->next = NULL; |
| 158 | if (treeNode->lastChild != NULL) |
| 159 | treeNode->lastChild->next = newChildNode; |
| 160 | newChildNode->prev = treeNode->lastChild; |
| 161 | treeNode->lastChild = newChildNode; |
| 162 | if (treeNode->firstChild == NULL) |
| 163 | treeNode->firstChild = newChildNode; |
| 164 | newChildNode->parent = treeNode; |
| 165 | newChildNode->firstChild = NULL; |
| 166 | newChildNode->lastChild = NULL; |
| 167 | tree->size++; |
| 168 | } |
| 169 | |
| 170 | void _tree_add_sibling(Tree* tree, TreeNode* treeNode, void* data) |
| 171 | { |
| 172 | TreeNode* newSiblingNode = (TreeNode*) safe_malloc(sizeof (TreeNode)); |
| 173 | newSiblingNode->data = safe_malloc(tree->dataSize); |
| 174 | memcpy(newSiblingNode->data, data, tree->dataSize); |
| 175 | newSiblingNode->next = treeNode->next; |
| 176 | if (treeNode->next != NULL) |
| 177 | treeNode->next->prev = newSiblingNode; |
| 178 | newSiblingNode->prev = treeNode; |
| 179 | treeNode->next = newSiblingNode; |
| 180 | newSiblingNode->parent = treeNode->parent; |
| 181 | newSiblingNode->firstChild = NULL; |
| 182 | newSiblingNode->lastChild = NULL; |
| 183 | tree->size++; |
| 184 | } |
| 185 | |
| 186 | void _tree_remove_rekursiv(Tree* tree, TreeNode* treeNode) |
| 187 | { |
| 188 | TreeNode* child = treeNode->firstChild; |
| 189 | while (child != NULL) |
| 190 | { |
| 191 | TreeNode* nextChild = child->next; |
| 192 | _tree_remove_rekursiv(tree, child); |
| 193 | child = nextChild; |
| 194 | } |
| 195 | safe_free(treeNode->data); |
| 196 | safe_free(treeNode); |
| 197 | tree->size--; |
| 198 | } |
| 199 | |
| 200 | void tree_remove(Tree* tree, TreeNode* treeNode) |
| 201 | { |
| 202 | if (treeNode->parent != NULL) |
| 203 | { |
| 204 | if (treeNode->prev == NULL) |
| 205 | treeNode->parent->firstChild = treeNode->next; |
| 206 | if (treeNode->next == NULL) |
| 207 | treeNode->parent->lastChild = treeNode->prev; |
| 208 | } |
| 209 | if (treeNode->next != NULL) |
| 210 | treeNode->next->prev = treeNode->prev; |
| 211 | if (treeNode->prev != NULL) |
| 212 | treeNode->prev->next = treeNode->next; |
| 213 | _tree_remove_rekursiv(tree, treeNode); |
| 214 | } |
| 215 | |
| 216 | void tree_rm_childs(Tree* tree, TreeNode* treeNode) |
| 217 | { |
| 218 | TreeNode* child = treeNode->firstChild; |
| 219 | while (child != NULL) |
| 220 | { |
| 221 | TreeNode* nextChild = child->next; |
| 222 | _tree_remove_rekursiv(tree, child); |
| 223 | child = nextChild; |
| 224 | } |
| 225 | treeNode->firstChild = NULL; |
| 226 | treeNode->lastChild = NULL; |
| 227 | } |
| 228 | |
| 229 | void tree_clear(Tree* tree) |
| 230 | { |
| 231 | if (tree->root != NULL) |
| 232 | _tree_remove_rekursiv(tree, tree->root); |
| 233 | _tree_init(tree, tree->dataSize); |
| 234 | } |
| 235 | |
| 236 | void tree_destroy(Tree* tree) |
| 237 | { |
| 238 | if (tree->root != NULL) |
| 239 | tree_clear(tree); |
| 240 | safe_free(tree); |
| 241 | } |
| 242 | |
| 243 | //////////////////// |
| 244 | // Iterator logic // |
| 245 | //////////////////// |
| 246 | |
| 247 | TreeIterator* tree_get_iterator(Tree* tree, TreeIteratorMode mode) |
| 248 | { |
| 249 | TreeIterator* treeI = (TreeIterator*) safe_malloc(sizeof (TreeIterator)); |
| 250 | treeI->tree = tree; |
| 251 | treeI->mode = mode; |
| 252 | treeI_reset(treeI); |
| 253 | return treeI; |
| 254 | } |
| 255 | |
| 256 | void treeI_reset(TreeIterator* treeI) |
| 257 | { |
| 258 | treeI->current = treeI->tree->root; |
| 259 | } |
| 260 | |
| 261 | Bool treeI_has_data(TreeIterator* treeI) |
| 262 | { |
| 263 | return (treeI->current != NULL); |
| 264 | } |
| 265 | |
| 266 | TreeNode* treeI_get_raw(TreeIterator* treeI) |
| 267 | { |
| 268 | return treeI->current; |
| 269 | } |
| 270 | |
| 271 | void treeI_move_next(TreeIterator* treeI) |
| 272 | { |
| 273 | TreeIteratorMode mode = treeI->mode; |
| 274 | switch (mode) |
| 275 | { |
| 276 | case IN_DEPTH: |
| 277 | if (!tree_is_leaf(treeI->current)) |
| 278 | { |
| 279 | // easy case: just descend deeper in the tree |
| 280 | treeI->current = treeI->current->firstChild; |
| 281 | return; |
| 282 | } |
| 283 | // leaf: while no next sibling is available, move up |
| 284 | while (treeI->current != NULL && treeI->current->next == NULL) |
| 285 | treeI->current = treeI->current->parent; |
| 286 | if (treeI->current != NULL) |
| 287 | // run goes on from next sibling |
| 288 | treeI->current = treeI->current->next; |
| 289 | break; |
| 290 | case IN_BREADTH: |
| 291 | if (treeI->current->next != NULL) |
| 292 | { |
| 293 | // easy case : just move to the next sibling |
| 294 | treeI->current = treeI->current->next; |
| 295 | return; |
| 296 | } |
| 297 | // try to go to next "cousin" on same level |
| 298 | if (treeI->current->parent != NULL && treeI->current->parent->next != NULL) |
| 299 | { |
| 300 | TreeNode* treeNodeParent = treeI->current->parent->next; |
| 301 | while (treeNodeParent != NULL && tree_is_leaf(treeNodeParent)) |
| 302 | treeNodeParent = treeNodeParent->next; |
| 303 | if (treeNodeParent != NULL) |
| 304 | { |
| 305 | treeI->current = treeNodeParent->firstChild; |
| 306 | return; |
| 307 | } |
| 308 | } |
| 309 | // try to go to next level |
| 310 | while (treeI->current->prev != NULL) |
| 311 | treeI->current = treeI->current->prev; |
| 312 | while (treeI->current != NULL && tree_is_leaf(treeI->current)) |
| 313 | treeI->current = treeI->current->next; |
| 314 | if (treeI->current != NULL) |
| 315 | treeI->current = treeI->current->firstChild; |
| 316 | break; |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | void treeI_destroy(TreeIterator* treeI) |
| 321 | { |
| 322 | safe_free(treeI); |
| 323 | } |