337 lines
8.4 KiB
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;
|
|
} |