输入一组关键值,建立相应的二叉排序树,完成结点的查找和删除操作。
(1)可以实现删除根结点、叶子结点以及其它任意结点的功能。
(2)可随时显示操作的结果。#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#define NULL 0
typedef struct node                           //定义二叉排序树的结点
{
 int key;                                     //数据域
 struct node *lchild, *rchild;                //左、右孩子指针
}*bitree;                                      //二叉排序树的结点结构bitree BSTInsert(bitree t,bitree s)      //二叉排序树的插入的非递归算法

 bitree p,q;
 if(t==NULL)                              //二叉排序树为空的情况
 {
  t=s;
  return(t);
 }
 p=t;                                     //从根结点开始
 while(p!=NULL)
 {
  q=p;
  if(s->key==p->key)                      //查找到返回
    return(t);
  else                                    //继续搜索
  {
   if(s->key<p->key)                      //搜索左子树
     p=p->lchild;
   else                                   //搜索右子树
     p=p->rchild;
  }
 }
 if(s->key>q->key)
  q->rchild=s;
 else
  q->lchild=s;
 return(t);
}void BSTCreat(bitree &t)                  //建立一个有n个节点的二叉排序树算法            
{
 bitree s;
 int key;                               //关键字
 int i,n;
 t=NULL;
 cout<<"请输入结点数目:"<<endl;
 cin>>n;
 cout<<"请输入结点的值:"<<endl;
 for(i=1;i<=n;i++)
 {
  cin>>key;                             //假定关键字为整型
  s=(bitree)malloc(sizeof(bitree));    //生成一个新结点
  s->lchild=NULL;
  s->rchild=NULL;
  s->key=key;                            //调用插入算法将s所指结点插入二叉排序树t中
  t=BSTInsert(t,s);
 }
}int BSTSearch(bitree t,int key)               //二叉排序树查找的非递归算法
{
 bitree p;
 p=t;
 while(p!=NULL && p->key!=key)
 {
  if(key<p->key)
    p=p->lchild;                           //沿左子树查找
  else
    p=p->rchild;                           //沿右子树查找
 }
 if(p!=NULL)
    return(1);
 else
    return(0);
}void BSTDelete(bitree t,int key)        //二叉排序树中删除一个结点的算法
{
 bitree p,q,s;
 p=t;
 q=NULL;                                 //p指向待比较的结点,q指向p的前驱结点
 while(p!=NULL && p->key!=key)           //查找值域为key的结点
  if(key<p->key)
  {
   q=p;
   p=p->lchild;
  }
  else
  {
   q=p;
   p=p->rchild;
  }
 if(p==NULL)
  cout<<"该结点不存在"<<endl;
 else if(p->lchild==NULL)               //被删结点无左子树
 {
  if(q==NULL) t=p->rchild;              //考虑p为根结点的情况
  else if(q->lchild==p)
   q->lchild=p->rchild;                 //p为双亲的左子树
   else 
     q->rchild=p->rchild;               //p为双亲的右子树
  free(p);                              //释放p结点
 }
 else if(p->rchild==NULL)               //被删除结点无右子树
 {
  if(q==NULL)
   t=p->rchild;                         //考虑p为根结点的情况
  else if(q->lchild==p)
   q->lchild=p->rchild;                 //p为双亲的左子树                
       else
         q->rchild=p->rchild;           //p为双亲的右子树         
  free(p);                              //释放P结点                             
 }
 else                                   //被删除结点同时有左子树和右子树
 {                                      //查找被删除结点的左子树中的最右结点,即刚好小于key的结点,也即是p的直接前驱
  s=p->lchild;
  while(s->rchild!=NULL)                //寻找p的直接前驱s
    s=s->rchild;
    s->rchild=p->rchild;                //被删除结点的右子树作为直接前驱s的右子树
                                        //被删除结点的左子树根代替被删结点
    if(q==NULL)                         //被删结点是根结点
     t=p->lchild;
    else if(q->lchild==p)               //p为其双亲结点左子树
     q->lchild=p->lchild;
         else                           //p为双亲的右子树
           q->rchild=p->lchild;
    free(p);
 }
}void BSTPrint(bitree t)
{
 if(t!=NULL)
 {
  BSTPrint(t->lchild);
  printf("%d\t",t->key);
  BSTPrint(t->rchild);
 }
}void main()
{
 int k;
 bitree p,s1;
 int key1;
 cout<<"建立二叉排序树:"<<endl;
 p=NULL;
 s1=NULL;
 BSTCreat(p);
 cout<<"请输入需要查找关键字:"<<endl;
 cin>>key1;
 k=BSTSearch(p,key1);
 if(!k)
  cout<<"该结点不存在"<<endl;
 else
  cout<<"该结点存在,已找到"<<endl;
 cout<<"请输入要删除的结点关键字的值"<<endl;
 cin>>key1;
 BSTDelete(p,key1);
 cout<<"删除结点后的二叉排序树的中序遍历为:"<<endl;
 BSTPrint(p);}程序编译和连接时均未出错,但运行生成的exe做删除结点操作时出错。请各位大虾指点!

解决方案 »

  1.   

    三个地方要注意:
    1. s=(bitree)malloc(sizeof(bitree));    //生成一个新结点
    这里的sizeof(bitree)取的是指针长度4,要换成sizeof(node);
    2.free(p);之后要p=NULL,否则成了野指针
    3.void BSTDelete(bitree t,int key);原型应为void BSTDelete(bitree *t,int key);
    也就是传二级指针,才能准确回传指针值
    修改过的代码如下:
    #include <iostream.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define NULL 0
    typedef struct node                           //定义二叉排序树的结点
    {
    int key;                                     //数据域
    struct node *lchild, *rchild;                //左、右孩子指针
    }*bitree;                                      //二叉排序树的结点结构bitree BSTInsert(bitree t,bitree s)      //二叉排序树的插入的非递归算法

    bitree p,q;
    if(t==NULL)                              //二叉排序树为空的情况
    {
    t=s;
    return(t);
    }
    p=t;                                     //从根结点开始
    while(p!=NULL)
    {
    q=p;
    if(s->key==p->key)                      //查找到返回
    return(t);
    else                                    //继续搜索
    {
    if(s->key<p->key)                      //搜索左子树
    p=p->lchild;
    else                                   //搜索右子树
    p=p->rchild;
    }
    }
    if(s->key>q->key)
    q->rchild=s;
    else
    q->lchild=s;
    return(t);
    }void BSTCreat(bitree &t)                  //建立一个有n个节点的二叉排序树算法            
    {
    bitree s;
    int key;                               //关键字
    int i,n;
    t=NULL;
    cout<<"请输入结点数目:"<<endl;
    cin>>n;
    cout<<"请输入结点的值:"<<endl;
    for(i=1;i<=n;i++)
    {
    cin>>key;                             //假定关键字为整型
    s=(bitree)malloc(sizeof(node));    //生成一个新结点
    s->lchild=NULL;
    s->rchild=NULL;
    s->key=key;                            //调用插入算法将s所指结点插入二叉排序树t中
    t=BSTInsert(t,s);
    }
    }int BSTSearch(bitree t,int key)               //二叉排序树查找的非递归算法
    {
    bitree p;
    p=t;
    while(p!=NULL && p->key!=key)
    {
    if(key<p->key)
    p=p->lchild;                           //沿左子树查找
    else
    p=p->rchild;                           //沿右子树查找
    }
    if(p!=NULL)
    return(1);
    else
    return(0);
    }void BSTDelete(bitree *t,int key)        //二叉排序树中删除一个结点的算法
    {
    bitree p,q,s;
    p=*t;
    q=NULL;                                 //p指向待比较的结点,q指向p的前驱结点
    while(p!=NULL && p->key!=key)           //查找值域为key的结点
    {
    if(key<p->key)
    {
    q=p;
    p=p->lchild;
    }
    else
    {
    q=p;
    p=p->rchild;
    }
    }
    if(p==NULL)
    cout<<"该结点不存在"<<endl;
    else if(p->lchild==NULL)               //被删结点无左子树
    {
    if(q==NULL) *t=p->rchild;              //考虑p为根结点的情况
    else if(q->lchild==p)
    q->lchild=p->rchild;                 //p为双亲的左子树
    else 
    q->rchild=p->rchild;               //p为双亲的右子树
    free(p);                              //释放p结点
    p = NULL;
    }
    else if(p->rchild==NULL)               //被删除结点无右子树
    {
    if(q==NULL)
    *t=p->rchild;                         //考虑p为根结点的情况
    else if(q->lchild==p)
    q->lchild=p->rchild;                 //p为双亲的左子树                
    else
    q->rchild=p->rchild;           //p为双亲的右子树         
    free(p); //释放P结点 
    p = NULL;                            
    }
    else                                   //被删除结点同时有左子树和右子树
    {                                      //查找被删除结点的左子树中的最右结点,即刚好小于key的结点,也即是p的直接前驱
    s=p->lchild;
    while(s->rchild!=NULL)                //寻找p的直接前驱s
    s=s->rchild;
    s->rchild=p->rchild;                //被删除结点的右子树作为直接前驱s的右子树
    //被删除结点的左子树根代替被删结点
    if(q==NULL)                         //被删结点是根结点
    *t=p->lchild;
    else if(q->lchild==p)               //p为其双亲结点左子树
    q->lchild=p->lchild;
    else                           //p为双亲的右子树
    q->rchild=p->lchild;
    free(p);
    p = NULL;
    }
    }void BSTPrint(bitree t)
    {
    if(t!=NULL)
    {
    BSTPrint(t->lchild);
    printf("%d\t",t->key);
    BSTPrint(t->rchild);
    }
    }void main()
    {
    int k;
    bitree p,s1;
    int key1;
    cout<<"建立二叉排序树:"<<endl;
    p=NULL;
    s1=NULL;
    BSTCreat(p);
    cout<<"请输入需要查找关键字:"<<endl;
    cin>>key1;
    k=BSTSearch(p,key1);
    if(!k)
    cout<<"该结点不存在"<<endl;
    else
    cout<<"该结点存在,已找到"<<endl;
    cout<<"请输入要删除的结点关键字的值"<<endl;
    cin>>key1;
    BSTDelete(&p,key1);
    cout<<"删除结点后的二叉排序树的中序遍历为:"<<endl;
    BSTPrint(p);

    }