编程语言
首页 > 编程语言> > 基于二叉查找树的字母查找程序

基于二叉查找树的字母查找程序

作者:互联网

记录下之前写的一个文件字母查找程序

数据结构采用二叉查找树,操作对象是文本文档中用户输入的字母

可以添加删除查找字母

二叉查找树会自动排序每个对象,检索起来很方便。对象越多,相对于遍历比较的优势越大。但是如果树根root设置的不好,会导致树的一侧很多节点,另一侧节点很少。

主程序:

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "tree_17_7.h"

char * s_gets(char * st, int n);
void eatline(void);
void CountYourChar(Tree *pTree);
void PutInTree(FILE *fp,Tree *pTree);
void ShowAndCount(Tree *pTree);
void ShowCharInfo(Item item);
void AddChar(Tree *pTree,FILE *fp);

int main(void)
{
   Tree Tree,*pTree;
   pTree=&Tree;
   InitializeTree(pTree);

   FILE *fp;
   if((fp=fopen("Practice17_7.txt","at+"))==NULL)
   {
       puts("cannot open file");
       exit(EXIT_FAILURE);
   }
   PutInTree(fp,pTree);


   puts("Choose from the lists:");
   puts("a) add your char to tree and append to file");
   puts("s) show all the character and count the times they showing up");
   puts("f) enter a character and will count times this character shows up in this .txt");
   puts("q) quit");
   int8_t Choice;
   while((Choice = getchar())!=EOF && Choice != 'q')
   {
       eatline();
       switch(Choice)
       {
           case 'a':
                AddChar(pTree,fp);
               break;
           case 's':
                Traverse(pTree,ShowCharInfo);
               break;
           case 'f':
               CountYourChar(pTree);
               break;
           default:
               break;
       }
        puts("Choose from the lists:");
        puts("a) add your char to tree and append to file");
        puts("s) show all the character and count the times they showing up");
        puts("f) enter a character and will count times this character shows up in this .txt");
        puts("q) quit");
        eatline();
   }
    fclose(fp);

   return 0;
}

void AddChar(Tree *pTree,FILE *fp)
{
    Trnode * tempSeekResult;
    Item AddChar;
    AddChar.Char_Counter=0;
    puts("enter a character you want to add,enter 'q' to quit");
    while((AddChar.EnglishChar=getchar())!=EOF && AddChar.EnglishChar!='q')
    {
        eatline();
        if(TreeIsFull(pTree)==true)
        {
            puts("Tree is full now");
            break;
        }
        tempSeekResult = SeekItem(&AddChar, pTree).child;
        if(tempSeekResult != NULL)
        {
            tempSeekResult->item.Char_Counter++;
            puts("add item exist,update the numbers");
        }
        else
        {
            if(AddItem(&AddChar,pTree)==false)
            {
                puts("add item failed");
                break;
            }
            printf("Character %c has been successfully added\n",AddChar.EnglishChar);
        }
        fputc(AddChar.EnglishChar,fp);
        puts("enter a character you want to add,enter 'q' to quit");
    }

}

void ShowCharInfo(Item item)
{
    printf("%c %u\n",item.EnglishChar,item.Char_Counter);
}


void CountYourChar(Tree *pTree)
{
   Trnode * tempSeekResult;
   Item SearchChar;
   SearchChar.Char_Counter=0;
   puts("enter a character,enter 'q' to quit");
   while((SearchChar.EnglishChar=getchar())!=EOF && SearchChar.EnglishChar!='q')
   {
       eatline();
       tempSeekResult = SeekItem(&SearchChar, pTree).child;
        if(tempSeekResult == NULL)
        {
            puts("no such char");
            continue;
        }
        else
        {
            printf("there're %u %c\n",tempSeekResult->item.Char_Counter,tempSeekResult->item.EnglishChar);
        }
        puts("enter a character,enter 'q' to quit");

   }

}

void PutInTree(FILE *fp,Tree *pTree)
{
   Item Item,*MyItem;
   MyItem = &Item;
   while( ( (MyItem->EnglishChar) = getc(fp) ) != EOF)
   {
       MyItem->Char_Counter=1;
       if(TreeIsFull(pTree)==true)
       {
           puts("Tree is not big enough");
           break;
       }
       if(AddItem(MyItem,pTree)==false)
       {
           puts("add item failed");
           break;
       }
   }

}

void ShowAndCount(Tree *pTree)
{
   Tree *ForSearch;
   ForSearch=pTree;
   while(ForSearch->root->left!=NULL)
   {
       printf("%c %u\n",ForSearch->root->item.EnglishChar,ForSearch->root->item.Char_Counter);
       ForSearch->root=ForSearch->root->left;
   }
   ForSearch=pTree;
   while(ForSearch->root->right!=NULL)
   {
       printf("%c %u\n",(ForSearch->root->item).EnglishChar,(ForSearch->root->item).Char_Counter);
       ForSearch->root=ForSearch->root->right;
   }
}

void eatline(void)
{
   while (getchar() != '\n')
       continue;
}
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'); // 查找换行符
       if (find) // 如果地址不是 NULL,
           *find = '\0'; // 在此处放置一个空字符
       else
           while (getchar() != '\n')
               continue; // 处理输入行的剩余字符
   }
   return ret_val;
}

tree.c

/* tree.c -- 树的支持函数 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tree_17_7.h"


/* 局部函数的原型 */
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 void DeleteNode(Trnode **ptr);
static void DeleteAllNodes(Trnode * ptr);

/* 函数定义 */
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 tempSeekBack;
    if (TreeIsFull(ptree))
    {
        fprintf(stderr, "Tree is full\n");
        return false; /* 提前返回 */
    }
    tempSeekBack = SeekItem(pi, ptree);
    if (tempSeekBack.child != NULL)
    {
        tempSeekBack.child->item.Char_Counter++;
        return true; /* 提前返回 */
    }
    new_node = MakeNode(pi); /* 指向新节点 */
    if (new_node == NULL)
    {
        fprintf(stderr, "Couldn't create node\n");
        return false; /* 提前返回 */
    }
    /* 成功创建了一个新节点 */
    ptree->size++;
    if (ptree->root == NULL) /* 情况1:树为空 */
        ptree->root = new_node; /* 新节点为树的根节点 */
    else /* 情况2:树不为空 */
        AddNode(new_node, ptree->root);/* 在树中添加新节点 */
    return true; /* 成功返回 */
}

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) /* 删除根节点项 */
        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;
}

/* 局部函数 */
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) /* 空子树 */
            root->left = new_node; /* 把节点添加到此处 */
        else
            AddNode(new_node, root->left); /* 否则处理该子树 */
    }
    else if (ToRight(&new_node->item, &root->item))
    {
        if (root->right == NULL)
            root->right = new_node;
        else
            AddNode(new_node, root->right);
    }
    else /* 不允许有重复项 */
    {
        fprintf(stderr, "location error in AddNode()\n");
        exit(1);
    }
}

static bool ToLeft(const Item * i1, const Item * i2)
{
    if ( i1->EnglishChar < i2->EnglishChar)
        return true;
    else
        return false;
}

static bool ToRight(const Item * i1, const Item * i2)
{
    if ( i1->EnglishChar > i2->EnglishChar)
        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;
}

Pair SeekItem(const Item * pi, const Tree * ptree)
{
    Pair look;
    look.parent = NULL;
    look.child = ptree->root;
    if (look.child == NULL)
        return look; /* 提前返回 */
    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 /* 如果前两种情况都不满足,则必定是相等的情 况 */
            break; /* look.child 目标项的节点 */
    }
    return look; /* 成功返回 */
}

static void DeleteNode(Trnode **ptr) /* ptr 是指向目标节点的父节点指针成员的地址 */
{
    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 /* 被删除的节点有两个子节点 */
    {
        /* 找到重新连接右子树的位置 */
        for (temp = (*ptr)->left; temp->right != NULL;temp = temp->right)
            continue;
        temp->right = (*ptr)->right;
        temp = *ptr;
        *ptr = (*ptr)->left;
        free(temp);
    }
}

tree.h

/* tree.h -- 二叉查找数 */
#ifndef _TREE_17_7_H_
#define _TREE_17_7_H_

#include <stdbool.h>
#include <stdint.h>

/* 根据具体情况重新定义 Item */
typedef struct item {
    char EnglishChar;
    uint8_t Char_Counter;
}Item;

#define MAXITEMS 300

typedef struct trnode {
    Item item;
    struct trnode * left; /* 指向左分支的指针 */
    struct trnode * right; /* 指向右分支的指针 */
}Trnode;

typedef struct tree{
    Trnode * root;/* 指向根节点的指针 */
    int size; /* 树的项数 */
}Tree;

typedef struct pair{
    Trnode * parent;
    Trnode * child;
}Pair;


Pair SeekItem(const Item * pi, const Tree * ptree);


/* 函数原型 */
/* 操作: 把树初始化为空*/
/* 前提条件: ptree指向一个树 */
/* 后置条件: 树被初始化为空 */
void InitializeTree(Tree * ptree);\

/* 操作: 确定树是否为空 */
/* 前提条件: ptree指向一个树 */
/* 后置条件: 如果树为空,该函数返回true */
/* 否则,返回false */
bool TreeIsEmpty(const Tree * ptree);

/* 操作: 确定树是否已满 */
/* 前提条件: ptree指向一个树 */
/* 后置条件: 如果树已满,该函数返回true */
/* 否则,返回false */
bool TreeIsFull(const Tree * ptree);

/* 操作: 确定树的项数 */
/* 前提条件: ptree指向一个树 */
/* 后置条件: 返回树的项数 */
int TreeItemCount(const Tree * ptree);

/* 操作: 在树中添加一个项 */
/* 前提条件: pi是待添加项的地址 */
/* ptree指向一个已初始化的树 */
/* 后置条件: 如果可以添加,该函数将在树中添加一个项 */
/* 并返回true;否则,返回false */
bool AddItem(const Item * pi, Tree * ptree);

/* 操作: 在树中查找一个项 */
/* 前提条件: pi指向一个项 */
/* ptree指向一个已初始化的树 */
/* 后置条件: 如果在树中添加一个项,该函数返回true */
/* 否则,返回false */
bool InTree(const Item * pi, const Tree * ptree);

/* 操作: 从树中删除一个项 */
/* 前提条件: pi是删除项的地址 */
/* ptree指向一个已初始化的树 */
/* 后置条件: 如果从树中成功删除一个项,该函数返回true*/
/* 否则,返回false */
bool DeleteItem(const Item * pi, Tree * ptree);

/* 操作: 把函数应用于树中的每一项 */
/* 前提条件: ptree指向一个树 */
/* pfun指向一个函数, */
/* 该函数接受一个Item类型的参数,并无返回值*/
/* 后置条件: pfun指向的这个函数为树中的每一项执行一次*/
void Traverse(const Tree * ptree, void(*pfun)(Item item));

/* 操作: 删除树中的所有内容 */
/* 前提条件: ptree指向一个已初始化的树 */
/* 后置条件: 树为空 */
void DeleteAll(Tree * ptree);



#endif

 

标签:const,字母,Tree,二叉,Item,查找,void,root,ptree
来源: https://www.cnblogs.com/OmarDevonLittle/p/14912910.html