227 lines
4.1 KiB
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;
|
|
}
|