1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include "gtree.h"
static unsigned int nodeId = 0;
/*Enum to track if we are going up or down the tree*/
enum DIRECTION {
up,
down
};
typedef enum DIRECTION DIRECTION_t;
DIRECTION_t path = down;
gtRoot_t *newGT(void)
{
return calloc(1, sizeof(gtRoot_t));
}
void freeGt(gtRoot_t *pRoot)
{
traverseTree(pRoot, post, (nodeActionFunc_t *)free);
free(pRoot);
}
/*Private function to find the last node in a level. I think this can be simplified
Will look into this later*/
gtNode_t *_findLastNode(gtNode_t *pFirstChild)
{
if (pFirstChild == NULL)
return NULL;
gtNode_t *pNode = NULL, *pNextNode = NULL, *pLastNode = NULL;
for (pNode = pFirstChild; pNode != NULL; pNode = pNextNode)
{
if (pNode != NULL)
pLastNode = pNode;
pNextNode = pNode->pSibling;
}
return pLastNode;
}
gtNode_t *addChildNode(gtRoot_t *pBtRoot, gtNode_t *pParentNode, void *pNodeData)
{
gtNode_t *pNewNode = NULL;
/*If the root structure is unitialised, exit with error*/
if (pBtRoot == NULL)
return NULL;
/*If we fail to allocate memory for our new structure, exit with error*/
if ((pNewNode = calloc(1, sizeof(gtNode_t))) == NULL)
return NULL;
/*If we are the first child of the tree, initialise everything to NULL*/
if (pBtRoot->pRoot == NULL)
{
/*Register the new node to the root of the tree*/
pBtRoot->pRoot = pNewNode;
pNewNode->id = nodeId++;
pNewNode->pParent = NULL;
pNewNode->pSibling = NULL;
pNewNode->pFirstChild = NULL;
pNewNode->pNodeData = pNodeData;
/*Tree already contains at least one element, so we need to add ourselves in*/
} else {
pNewNode->id = nodeId++;
pNewNode->pParent = pParentNode;
pNewNode->pSibling = NULL;
pNewNode->pFirstChild = NULL;
pNewNode->pNodeData = pNodeData;
/*If our parent has no children nodes, it means the first one is us*/
if (pParentNode->pFirstChild == NULL)
pParentNode->pFirstChild = pNewNode;
/*If our parent has already has childrens, we need to add ourself at the end
of the list. We are the last sibling*/
else
_findLastNode(pParentNode->pFirstChild)->pSibling = pNewNode;
}
return pNewNode;
}
/*Just a wrapper of the traverseTree function to enable us to use the root of the
tree as an entry point*/
int traverseTree(gtRoot_t *pGtRoot, ORDER_t traversal, nodeActionFunc_t *nodeAction)
{
return traverseBranch(pGtRoot->pRoot, traversal, nodeAction);
}
int traverseBranch(gtNode_t *pNode, ORDER_t traversal, nodeActionFunc_t *nodeAction)
{
if (pNode == NULL)
return -1;
/* Depeding on what we are asked to do, either act on the parent node before visiting
children (pre-order), or act on the parent node after visiting the children
(post-order) */
switch (traversal) {
/*When we are doing pre-order, act on the node on the first visit*/
case pre:
if (path == down)
nodeAction(pNode);
break;
/*When we are doing post-order, act on the node on last visit, and print all
nodes with no children*/
case post:
if ((path == up) || (pNode->pFirstChild == NULL))
nodeAction(pNode);
break;
/*We should never get there, so exit on error*/
default:
return -1;
}
if (pNode->pFirstChild != NULL)
{
/*If we are going down the tree, we just visit the next child*/
if (path == down)
{
traverseBranch(pNode->pFirstChild, traversal, nodeAction);
/*If we are going up, we have 2 cases. If we have a sibling to our right,
visit it, and possilby his children (so set the path to down). If we have no
more siblings to our right, we must go up to our parent (so set path to up)*/
} else {
if (pNode->pSibling != NULL)
{
path = down;
traverseBranch(pNode->pSibling, traversal, nodeAction);
} else {
path = up;
traverseBranch(pNode->pParent, traversal, nodeAction);
}
}
/*We have no children under our node*/
} else {
/*Let's follow our right sibling if we have one*/
if (pNode->pSibling != NULL)
{
traverseBranch(pNode->pSibling, traversal, nodeAction);
/*If we don't have a right sibling, then we must go up to ur parent (so set
path to up) */
} else {
path = up;
traverseBranch(pNode->pParent, traversal, nodeAction);
}
}
return 0;
} |
Partager