cmkl/spring-2025/sen-107/00020/matrilinealDescendant.c

227 lines
4.1 KiB
C

/* matrilineal.c
*
* A non-sorted tree of mother-daughter relationships
*
* Created by Pasin Manurangsi, 2025-01-08
* Modified by Thanawin Pattanaphol, 2025-05-02
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Adds person with a given name at the root
*/
#define MAX_CHILDREN 10
#define MAX_NAME_LENGTH 25
#define MAX_PATH_LENGTH 100
typedef struct NODE_T
{
char name[MAX_NAME_LENGTH];
int numChildren;
struct NODE_T* parent;
struct NODE_T* children[MAX_CHILDREN];
} NODE_T;
NODE_T* root = NULL;
NODE_T* createNode(char* name)
{
NODE_T* newNode = (NODE_T*)malloc(sizeof(NODE_T));
if (newNode == NULL)
{
printf("Memory allocation failed.\n");
exit(1);
}
strncpy(newNode->name, name, MAX_NAME_LENGTH - 1);
newNode->name[MAX_NAME_LENGTH - 1] = '\0';
newNode->numChildren = 0;
newNode->parent = NULL;
for (int i = 0; i < MAX_CHILDREN; i++)
{
newNode->children[i] = NULL;
}
printf("Added\n");
return newNode;
}
// Create the root
NODE_T* addRoot(char* name)
{
if (root != NULL)
{
printf("Root already exists.\n");
return root;
}
root = createNode(name);
return root;
}
// Function that helps finding a node by name
NODE_T* findNode(NODE_T* currentNode, char* name)
{
if (currentNode == NULL) return NULL;
if (strcmp(currentNode->name, name) == 0) return currentNode;
for (int i = 0; i < currentNode->numChildren; i++)
{
NODE_T* found = findNode(currentNode->children[i], name);
if (found != NULL) return found;
}
return NULL;
}
/* Adds person with a given name and mother's name to the tree.
*/
NODE_T* addNonRoot(char* name, char* motherName)
{
if (root == NULL)
{
printf("Error: Root does not exist. Please add a root first.\n");
return NULL;
}
NODE_T* motherNode = findNode(root, motherName);
if (motherNode == NULL)
{
printf("Unsuccessful\n");
return NULL;
}
if (motherNode->numChildren == MAX_CHILDREN)
{
printf("Unsuccessful\n");
return NULL;
}
NODE_T* newNode = createNode(name);
newNode->parent = motherNode;
motherNode->children[motherNode->numChildren++] = newNode;
return newNode;
}
/* DFS function
*/
void dfsPrintDescendants(NODE_T* node)
{
for (int i = 0; i < node->numChildren; i++)
{
printf("%s ", node->children[i]->name);
dfsPrintDescendants(node->children[i]);
}
}
/* Prints the descendants of a given node.
*/
void printDescendants(char* name)
{
NODE_T* node = findNode(root, name);
if (node == NULL || node->numChildren == 0)
{
printf("Not Found\n");
return;
}
dfsPrintDescendants(node);
printf("\n");
}
/* DFS function to find the maximum chain
*/
void dfsFindMaxChain(
NODE_T* node,
NODE_T* path[],
int depth,
NODE_T* maxPath[],
int* maxDepth
)
{
path[depth] = node;
if (node->numChildren == 0)
{
if (depth + 1 > *maxDepth)
{
*maxDepth = depth + 1;
for (int i = 0; i <= depth; i++)
{
maxPath[i] = path[i];
}
}
}
else
{
for (int i = 0; i < node->numChildren; i++)
{
dfsFindMaxChain(
node->children[i],
path,
depth + 1,
maxPath,
maxDepth
);
}
}
}
// Function to print the longest chain
void printLongestChain()
{
if (root == NULL)
{
printf("Tree is empty\n");
return;
}
NODE_T* path[MAX_PATH_LENGTH];
NODE_T* maxPath[MAX_PATH_LENGTH];
int maxDepth = 0;
dfsFindMaxChain(root, path, 0, maxPath, &maxDepth);
for (int i = 0; i < maxDepth; i++)
{
printf("%s ", maxPath[i]->name);
}
printf("\n");
}
int main()
{
char input[64];
char name[MAX_NAME_LENGTH];
char motherName[MAX_NAME_LENGTH];
int numOperations;
scanf("%d", &numOperations);
scanf("%s", name);
addRoot(name);
for (int i = 1; i < numOperations; i++)
{
scanf("%s", input);
if (strcmp(input, "Add") == 0)
{
scanf("%s %s", name, motherName);
addNonRoot(name, motherName);
}
else if (strcmp(input, "Descendant") == 0)
{
scanf("%s", name);
printDescendants(name);
}
else if (strcmp(input, "Max") == 0)
{
printLongestChain();
}
}
return 0;
}