/* implementation of standard tree functions 
   file:  /home/walker/prog-mgmt/bst-proc.c 
*/

/* library for standard I/O */
#include <stdio.h>

/* tree header file */
#include "bst-proc.h"

void addName(struct node ** rootPtr, char * name) {
/* pre-condition:  rootPtr points to the pointer designating the root of a tree
  post-condition:  a name is read and inserted into the binary search tree
*/

  struct node * newNode = (struct node *)malloc(sizeof(struct node));
  struct node * treePtr;

  /* Create and initialize new node */
  strcpy (newNode->data, name);
  newNode->left = NULL;
  newNode->right = NULL;

  /* Insert new node into tree */
  /* Check if tree is empty */
  if (*rootPtr == NULL) {
    *rootPtr = newNode;
    return ;
  }

  /* For non-empty tree, search down to find the bottom of the tree */
  treePtr = *rootPtr;
  while (1) {
    /* Move down tree */
    if (strcmp (newNode->data, treePtr->data) < 0) {
      /* move left */
      if (treePtr->left) {
        treePtr = treePtr->left;
      } else {
        treePtr->left = newNode;
        return;
      }
    } else {
      /* move right */
      if (treePtr->right) {
        treePtr = treePtr->right;
      } else {
        treePtr->right = newNode;
        return;
      }
    }
  }
}

int countNodes (struct node * root) {
/* pre-condition:  root designates the root of the tree 
  post-condition:  the number of items on the list is counted and returned
                   the tree itself is unchanged
*/
  if (root) 
    return (1 + countNodes(root->left) + countNodes(root->right));
  else
    return 0;
}

void deleteName(struct node ** roottPtr, char * item) {
/* pre-condition:  rootPtr points to the pointer designating the root of a tree
  post-condition:  a name is read and
                   that name is deleted from the tree
*/
  printf ("Function deleteName is not implemented at present\n\n");

}

int find (struct node * root, char * item) {
/* pre-condition:  root designates the root of the tree 
                   item designates a data element (string)
  post-condition:  true is returned if the item is in the tree 
                   false is returned otherwise;
                   the tree itself is unchanged
*/
  if (root == NULL)
    return 0;
  if (strcmp (item, root->data) == 0)
    return 1;
  if (strcmp (item, root->data) < 0)
    return find(root->left, item);
  else return find(root->right, item);
}

void print(struct node * root, int level) {
/* pre-condition:  root designates the root of the tree
  post-condition:  The items on the list are printed using an in-order traversal
                   printed items are indented according to their level
                   the tree itself is unchanged
*/
  int i;
  if (root) {
    print (root->left, level+1);
    for (i = 0; i < level; i++) /* indent based on level of node */
      printf ("   ");
    printf ("%s\n", root->data);
    print (root->right, level+1);
  }
}

void printLeaves (struct node * root) {
/* pre-condition:  root designates the root of the tree
  post-condition:  the leaves on the tree are printed; 
                   the tree itself is unchanged
*/
  if (root) {
    if ((!(root->left))&&(!(root->right)))
      printf ("%s\n", root->data);
    else {
      printLeaves (root->left);
      printLeaves (root->right);
    }
  }
}
