| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 955 人关注过本帖
标题:求有调试能力的大神帮下忙,关于二叉树的程序...
取消只看楼主 加入收藏
那小扎
Rank: 1
来 自:长沙
等 级:新手上路
帖 子:21
专家分:9
注 册:2013-6-12
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:7 
求有调试能力的大神帮下忙,关于二叉树的程序...
这两天,我写了一个二叉树的实现代码,有结点插入和删除,结点遍历输出,返回结点数目等功能,但是写出来修改完错误,却达不到我的预想。还不是擅长调试 - -,求大神解决,可以的话加我QQ 871847544
在删除结点和遍历时都会产生崩溃,程序如下:
程序代码:
/*主函数  My_tree.c    */
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "tree.h"

 
enum allchoices {addone,deleteone,itemcount,search,showall,cleanall};              //提供全部的命令的集合
const char * choices[]={"addone","deleteone","itemcount","search","showall","cleanall"};       //为了使用上述命令创作的数组
 
#define LEN 15
void menu(void);                                        //主函数中需要调用的命令,见下
void AddOne (Tree *ptree);
void DeleteOne(Tree *ptree);
void ItemCount(const Tree *ptree);
void FindOne(const Tree *ptree);
void ShowAll(const Tree *ptree);
void CleanAll(Tree *ptree);
void PrintItem(Item item);

 
int main(void)
{
    Tree classmates;                                        // 构建数据结构的变量
    char yourchoice[LEN];
    enum allchoices  choice;
    bool the_order_iseffective=false;
    InitializeTree(&classmates);                            //初始化一棵树
 
     menu();
    while(strcmp(gets(yourchoice),"quit")!=0&&yourchoice[0]!='\0')               //当输入"quit"或者空行时退出循环
    {
        for(choice=addone;choice<=cleanall;choice++)                       //与可使用的命令集进行比较,
        {
            if(strcmp(yourchoice,choices[choice])==0)                 
            {
                the_order_iseffective=true;
                break;
            }
        }
        if(the_order_iseffective)                           //当输入某一命令式,实现二叉树的特定功能;
            switch (choice)
        {
            case (addone): AddOne(&classmates);                    // 在书中添加一个项目命令
            break;                  
            case (deleteone):DeleteOne(&classmates);                 //在树种删除一个项目命令;           
            break;
            case(itemcount):ItemCount(&classmates);                  //返回结点的数目命令
            break;
            case(search):FindOne(&classmates);                    //搜索某一特定项目
            break;
            case(showall):ShowAll(&classmates);            //遍历输出结点命令;
            break;
            case(cleanall):CleanAll(&classmates);                   //清空树的命令;
            break;

 
        }
        else
            printf("i don\'t know what the order mean!\n");
        the_order_iseffective=false;
        while(getchar()!='\n')
            continue;
        puts("next order\n");
         menu();

 
    }
    puts("good job\n");
    return 0;
}

 
void menu(void)
{
     puts("please chioce what do you want to to?\n");
     puts("enter \"addone\" to add a classmate.\n");
     puts("enter \"deleteone\" to delete a classmate\n");
     puts("enter \"itemcount\" to konw the number of your classmatas\n");
     puts("enter \"search\" to find your classmate\n");
     puts("enter\"showall\"to printf all of your classmates.\n");
     puts("enter \"cleanall\"to chean all items. \n");
     puts("enter \"quit\" to quit\n");
     return 0;
}

 
void AddOne (Tree *ptree)                      //添加一个项目的方法
{
    Item temp;
    if(TreeIsFull(ptree))
        puts("no room to accept a new one!\n");
    else
        {
        puts("please enter your classmate\'s name:\n");
        gets(temp.name);
        puts("please enter sex of your classmate:\n");
        gets(temp.sex);
        puts("please enter age of your classmate:\n");
        scanf("%d",&temp.age);
        AddItem(&temp,ptree);
        }

 

 
}

 
void DeleteOne(Tree *ptree)                    //删除一个项目的方法
{
   Item temp;

 
   if(TreeIsEmpty(ptree))
   {
       puts("no members to put out!\n");
       return;
    }

 
    puts("please enter name of classmate you want to delete:\n");
    gets(temp.name);
    if(DeleteItem(&temp,ptree))
        printf("sccessfully\n");
    else
        puts("is not a members\n");

 
}

 
void ItemCount(const Tree *ptree)                    //返回结点数目的方法
{
    unsigned int number;
    number=TreeItemCount(ptree);
    printf("there are %d  classmates\n",number);

 

 
}
void FindOne(const Tree *ptree)                     //寻找特定项目的方法
{
    Item temp;

 
    if(TreeIsEmpty(ptree))
    {
        puts("no information in the tree!");
        return;
    }
    puts("please enter name of classmate you want to find:\n");
    gets(temp.name);
    if(InTree(&temp,ptree))
        puts("is a member in the class!");
        else
        puts("is not a member");

 
}

 

 
void ShowAll(const Tree *ptree)                   //遍历输出所有结点的方法
{
    if(TreeIsEmpty(ptree))
    {
        puts("no information in the tree!\n");
        return;
    }
    else
        Traverse(ptree,PrintItem);

 
}

 
void CleanAll(Tree *ptree)                         // 清空树的方法
{
    DeleteAll(ptree);
    printf("just clean all\n");
}

 
void PrintItem(Item item)                         //输出项目的格式
{
   printf("name:%s,\tsex:%s,\tage:%d",item.name,item.sex,item.age);
}

/*头文件,  tree.h */
#ifndef _TREE_H_                         //头文件在这里
#define _TREE_H_
#include <stdbool.h>

 
#define SIZE 15
#define MAXSIZE 15

 
typedef struct item                             //构造存储所需项目的数据结构,这是简单的指人的数据结构,并使Item 这种通用方便的名称
{
    char name[SIZE];
    char sex[SIZE];
    int age;
} Item;

 
typedef struct node                        //二叉树中结点的数据结构,包含项目和指向左右结点的子树的指针
{
    Item item;
    struct node * left;
    struct node * right;
} Node;

 
typedef struct tree                       //构造一颗二叉树,包含跟结点和树中结点数目
{
    Node *root;
    unsigned int size;
} Tree;

 
typedef struct pair                      //构造一种数据结构,便于搜索二叉树中特定的项目,返回指向要搜索结点的指针和指向其父节点的指针,
{
    Node * parent;
    Node * child;
}Pair;

 
void InitializeTree(Tree *ptree);                   //二叉树的操作集
bool TreeIsEmpty(const Tree *ptree);
bool TreeIsFull(const Tree *ptree);
unsigned int TreeItemCount(const Tree*ptree);
bool AddItem(const Item *pitem,Tree *ptree);
bool InTree(const Item *pitem,const Tree *ptree);
bool DeleteItem(const Item *pitem,Tree *ptree);
void Traverse(const Tree *ptree,void(*pun)(Item item));
void DeleteAll(Tree *ptree);

 

 
#endif // _TREE_H_


/*实现头文件功能    tree.c   */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"

 
static Node * MakeNode(const Item *pitem);                                      //   实现头文件功能需要调用的静态函数!
static bool ToLeft(const Item *pitem1,const Item *pitem2);
static bool ToRight(const Item *pitem1,const Item *pitem2);
static void AddNode(Node * new_node,Node *root);
static void TraverseTree(const Node *root,void (*pfun)(Item item));
static Pair SeekItem(const Item *pitem,const Tree *ptree);
static void DeleteNode(Node **ptree);
static void DeleteAllNode(Node *root);

 

 
void InitializeTree(Tree *ptree)                         //树的初始化,根节点为空,结点数目为0
{
       ptree->root=NULL;
       ptree->size=0;
}

 

 bool TreeIsEmpty(const Tree *ptree)                    //判断树是否为空,如果是,返回tree
{
    if(ptree->root==NULL)
        return true;
    else
        return false;
}

 
bool TreeIsFull(const Tree *ptree)                        //判断树是否为满树,如果是,返回tree;
{
    if(ptree->size==MAXSIZE)
        return true;
    else
        return false;
}

 
unsigned int TreeItemCount(const Tree *ptree)                    //返回二叉树中结点数目
{
    return ptree->size;
}

 
bool AddItem(const Item *pitem,Tree *ptree)                             //在二叉树中添加一个结点
 {
     Node *new_node;
     if(SeekItem(pitem,ptree).child!=NULL)                               //判断要添加的结点是否已经存在在树中,
     {
         printf("the item is already exist.");
         return false;
     }
     new_node=MakeNode(pitem);                            //为新的结点分配空间,并创造新的结点
     if(new_node==NULL)
     {
         printf("FAIED TO CREAT A NODE!");
         return false;
     }
     ptree->size++;
     if(ptree->root==NULL)                                //如果树跟为空,则树根结点=新结点
        ptree->root=new_node;
     else
        AddNode(new_node,ptree->root);                     //如果树根不为空,则添加结点
 }

 

 bool InTree(const Item *pitem,const Tree *ptree)                   //判断树中是否有该项目      
 {
     return(SeekItem(pitem,ptree).child==NULL?false:true);

 }

 

 bool DeleteItem(const Item *pitem,Tree *ptree)                //删除树中某个结点
 {
     Pair temp;

 
     temp=SeekItem(pitem,ptree);
     if(temp.child==NULL)
        return false;
     else if(temp.parent==NULL)
        DeleteNode(&ptree->root);
     else
        DeleteNode(&temp.child);                
     ptree->size--;
     return true;

 

 }

 void Traverse(const Tree *ptree,void(*pfun)(Item item))                 //遍历树,调用函数输出结点中项目
 {
     if(ptree!=NULL)
        TraverseTree(ptree->root,pfun);

 }

 

 void DeleteAll(Tree *ptree)                                 //清空树,删除多有结点
 

 {
     if(ptree->root!=NULL)                                      //如果根节点不为空,则递归调用删除根节点
        DeleteAllNode(ptree->root);
     ptree->root=NULL;
     ptree->size=0;
}

 
static Node *MakeNode(const Item *pitem)                         //局部函数集合,可以当方法调用,创建新的结点,为其分配内存空间
{
    Node * new_node;
    new_node=(Node *)malloc(sizeof(Node));
    if(new_node!=NULL)
    {
        new_node->item=*pitem;
        new_node->left=NULL;
        new_node->right=NULL;
    }
    return new_node;
}

 
static bool ToLeft(const Item *pitem1,const Item *pitem2)                   //用于比较二叉树中项目该节点应该在左边?如果该,返回真,
{                                                                                //用C语言字符串的比较,
    int flag;
    if(flag=strcmp(pitem1->name,pitem2->name)<0)
        return true;
    else
        return false;
}
static bool ToRight (const Item *pitem1,const Item*pitem2)                 //同上,比较是否在右边
{
    int flag;
    if(flag=strcmp(pitem1->name,pitem2->name)<0)
        return true;
    else
        return false;
}

 
static void AddNode(Node *new_node,Node *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);

 
}

 
static void TraverseTree(const Node *root,void (*pfun)(Item item))                    //遍历二叉树的方法,并调用函数
{
    if(root!=NULL)
    {
        TraverseTree(root->left,pfun);
        (*pfun)(root->item);
        TraverseTree(root->right,pfun);
    }
    else
        printf("no member!");
}

 
static Pair SeekItem(const Item *pitem,const Tree *ptree)                       //返回二叉树中要搜索的结点
{
    Pair temp;
    temp.parent=NULL;
    temp.child=ptree->root;

 
  while(temp.child!=NULL)
  {
      if(ToLeft(pitem,&temp.child->item))
      {
       temp.parent=temp.child;
       temp.child=temp.child->left;

 
      }
      else if (ToRight(pitem,&temp.child->item))
      {
          temp.parent=temp.child;
          temp.child=temp.child->right;
      }
      else
        break;
    }
    return temp;
}

 
static void DeleteNode(Node **ptree)                                  //删除二叉树中的结点
{
    Node * temp;
    if((*ptree)->left=NULL)
    {
        temp=*ptree;
        *ptree=(*ptree)->right;
        free(temp);
    }
    else if ((*ptree)->right=NULL)
    {
        temp=*ptree;
        *ptree=(*ptree)->left;
        free(temp);
    }
    else
    {
     for(temp=(*ptree)->left;temp->right==NULL;temp=temp->right)
        break;
     temp->right=(*ptree)->right;
     temp=*ptree;
     (*ptree)=(*ptree)->left;
          free(temp);
    }
}

 
static void DeleteAllNode(Node * root)                       //清空树所需要的删除全部结点
{
   Node *pright;
   if (root!=NULL)
   {
       pright=root->right;
       DeleteAllNode(root->left);
       free(root);
       DeleteAllNode(pright);
   }
}


[ 本帖最后由 那小扎 于 2013-6-12 18:15 编辑 ]
搜索更多相关主题的帖子: 能力 二叉树 
2013-06-12 09:27
那小扎
Rank: 1
来 自:长沙
等 级:新手上路
帖 子:21
专家分:9
注 册:2013-6-12
收藏
得分:0 
论坛的吧主或者大神纳 - -,小弟实在是求帮忙呀

    将编写玩具式程序的趣味性与为实现功能而进行开发的艰难性区分开来!!
2013-06-12 11:56
那小扎
Rank: 1
来 自:长沙
等 级:新手上路
帖 子:21
专家分:9
注 册:2013-6-12
收藏
得分:0 
回复 3楼 蚕头燕尾
有头文件呀,专门注明了,
#ifndef _TREE_H_
至于你说的确实是C的头文件,C99才开始引用的应该是,

[ 本帖最后由 那小扎 于 2013-6-12 17:30 编辑 ]

    将编写玩具式程序的趣味性与为实现功能而进行开发的艰难性区分开来!!
2013-06-12 17:29
那小扎
Rank: 1
来 自:长沙
等 级:新手上路
帖 子:21
专家分:9
注 册:2013-6-12
收藏
得分:0 
回复 4楼 神经不正常
这不是很复杂呀,只是二叉树的实现,以及对其结点的一些操作

    将编写玩具式程序的趣味性与为实现功能而进行开发的艰难性区分开来!!
2013-06-12 17:29
那小扎
Rank: 1
来 自:长沙
等 级:新手上路
帖 子:21
专家分:9
注 册:2013-6-12
收藏
得分:0 
谁可以把大版主请进来, - -,求大神支援...

    将编写玩具式程序的趣味性与为实现功能而进行开发的艰难性区分开来!!
2013-06-12 17:35
那小扎
Rank: 1
来 自:长沙
等 级:新手上路
帖 子:21
专家分:9
注 册:2013-6-12
收藏
得分:0 
回复 4楼 神经不正常
不好意思,疏忽了,我补充了很多注释,方便你们阅读,可以更好的帮我调试程序

    将编写玩具式程序的趣味性与为实现功能而进行开发的艰难性区分开来!!
2013-06-12 18:03
那小扎
Rank: 1
来 自:长沙
等 级:新手上路
帖 子:21
专家分:9
注 册:2013-6-12
收藏
得分:0 
- -,求论坛大神现身

    将编写玩具式程序的趣味性与为实现功能而进行开发的艰难性区分开来!!
2013-06-13 12:16
那小扎
Rank: 1
来 自:长沙
等 级:新手上路
帖 子:21
专家分:9
注 册:2013-6-12
收藏
得分:0 
回复 13楼 蚕头燕尾
我使用的编译器是GCC,基本支持C99吧,至于这段代码在我的电脑里是不显示错误的,只是在运行时进行某一些步奏会直接崩溃;例如addone后deleteone 会直接崩溃,遍历也会,可能是存在一些逻辑上的错误 - -,反正我的编译器是发现不了,只能靠调试了,还有你提出的关于枚举型的问题,下面这段代码在我的编译器里是可以正常运行的;
程序代码:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

enum allchoices {addone,deleteone,itemcount,search,showall,cleanall};
const char * choices[]={"addone","deleteone","itemcount","search","showall","cleanall"};

#define LEN 15
void menu(void);
void AddOne (void);
void DeleteOne(void);
void Itemcount(void);
void FindOne(void);
void ShowAll(void);
void CleanAll(void);

int main(void)
{
    char yourchoice[LEN];
    enum allchoices  choice;
    bool the_order_iseffective=false;

     menu();
    while(strcmp(gets(yourchoice),"quit")!=0&&yourchoice[0]!='\0')
    {
        for(choice=addone;choice<=cleanall;choice++)
        {
            if(strcmp(yourchoice,choices[choice])==0)
            {
                the_order_iseffective=true;
                break;
            }
        }
        if(the_order_iseffective)
            switch (choice)
        {
            case (addone): AddOne();
            break;
            case (deleteone):DeleteOne();
            break;
            case(itemcount):ItemCount();
            break;
            case(search):FindOne();
            break;
            case(showall):ShowAll();
            break;
            case(cleanall):CleanAll();
            break;

        }
        else
            printf("i don\'t know what the order mean!\n");
        the_order_iseffective=false;
        puts("next order\n");
         menu();

    }
    puts("good job\n");
    return 0;
}

void menu(void)
{
     puts("please chioce what do you want to to?\n");
     puts("enter \"addone\" to add a classmate.\n");
     puts("enter \"deleteone\" to delete a classmate\n");
     puts("enter \"itemcount\" to konw the number of your classmatas\n");
     puts("enter \"search\" to find your classmate\n");
     puts("enter\"showall\"to printf all of your classmates.\n");
     puts("enter \"cleanall\"to chean all items. \n");
     puts("enter \"quit\" to quit\n");
     return 0;
}

void AddOne (void)
{
    printf("just like this.\n");
}

void DeleteOne(void)
{
    printf("just like\n");
}

void Itemcount(void)
{
    printf("just like2\n");
}
void FindOne(void)
{
    printf("just like 3\n");
}

void ShowAll(void)
{
    printf("just like 4\n");
}

void CleanAll(void)
{
    printf("just clean all\n");
}

所以这方面应该不会出现问题;你的编译器可能不支持C99,不过添加下面代码应该可以通过编译的,
#define bool int
#define true 1
#define false 0
删除掉#include<stdbool.h>

[ 本帖最后由 那小扎 于 2013-6-14 12:33 编辑 ]

    将编写玩具式程序的趣味性与为实现功能而进行开发的艰难性区分开来!!
2013-06-14 12:28
快速回复:求有调试能力的大神帮下忙,关于二叉树的程序...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.044630 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved