cmkl/spring-2025/sen-107/00030/orgchart.c

337 lines
8.4 KiB
C

/* orgChart
*
* Build a corporate hierarchy structure and sorted binary tree
*
* Created by Chavakorn Arunkunarax and Phasit Thanitkul, 2025-01-12
* Modified by Thanawin Pattanaphol, 2025-05-02
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
// Structure for an employee in the organization chart (general tree node)
typedef struct EmployeeNode
{
char name[32];
char employeeId[8];
char jobTitle[32];
struct EmployeeNode *supervisor;
struct EmployeeNode *firstChild;
struct EmployeeNode *nextSibling;
} EmployeeNode;
// Structure for a node in the sorted binary tree (index)
typedef struct IndexNode
{
char key[40]; // Concatenation of Name and EmployeeId
EmployeeNode *employeePtr;
struct IndexNode *left;
struct IndexNode *right;
} IndexNode;
EmployeeNode *root = NULL; // Root of the organization chart
IndexNode *indexRoot = NULL; // Root of the sorted binary tree
// Function to create a new employee node
EmployeeNode *createEmployeeNode(char *name, char *employeeId, char *jobTitle)
{
EmployeeNode *newNode = (EmployeeNode *)malloc(sizeof(EmployeeNode));
if (newNode == NULL)
{
perror("Failed to allocate memory for employee node");
exit(EXIT_FAILURE);
}
strcpy(newNode->name, name);
strcpy(newNode->employeeId, employeeId);
strcpy(newNode->jobTitle, jobTitle);
newNode->supervisor = NULL;
newNode->firstChild = NULL;
newNode->nextSibling = NULL;
return newNode;
}
// Function to create a new index node
IndexNode *createIndexNode(char *key, EmployeeNode *employeePtr)
{
IndexNode *newNode = (IndexNode *)malloc(sizeof(IndexNode));
if (newNode == NULL)
{
perror("Failed to allocate memory for index node");
exit(EXIT_FAILURE);
}
strcpy(newNode->key, key);
newNode->employeePtr = employeePtr;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// Function to insert into the sorted binary tree
IndexNode *insertIndexNode(IndexNode *root, char *key, EmployeeNode *employeePtr)
{
if (root == NULL)
{
return createIndexNode(key, employeePtr);
}
int cmp = strcmp(key, root->key);
if (cmp < 0)
{
root->left = insertIndexNode(root->left, key, employeePtr);
}
else if (cmp > 0)
{
root->right = insertIndexNode(root->right, key, employeePtr);
}
return root;
}
/* Adds employee to the corporate hierarchy structure and sorted binary tree
*/
void addEmployee(char *name, char *employeeId, char *jobTitle, char *supervisorName, char *supervisorId)
{
EmployeeNode *newEmployee = createEmployeeNode(name, employeeId, jobTitle);
char indexKey[40];
sprintf(indexKey, "%s%s", name, employeeId);
indexRoot = insertIndexNode(indexRoot, indexKey, newEmployee);
if (strcmp(supervisorName, "--") == 0)
{
if (root == NULL)
{
root = newEmployee;
}
else
{
fprintf(stderr, "Error: Multiple root employees found.\n");
// Handle this error as needed, maybe free the newEmployee
}
return;
}
EmployeeNode *supervisorNode = NULL;
// Search for the supervisor in the existing organization chart
// A simple linear search here. For larger organizations, a hash map would be more efficient.
// However, for this exercise, we'll keep it straightforward.
EmployeeNode *queue[100]; // Assuming a reasonable maximum number of employees for the queue
int head = 0, tail = 0;
if (root != NULL)
{
queue[tail++] = root;
}
while (head < tail)
{
EmployeeNode *current = queue[head++];
if (strcmp(current->name, supervisorName) == 0 && strcmp(current->employeeId, supervisorId) == 0)
{
supervisorNode = current;
break;
}
EmployeeNode *child = current->firstChild;
while (child != NULL)
{
queue[tail++] = child;
child = child->nextSibling;
}
}
if (supervisorNode != NULL)
{
newEmployee->supervisor = supervisorNode;
if (supervisorNode->firstChild == NULL)
{
supervisorNode->firstChild = newEmployee;
}
else
{
EmployeeNode *sibling = supervisorNode->firstChild;
while (sibling->nextSibling != NULL)
{
sibling = sibling->nextSibling;
}
sibling->nextSibling = newEmployee;
}
}
else
{
fprintf(stderr, "cannot_add %s %s\n", name, employeeId);
// Free the allocated memory for the employee node since it couldn't be added
free(newEmployee);
}
}
/* Prints the corporate hierarchy structure, pre-order
*/
void printCorporateHierarchyHelper(EmployeeNode *node, int level)
{
if (node == NULL)
{
return;
}
for (int i = 0; i < level; i++)
{
printf("...");
}
printf("%s %s %s\n", node->name, node->employeeId, node->jobTitle);
EmployeeNode *child = node->firstChild;
while (child != NULL)
{
printCorporateHierarchyHelper(child, level + 1);
child = child->nextSibling;
}
}
void printCorporateHierarchy()
{
printCorporateHierarchyHelper(root, 0);
}
// Helper function for in-order traversal of the index tree to print sorted list
void printSortedListHelper(IndexNode *root)
{
if (root == NULL)
{
return;
}
printSortedListHelper(root->left);
printf("%s %s %s\n", root->employeePtr->name, root->employeePtr->employeeId, root->employeePtr->jobTitle);
printSortedListHelper(root->right);
}
/* Prints the sorted list of employees
*/
void printSortedList()
{
printSortedListHelper(indexRoot);
}
/* Searches for an employee in the corporate hierarchy structure using the index tree
*/
void searchEmployee(char *name, char *employeeId)
{
char searchKey[40];
sprintf(searchKey, "%s%s", name, employeeId);
IndexNode *current = indexRoot;
while (current != NULL)
{
int cmp = strcmp(searchKey, current->key);
if (cmp < 0)
{
current = current->left;
}
else if (cmp > 0)
{
current = current->right;
}
else
{
EmployeeNode *employee = current->employeePtr;
printf("%s %s %s\n", employee->jobTitle, employee->supervisor ? employee->supervisor->name : "Top", employee->employeeId);
return;
}
}
printf("not_found\n");
}
// Helper function to free the organization chart tree
void freeOrganizationChart(EmployeeNode *node)
{
if (node == NULL)
{
return;
}
EmployeeNode *child = node->firstChild;
while (child != NULL)
{
EmployeeNode *next = child->nextSibling;
freeOrganizationChart(child);
child = next;
}
free(node);
}
// Helper function to free the index tree
void freeIndexTree(IndexNode *node)
{
if (node == NULL)
{
return;
}
freeIndexTree(node->left);
freeIndexTree(node->right);
free(node);
}
/* Free the contents of the datastructures used */
void freeAll()
{
freeOrganizationChart(root);
freeIndexTree(indexRoot);
root = NULL;
indexRoot = NULL;
}
int main()
{
char input[128];
char name[32];
char employeeId[8];
char jobTitle[32];
char supervisorName[32];
char supervisorId[8];
int numEmployees;
int numQuestions;
if (scanf("%d", &numEmployees) != 1)
{
fprintf(stderr, "Error reading number of employees.\n");
return 1;
}
if (scanf("%d", &numQuestions) != 1)
{
fprintf(stderr, "Error reading number of queries.\n");
return 1;
}
for (int i = 0; i < numEmployees; i++) {
if (scanf("%s %s %s %s %s", name, employeeId, jobTitle, supervisorName, supervisorId) != 5)
{
fprintf(stderr, "Error reading employee data.\n");
return 1;
}
addEmployee(name, employeeId, jobTitle, supervisorName, supervisorId);
}
printCorporateHierarchy();
for (int i = 0; i < numQuestions; i++)
{
if (scanf("%s %s", name, employeeId) != 2)
{
fprintf(stderr, "Error reading query.\n");
return 1;
}
searchEmployee(name, employeeId);
}
printSortedList();
freeAll();
return 0;
}