检索树

//检索树的构造、查找、插入、删除等综合程序
//其中,插入函数是非递归的
//检索树的构造、查找、插入、删除等综合程序
//其中,插入函数是非递归的
#include  <stdio.h> 
#include  <ctype.h>
#include  <malloc.h>  //包含动态存储分配函数malloc和free等
#include  <stdlib.h> //异常终止函数exit所在的库文件
#define  M   100  //结点个数的最大值
#define  ZERO  0 //定义空结点值
#define  SUCC  1  //删除成功的返回值
#define  DEFT  0   //定义删除失败的返回值
#define  MIN   -1  //定义无穷小元素值
#define  MAX  2001  //定义无穷大元素值

typedef  int  valuetype;  //假定值类型是int
typedef   struct  Bnode   //定义二叉树结点类型Bnode
  { valuetype data;   //值域
    int  layer; //结点的层号域layer
     struct  Bnode  *Lson, *Rson; //指向左右儿子的链域
  } Bnode, *Bptr;  // 定义结点类型名和指针类型名

//按层输出二叉树的函数
void writeT(Bptr  root)
{ int frist=0,last=1;
  Bptr p,q[M];
  if(root->data==MIN)p=root->Rson; else p=root->Lson;//p指向真根结点
  if(p==NULL)
  {  printf("   当前二叉树为空,没有结点。\n"); return;}
  printf("      当前二叉树中的结点为:\n");
  printf("    层号    当前结点       左儿子    右儿子\n");
  p->layer=1; //根结点的层号为1
  q[0]=p;
  while(frist!=last)
  { p=q[frist++];  //队头结点出队
    printf("%6d%10d  ",p->layer,p->data); //输出当前结点
    if(p->Lson==NULL)printf("%12c",'\040'); //左儿子为空时,输出足够的空格
    else  //左儿子不空
     { printf("%12d",p->Lson->data); //输出左儿子   
       p->Lson->layer=p->layer+1; //给左儿子定层号
      q[last++]=p->Lson; //左儿子进队
     }
   if(p->Rson!=NULL) //若右儿子不空
     { printf("%12d",p->Rson->data);//输出右儿子
       p->Rson->layer=p->layer+1; //给右儿子定层号
      q[last++]=p->Rson;//右儿子进队
    }
  printf("\n"); //每个结点占一行
  }
}
//中序遍历函数
void  inorder(Bptr p)
  // p指向当前子树的根结点
  { 
    if(!p)  return;  //若p等于NULL,什么也不做,返回
    inorder(p->Lson);
    printf("%5d",p->data);
    inorder(p->Rson);
  }
//排序输出树中结点的函数
void sortT(Bptr root)
  {
   if(root->data==MIN)   inorder(root->Rson);
    else   inorder(root->Rson);
   printf("\n");
  }

//算法4-8  检索树的查找算法
Bptr  search(valuetype x,Bptr p)
  //参数x是待查元素值
  //参数p是指向当前结点的指针
  //返回值是指向值为x的结点指针;若x不在树中,返回NULL
  {
   while(p!=NULL)
    {  if (x==p->data)  return  p;  //找到x,返回指向结点x的指针
       if (x<p->data)  p=p->Lson;  //转向左子树查找
       else  p=p->Rson;  //转向右子树查找
    }
  return  NULL; //遇到空树,表明没查到x,返回NULL
  }
//主调语句:p=search(x,root);
//查找操作
 void  searchT(Bptr root)
  //root是指向当前结点的指针
 {  int x; 
   printf("请输入要查找的结点值x>0,x=");
   scanf("%d",&x); 
   if(search(x,root) ==NULL)  printf("树中没有 %d !\n",x);
    else   printf(" %d  已被找到!\n ",x);
 }
//********************************
//算法4-9  检索树非递归的插入算法
//主调语句为: insert( x, root);
void  insert(valuetype  x, Bptr &root)
  //x是待插入元素值
  // root是指向根结点的指针
 { Bptr f,p;
   f=NULL;  p=root;  //采用f和p双指针搜索法,f将指向p的父结点
   while(p!=NULL)  //一直查到p等于空
   if(x<=p->data)  f=p, p=p->Lson;  //转向左子树
    else  f=p, p=p->Rson;  //转向右子树
  //程序执行到此处时,p的值等于NULL
   p=(Bptr)malloc(sizeof(Bnode));  //产生新结点 
   p->data=x;  p->Lson=p->Rson=NULL;  //x做新叶
   if(f==NULL) root=p;  //若插入前树为空,则x做根
   else
    if(x<=f->data)  f->Lson=p; //  x做f的左儿子
     else  f->Rson=p; //  x做f的右儿子
   }

//插入操作
void  insertT(Bptr p)
{  int x;
   printf("请输入要插入的结点值x>0,x=");
   scanf("%d",&x);  
   insert(x,p);
   printf(" %d 已被插在树中。\n",x);
}

//算法4-12  检索树的构造算法
//主调语句:root=creatST( );
Bptr  creatST( )
 //输入以ZERO为结束标记的元素序列
 //返回所构造的二叉树根结点指针
  { Bptr  root;   valuetype  x;
   root=NULL;  //造一个空树
   printf("    构造初始检索树,请输入元素序列,元素个数不超过 %d,要求:  \n",M);
   printf("序列以 %d 或 %d 开始,以 0 结束,元素值均为小于 %d的正整数\n",MIN,MAX,MAX);
   scanf("%d",&x);  //读入元素x
   while(x!=ZERO)  //x不是结束标记ZERO时,循环
    { insert(x,root);  //将x插到树中
      scanf("%d",&x);  //读入下一个x值
    }
   return  root;  //退出循环后,返回根指针
  }
//&&&&&&&&&&&&&&&&&&&&&
//算法4-13  带表头监督元结点的检索树删除算法
//主调语句形如:k=deleteST(x,root);
int deleteST(valuetype x, Bptr root)
//root是根指针(指向监督元结点),x是要删除的结点值
 { Bptr f,p,s,r;
  //句1至句5的循环用于查找x
  for(p=root; ; ) //p是搜索指针,初值指向虚根
  { 
    if(p==NULL) return  DEFT; //遇到空树,x不在树中,返回删除不成功信息
    if(x==p->data)  break;  //找到x后,退出循环
    if(x<p->data)  {f=p; p=p->Lson;}  //向左
      else  { f=p; p=p->Rson;}  //向右
  }//循环体结束
//以下是找到x后(p指向x)的处理步骤
  if (p->Rson==NULL) 
      // p没有右儿子(是叶,或只有左儿子),用左儿子代替p
  { if (p==f->Lson) f->Lson=p->Lson; else  f->Rson=p->Lson; 
    free(p);  //删去p
    return  SUCC;  //返回删除成功信息
  } 
  if (p->Lson==NULL)  
    // p有右儿子,无左儿子,用右儿子代替p
  {  if (p==f->Lson) f->Lson=p->Rson; else  f->Rson=p->Rson; 
     free(p);  //删去p
     return  SUCC; //返回删除成功信息
  } 
 //以下处理p有两个儿子的情况
   s=p->Lson;   //s是p的左儿子
   if (s->Rson==NULL)
  //p的左儿子s没有右儿子,s是p的中序前趋
    {  p->data=s->data;  //用s的值域代换p的值域
       p->Lson=s->Lson; 
       free(s);  //删去s
       return  SUCC; //返回删除成功信息
    }
 //p的左儿子s有右儿子
   r=s->Rson;  //找p的左儿子的最右子孙r
   while(r->Rson!=NULL) {s=r; r=r->Rson;}  //r始终是s的右儿子
   p->data=r->data;  //用r的值域代换p的值域
   s->Rson=r->Lson; 
   free(r);   //删去r
   return  SUCC;  //返回删除成功信息
   }//函数结束

//删除操作
void  deleteT( Bptr root)
  //root为根指针
  {  int x;
     printf("请输入要删除的结点值x>0,x=");
     scanf("%d",&x);
     if(deleteST(x,root))
       printf("  %d  已被删除! \n",x);
     else printf("  %d 不在树中,无法删除!\n",x);
}

char getalpha()
 { char c;
   while(1)
   { c=getchar();
    if(isalpha(c))return c;
   }
 }
void treeT(Bptr  root)
{ char c;
  printf("   对检索树可以进行下列操作:\n");
  printf("F/f:查找;    I/i:插入\nD/d:删除;    P/p:显示树中结点\n");
  printf("S/s:结点排序;   E/e:退出;   其他字母:程序继续!  \n");
  while(1)
  { printf("请输入操作码:查找F,插入I,删除D,显示P,结点排序S,终止E)?");
    c=getalpha();
    switch(c)
    { 
    case 'f':
    case 'F': searchT(root); break; //查找
    case 'p':
    case 'P': writeT(root);  break;  //显示
    case 'i':
    case 'I': insertT(root); break;  //插入
    case 'd':
    case 'D': deleteT(root); break;  //删除
    case 's':
    case 'S': sortT(root);  break; //结点排序输出
    case 'e':
    case 'E': writeT(root);  return; //退出
    default : printf("输入操作码不对,请重新输入! \n");continue ;  //继续
    }
  }
}

int  main( )  //主函数
{ Bptr  root;
  root= creatST( );//构造初始检索树
  treeT(root);
  printf("程序结束,再见!\n");
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值