/*
* CIS 610, Assignment 3
* Author: Dmitri Tikhonov
* Date: March 4, 2006
*
* Simple BST implementation.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LINESIZE 128
struct node {
int value;
struct node *parent;
struct node *left;
struct node *right;
};
typedef struct node node_t;
node_t *
new_node (int value)
{
node_t *node = malloc(sizeof(node_t));
node->parent = node->left = node->right = NULL;
node->value = value;
return node;
}
#define destroy_node(x) free(x)
node_t *
insert_node (node_t *root, node_t *node)
{
if (node->value > root->value) {
if (root->right) {
return insert_node(root->right, node);
} else {
node->parent = root;
return root->right = node;
}
} else if (node->value < root->value) {
if (root->left) {
return insert_node(root->left, node);
} else {
node->parent = root;
return root->left = node;
}
} else {
return NULL; /* Already exists */
}
}
node_t *
search_node (node_t *root, int value)
{
if (!root)
return NULL;
if (value > root->value)
return search_node(root->right, value);
else if (value < root->value)
return search_node(root->left, value);
else
return root;
}
void
print_nodes (node_t *root)
{
if (!root)
return;
printf("(");
print_nodes(root->left);
printf(" %d ", root->value);
print_nodes(root->right);
printf(")");
return;
}
node_t *
delete_node (node_t **root, int value)
{
node_t *target;
target = search_node(*root, value);
if (!target)
return NULL;
if (target->left && target->right) {
/* Possible improvement: randomly pick left or right */
node_t *node;
int value = target->value;
for (node = target->left; node->right; node = node->right)
;
target->value = node->value;
if (node == target->left)
target->left = node->left;
else
node->parent->right = node->left;
if (node->left)
node->left->parent = node->parent;
node->value = value;
return node;
} else if (target->left) {
if (target->parent) {
if (target->parent->left == target) {
target->parent->left = target->left;
target->left->parent = target->parent;
return target;
} else {
target->parent->right = target->left;
target->left->parent = target->parent;
return target;
}
} else {
*root = target->left;
target->left->parent = NULL;
return target;
}
} else if (target->right) {
if (target->parent) {
if (target->parent->left == target) {
target->parent->left = target->right;
target->right->parent = target->parent;
return target;
} else {
target->parent->right = target->right;
target->right->parent = target->parent;
return target;
}
} else {
*root = target->right;
target->right->parent = NULL;
return target;
}
} else {
if (target->parent) {
if (target->parent->left == target)
target->parent->left = NULL;
else
target->parent->right = NULL;
return target;
} else {
*root = NULL;
return target;
}
}
return target;
}
int
process_commands (node_t **root, FILE *stream)
{
#define WS " \t\n"
int retval = 0;
char line[LINESIZE];
while (fgets(line, sizeof(line), stream)) {
char *aux;
printf(line);
aux = strtok(line, WS);
if (!aux) /* Empty line */
continue;
switch (*aux) {
case 'i':
case 'I':
while (NULL != (aux = strtok(NULL, WS))) {
int value = atoi(aux);
node_t *node = new_node(value);
if (NULL == *root) {
*root = node;
printf("- Inserted %d\n", value);
} else {
if (insert_node(*root, node)) {
printf("- Inserted %d\n", value);
} else {
destroy_node(node);
printf("- Could not insert %d: already exists\n",
value);
}
}
}
break;
case 'p':
case 'P':
printf("-");
print_nodes(*root);
printf("\n");
break;
case 'd':
case 'D':
while (NULL != (aux = strtok(NULL, WS))) {
int value = atoi(aux);
node_t *node;
if (NULL != (node = delete_node(root, value))) {
printf("- Deleted node %d\n", value);
destroy_node(node);
} else {
printf("- Could not delete %d: not found\n", value);
}
}
break;
case 's':
case 'S':
while (NULL != (aux = strtok(NULL, WS))) {
int value = atoi(aux);
if (search_node(*root, value))
printf("- Found node %d\n", value);
else
printf("- Node %d not found\n", value);
}
break;
default:
printf("- Unknown command: %s\n", aux);
break;
}
}
if (!feof(stream)) {
fprintf(stderr, "Input line is too long. Aborting.\n");
return -1;
}
return retval;
}
void
_usage (const char *prog)
{
fprintf(stderr, "Usage: %s [-f file] [-h]\n", prog);
return;
}
int
main (int argc, char **argv)
{
int opt;
node_t *tree = NULL;
FILE *stream = stdin;
while (-1 != (opt = getopt(argc, argv, "hf:"))) {
switch (opt) {
case 'h':
_usage(*argv);
exit(0);
break;
case 'f':
if (strcmp(optarg, "-")) {
stream = fopen(optarg, "r");
if (!stream) {
perror("Coould not open file for reading");
exit(1);
}
}
break;
case '?':
_usage(*argv);
exit(2);
}
}
process_commands(&tree, stream);
exit(0);
}
syntax highlighted by Code2HTML, v. 0.9.1