This code is a revised version of the implementation which asked for an advice on improvement. Original post here: Counting unival subtrees Credits to: [Deduplicator], [Reinderien], [Toby Speight], [chux].
The revised version was applied following changes:
- Merge
insertRight(), insertLeft()
function intocreateNode
function - free resources after use
- used
const
if referenced memory address value is not altered. - fix
isTreeUniv()
into recursive version - get rid of globals
Revised code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct stTree
{
struct stTree *left;
struct stTree *right;
int value;
} stTree;
stTree* createNode(int value, stTree *leftNode, stTree *rightNode)
{
stTree *node = malloc(sizeof *node);
if (!node) abort();
node->left = leftNode;
node->right = rightNode;
node->value = value;
return node;
}
bool isUnivSubTimpl(const stTree *node, const stTree *parent, size_t *count)
{
if (!node) return 1; //node without child count as unival subT
bool r = isUnivSubTimpl(node->left, node, count) &isUnivSubTimpl(node->right, node, count);
*count += r;
return (r &node->value == parent->value);
}
size_t countUnivSubT(const stTree *node)
{
size_t count = 0;
isUnivSubTimpl(node, node, &count);
return count;
}
static stTree* findBottomLeft(stTree *node)
{
while (node->left)
node = node->left;
return node;
}
bool freeTree(stTree *node)
{
if (!node) return true;
stTree *bottomLeft = findBottomLeft(node);
while (node)
{
if (node->right)
{
bottomLeft->left = node->right;
bottomLeft = findBottomLeft(bottomLeft);
}
stTree *old = node;
node = node->left;
free(old);
}
return true;
}
int main(void)
{
//build a tree
stTree *rootNode =
createNode(0,
createNode(1, NULL, NULL),
createNode(0,
createNode(1,
createNode(1, NULL, NULL),
createNode(1, NULL, NULL)
),
createNode(0, NULL, NULL)));
printf("total universal subree: %u\n", countUnivSubT(rootNode));
if (freeTree(rootNode))
printf("memory released\n");
}