/* tree.h -- binary search tree */
/* no duplicate items are allowed in this tree */
#ifndef _TREE_H_
#define _TREE_H_
#include <stdbool.h>
/* redefine Item as appropriate */
#define SLEN 20
#define MAXITEMS 10000
typedef struct item
{
char name[SLEN];
int times;
} Item;
typedef struct trnode
{
Item item;
struct trnode * left; /* pointer to right branch */
struct trnode * right; /* pointer to left branch */
} Trnode;
typedef struct tree
{
Trnode * root; /* pointer to root of tree */
int size; /* number of items in tree */
} Tree;
void ShowItemTimes(const Item * pi, const Tree * ptree);
/* function prototypes */
/* operation: initialize a tree to empty */
/* preconditions: ptree points to a tree */
/* postconditions: the tree is initialized to empty */
void InitializeTree(Tree * ptree);
/* operation: determine if tree is empty */
/* preconditions: ptree points to a tree */
/* postconditions: function returns true if tree is */
/* empty and returns false otherwise */
bool TreeIsEmpty(const Tree * ptree);
/* operation: determine if tree is full */
/* preconditions: ptree points to a tree */
/* postconditions: function returns true if tree is */
/* full and returns false otherwise */
bool TreeIsFull(const Tree * ptree);
/* operation: determine number of items in tree */
/* preconditions: ptree points to a tree */
/* postconditions: function returns number of items in */
/* tree */
int TreeItemCount(const Tree * ptree);
/* operation: add an item to a tree */
/* preconditions: pi is address of item to be added */
/* ptree points to an initialized tree */
/* postconditions: if possible, function adds item to */
/* tree and returns true; otherwise, */
/* the function returns false */
bool AddItem(const Item * pi, Tree * ptree);
/* operation: find an item in a tree */
/* preconditions: pi points to an item */
/* ptree points to an initialized tree */
/* postconditions: function returns true if item is in */
/* tree and returns false otherwise */
bool InTree(const Item * pi, const Tree * ptree);
/* operation: delete an item from a tree */
/* preconditions: pi is address of item to be deleted */
/* ptree points to an initialized tree */
/* postconditions: if possible, function deletes item */
/* from tree and returns true; */
/* otherwise the function returns false*/
bool DeleteItem(const Item * pi, Tree * ptree);
/* operation: apply a function to each item in */
/* the tree */
/* preconditions: ptree points to a tree */
/* pfun points to a function that takes*/
/* an Item argument and has no return */
/* value */
/* postcondition: the function pointed to by pfun is */
/* executed once for each item in tree */
void Traverse (const Tree * ptree, void (* pfun)(Item item));
/* operation: delete everything from a tree */
/* preconditions: ptree points to an initialized tree */
/* postconditions: tree is empty */
void DeleteAll(Tree * ptree);
#endif
/* tree.c -- tree support functions */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
/* local data type */
typedef struct pair {
Trnode * parent;
Trnode * child;
} Pair;
/* protototypes for local functions */
static Trnode * MakeNode(const Item * pi);
static bool ToLeft(const Item * i1, const Item * i2);
static bool ToRight(const Item * i1, const Item * i2);
static void AddNode (Trnode * new_node, Trnode * root);
static void InOrder(const Trnode * root, void (* pfun)(Item item));
static Pair SeekItem(const Item * pi, const Tree * ptree);
static void DeleteNode(Trnode **ptr);
static void DeleteAllNodes(Trnode * ptr);
/* function definitions */
void InitializeTree(Tree * ptree)
{
ptree->root = NULL;
ptree->size = 0;
}
bool TreeIsEmpty(const Tree * ptree)
{
if (ptree->root == NULL)
return true;
else
return false;
}
bool TreeIsFull(const Tree * ptree)
{
if (ptree->size == MAXITEMS)
return true;
else
return false;
}
int TreeItemCount(const Tree * ptree)
{
return ptree->size;
}
bool AddItem(const Item * pi, Tree * ptree)
{
Trnode * new_node;
Pair found_pair;
if (TreeIsFull(ptree))
{
fprintf(stderr,"Tree is full\n");
return false; /* early return */
}
if (SeekItem(pi, ptree).child != NULL)
{
fprintf(stderr, "Attempted to add duplicate item\n");
found_pair=SeekItem(pi, ptree);
found_pair.child->item.times++;
return false; /* early return */
}
new_node = MakeNode(pi); /* points to new node */
if (new_node == NULL)
{
fprintf(stderr, "Couldn't create node\n");
return false; /* early return */
}
/* succeeded in creating a new node */
ptree->size++;
if (ptree->root == NULL) /* case 1: tree is empty */
ptree->root = new_node; /* new node is tree root */
else /* case 2: not empty */
AddNode(new_node,ptree->root); /* add node to tree */
return true; /* successful return */
}
void ShowItemTimes(const Item * pi, const Tree * ptree)
{
if (InTree(pi, ptree))
{
Trnode *foundNode = SeekItem(pi, ptree).child;
printf("%s has %d times\n", pi->name, foundNode->item.times);
}
else
{
printf("%s is not in the tree\n", pi->name);
}
}
bool InTree(const Item * pi, const Tree * ptree)
{
return (SeekItem(pi, ptree).child == NULL) ? false : true;
}
bool DeleteItem(const Item * pi, Tree * ptree)
{
Pair look;
look = SeekItem(pi, ptree);
if (look.child == NULL)
return false;
if (look.parent == NULL) /* delete root item */
DeleteNode(&ptree->root);
else if (look.parent->left == look.child)
DeleteNode(&look.parent->left);
else
DeleteNode(&look.parent->right);
ptree->size--;
return true;
}
void Traverse (const Tree * ptree, void (* pfun)(Item item))
{
if (ptree != NULL)
InOrder(ptree->root, pfun);
}
void DeleteAll(Tree * ptree)
{
if (ptree != NULL)
DeleteAllNodes(ptree->root);
ptree->root = NULL;
ptree->size = 0;
}
/* local functions */
static void InOrder(const Trnode * root, void (* pfun)(Item item))
{
if (root != NULL)
{
InOrder(root->left, pfun);
(*pfun)(root->item);
InOrder(root->right, pfun);
}
}
static void DeleteAllNodes(Trnode * root)
{
Trnode * pright;
if (root != NULL)
{
pright = root->right;
DeleteAllNodes(root->left);
free(root);
DeleteAllNodes(pright);
}
}
static void AddNode (Trnode * new_node, Trnode * root)
{
if (ToLeft(&new_node->item, &root->item))
{
if (root->left == NULL) /* empty subtree */
root->left = new_node; /* so add node here */
else
AddNode(new_node, root->left);/* else process subtree*/
}
else if (ToRight(&new_node->item, &root->item))
{
if (root->right == NULL)
root->right = new_node;
else
AddNode(new_node, root->right);
}
else /* should be no duplicates */
{
fprintf(stderr,"location error in AddNode()\n");
exit(1);
}
}
static bool ToLeft(const Item * i1, const Item * i2)
{
int comp1;
if ((comp1 = strcmp(i1->name, i2->name)) < 0)
return true;
else
return false;
}
static bool ToRight(const Item * i1, const Item * i2)
{
int comp1;
if ((comp1 = strcmp(i1->name, i2->name)) > 0)
return true;
else
return false;
}
static Trnode * MakeNode(const Item * pi)
{
Trnode * new_node;
new_node = (Trnode *) malloc(sizeof(Trnode));
if (new_node != NULL)
{
new_node->item = *pi;
new_node->left = NULL;
new_node->right = NULL;
}
return new_node;
}
static Pair SeekItem(const Item * pi, const Tree * ptree)
{
Pair look;
look.parent = NULL;
look.child = ptree->root;
if (look.child == NULL)
return look; /* early return */
while (look.child != NULL)
{
if (ToLeft(pi, &(look.child->item)))
{
look.parent = look.child;
look.child = look.child->left;
}
else if (ToRight(pi, &(look.child->item)))
{
look.parent = look.child;
look.child = look.child->right;
}
else /* must be same if not to left or right */
break; /* look.child is address of node with item */
}
return look; /* successful return */
}
static void DeleteNode(Trnode **ptr)
/* ptr is address of parent member pointing to target node */
{
Trnode * temp;
if ( (*ptr)->left == NULL)
{
temp = *ptr;
*ptr = (*ptr)->right;
free(temp);
}
else if ( (*ptr)->right == NULL)
{
temp = *ptr;
*ptr = (*ptr)->left;
free(temp);
}
else /* deleted node has two children */
{
/* find where to reattach right subtree */
for (temp = (*ptr)->left; temp->right != NULL;
temp = temp->right)
continue;
temp->right = (*ptr)->right;
temp = *ptr;
*ptr =(*ptr)->left;
free(temp);
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "tree.h"
// 17.12-7.txt
char menu(void);
void add(Tree * pt,Item temp);
void drop(Tree * pt,Item temp);
void show(const Tree * pt);
void find(const Tree * pt);
void printitem(Item item);
char * s_gets(char * st, int n);
Item Initializeitem(Item temp);
int main()
{
Tree strings;
InitializeTree(&strings);
int ch,i=0,j=0;
FILE *fp;
char file_name[SLEN]="17.12-7.txt";
Item temp;
temp.times=1;
int in_word=0;
if ((fp = fopen(file_name, "r")) == NULL)
{
printf("Can't open %s\n", file_name);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF)
{
printf("%d,",j); //观察循环过程
printf("%c,\n",ch); //观察循环过程
if(isalpha(ch))
{
temp.name[j]=ch;
in_word=1;
}
else if(in_word&&isalpha(ch)==0)
{
temp.name[j]='\0';
temp.times=1;
in_word=0;
add(&strings,temp);
temp=Initializeitem(temp);
j=0;
continue;//很重要`跳过后面的j++
}
else
{
in_word=0;
j=0;
}
j++;
}
fclose(fp);
char choice;
while ((choice = menu()) != 'c')
{
switch (choice)
{
case 'a' : show(&strings);
break;
case 'b' : find(&strings);
break;
default : puts("Switching error");
}
}
DeleteAll(&strings);
puts("Bye.");
return 0;
}
char menu(void)
{
int ch;
puts("a) list words and times\tb) find your word\n");
puts("c) quit:");
while ((ch = getchar()) != EOF)
{
while (getchar() != '\n') /* discard rest of line */
continue;
ch = tolower(ch);
if (strchr("abc",ch) == NULL)
puts("Please enter an a, b, c:");
else
break;
}
if (ch == EOF) /* make EOF cause program to quit */
ch = 'c';
return ch;
}
void add(Tree * pt,Item temp)
{
if (TreeIsFull(pt))
puts("No room in the club!");
else
{
AddItem(&temp, pt);
}
}
void show(const Tree * pt)
{
if (TreeIsEmpty(pt))
puts("No entries!");
else
Traverse(pt, printitem);
}
void printitem(Item item)
{
printf("word: %-19s times: %d\n", item.name,item.times);
}
void find(const Tree * pt)
{
Item temp;
if (TreeIsEmpty(pt))
{
puts("No entries!");
return; /* quit function if tree is empty */
}
puts("Please enter name of pet you wish to find:");
s_gets(temp.name, SLEN);
if (InTree(&temp, pt))
{
ShowItemTimes(&temp, pt);
}
else
printf("is not a member.\n");
}
void drop(Tree * pt,Item temp)
{
if (TreeIsEmpty(pt))
{
puts("No entries!");
return; /* quit function if tree is empty */
}
printf("%s ", temp.name);
if (DeleteItem(&temp, pt))
printf("is dropped from the club.\n");
else
printf("is not a member.\n");
}
char * s_gets(char * st, int n)
{
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
find = strchr(st, '\n'); // look for newline
if (find) // if the address is not NULL,
*find = '\0'; // place a null character there
else
while (getchar() != '\n')
continue; // dispose of rest of line
}
return ret_val;
}
Item Initializeitem(Item temp)
{
for(int i=0;i<SLEN;i++)
temp.name[i]='\0';
temp.times=0;
return temp;
}