2-3树的建树(即插入)过程

来源:互联网 发布:男士钱包 知乎 编辑:程序博客网 时间:2024/05/17 00:55

题目:2-3树的建树(即插入)过程
问题描述:
 实现2—3树的插入过程。
 2—树是这样一种树:
  A.每个非叶子结点都有2个或3个儿子;
  B.每条众树根到树叶的路径长度相等;
  C.只有一个根结点的树也是2—3树。
算法设计思想:(冒泡法等方法)
 构建这样的结点:p指向父结点;lb指向左子树最大结点;mb指向第二个子树最大结点;ls指向最左孩子结点;ms指向中间孩子结点;rs指向最右孩子结点;ap附加孩子结点。
 向2—3树T插入新的结点:
如果T只有一个叶子结点 标记为 ,则创建一个新的根结点 ,创建一个新的叶子结点 标记为 ,使 和 成为 的孩子,使 和 中较大的成为左孩子,另一个为中间孩子;
如果T有多于一个的结点,则令 ( 为 中所有孩子都是叶子结点的结点),创建一个新的叶子结点 标记为 ,如果 只有两个标记为 和 的孩子,那么令 ,调整 、 和 为正确的顺序;如果 有三个孩子,则令 ,再调用 合并 及其四个孩子到树T中,并调整合并后的树T根结点到 结点的路径上结点顺序。
源代码:
#include <iostream.h>
#define Create(v,x) v=new TreeNode;v->data=x;v->p=NULL;v->lb=NULL;v->mb=NULL;v->ls=NULL;v->ms=NULL;v->rs=NULL;v->ap=NULL;
//define后的字符列表只能在同一行
#define Delete(v) delete(v);
typedef struct TreeNode
{
 int data;     //数据项
 struct TreeNode *p;   //指向父结点的指针
 struct TreeNode *lb;  //指向左子树最大结点的指针
 struct TreeNode *mb;  //指向第二个子树最大结点的指针
 struct TreeNode *ls;  //指向最左孩子结点的指针
 struct TreeNode *ms;  //指向中间孩子结点的指针
 struct TreeNode *rs;  //指向最右孩子结点的指针
 struct TreeNode *ap;  //附加孩子结点
}TreeNode;
TreeNode* BuildTTT(int x)
{
 TreeNode *t;
 Create(t,x);
 return t;
}
//查找函数,成功返回指向该结点的指针,否则返回NULL
TreeNode* Search(TreeNode *x,TreeNode *t)
//t为要查找的树的根结点,x为要查找的对象结点
{
 if(t==NULL) return NULL;  //查找失败
 if(t->ls!=NULL&&t->ls->ls==NULL)//若孩子的下一层为空则说明孩子都是叶子结点
  return t;
 else
 {
  if(x->data<=t->lb->data)
   return Search(x,t->ls); 
  else if((t->ms!=NULL&&t->rs==NULL)||x->data<=t->mb->data)
//只有两个孩子或者关键字〈=中间树的最大值
   return Search(x,t->ms);
  else  //最后就只能在第三个子树中寻找了嘛
   return Search(x,t->rs);
 }
}
TreeNode* MaxNode(TreeNode *t)  //寻找某棵树中的关键字最大的结点并返回之
{
 if(t->ls==NULL) return t;
 else
 {
  TreeNode *l=MaxNode(t->ls);
  TreeNode *m=MaxNode(t->ms);
  TreeNode *max=l;
  if(max->data<m->data)
   max=m;
  if(t->rs!=NULL)
  {
   TreeNode *r=MaxNode(t->rs);
   if(r->data>max->data)
    max=r;
  }
  return max;
 }
}
void AddSon(TreeNode *t)  //把有四个孩子的树转换成2-3树
{
 TreeNode *tt;
 Create(tt,0);
 tt->ls=t->rs;
 tt->ms=t->ap;
 tt->lb=MaxNode(t->rs);
 tt->mb=MaxNode(t->ap);
 t->rs->p=tt;
 t->ap->p=tt;
 t->rs=NULL;
 t->ap=NULL;
 if(t->p==NULL)  //无父结点即为根结点
 {
  TreeNode *r;
  Create(r,0);
  r->ls=t;
  r->ms=tt;
  r->lb=MaxNode(t);
  r->mb=MaxNode(tt);
  t->p=r;
  tt->p=r;
 }
 else
 {
  TreeNode *f=t->p;
  if(f->rs==t)//最右孩子
   f->ap=tt;
  else if(f->ms==t)//中间孩子
  {
   f->ap=f->rs;
   f->rs=tt;
  }
  else if(f->ls==t)//最左孩子
  {
   f->ap=f->rs;
   f->rs=f->ms;
   f->ms=tt;
  }
  tt->p=f;
  if(f->ap!=NULL)
   AddSon(f);
 }
}
//t为要插入的树的根结点,p为要插入的对象
void Insert(TreeNode *t,TreeNode *p)  
{
 if(t->ls==NULL)  //只有一个元素
 {
  TreeNode *tt;
  Create(tt,0); //新建一个树根
  if(t->data<p->data)
  {
   tt->lb=tt->ls=t;
   tt->mb=tt->ms=p;//初始错误ms误写成rs,导致程序无法正常执行
  }
  else if(t->data>p->data)
  {
   tt->lb=tt->ls=p;
   tt->mb=tt->ms=t;//初始错误ms误写成rs,导致程序无法正常执行
  }
  t->p=tt;   //开始忘了
  p->p=tt;
 }
 else    //还有其它元素
 {
  TreeNode *f=Search(p,t);
  if(f->rs==NULL) //只有两个孩子
  {
   if(f->ls->data>p->data)
   {
    f->rs=f->ms;
    f->ms=f->ls;
    f->ls=p;
    f->lb=p;
    f->mb=f->ms;
   }
   else if(f->ls->data<p->data&&p->data<f->ms->data)
   {
    f->rs=f->ms;
    f->ms=p;
    f->mb=p;
   }
   else if(p->data>f->ms->data)
    f->rs=p;
   p->p=f;
  }
  else  //有三个孩子时将p作为f的一个附加结点
  {
   if(f->ls->data>p->data)
   {
    f->ap=f->rs;
    f->rs=f->ms;
    f->ms=f->ls;
    f->ls=p;
    f->mb=f->ms;
   }
   else if(f->ls->data<p->data&&p->data<f->ms->data)
   {
    f->ap=f->rs;
    f->rs=f->ms;
    f->ms=p;
    f->mb=p;
   }
   else if(p->data>f->ms->data&&p->data<f->rs->data)
   {
    f->ap=f->rs;
    f->rs=p;
   }
   else if(p->data>f->rs->data)
    f->ap=p;
   p->p=f;
   AddSon(f);
  }
 }
 //while(t->p!=NULL) t=t->p;//在内部时不能保证直接返回到根结点
}
void PrintTree(TreeNode *t)//起始的遍历存在问题,只能打印首尾两个
{
 if(t->ls==NULL)   //叶子结点直接打印
  cout<<t->data<<"/t";
 else
 {
  PrintTree(t->ls);
  PrintTree(t->ms);
  if(t->rs!=NULL)
   PrintTree(t->rs);
  //PrintTree(t);  //若在此加上这句将会多次打印首尾,但仍不会打印其它元素
 }
}
int main(void)
{
 TreeNode *t=BuildTTT(1);
 TreeNode *p;
 Create(p,3);
 Insert(t,p);
 while(t->p!=NULL) t=t->p;//每次插入完成后退回到根结点
 Create(p,5);
 Insert(t,p);
 while(t->p!=NULL) t=t->p;
 Create(p,6);
 Insert(t,p);
 while(t->p!=NULL) t=t->p;
 Create(p,7);
 Insert(t,p);
 while(t->p!=NULL) t=t->p;
 Create(p,8);
 Insert(t,p);
 while(t->p!=NULL) t=t->p;
 Create(p,9);
 Insert(t,p);
 while(t->p!=NULL) t=t->p;
 cout<<"插入前"<<endl;
 PrintTree(t);  //插入前
 cout<<endl<<"插入2后"<<endl;
 Create(p,2);  //插入2
 Insert(t,p);
 while(t->p!=NULL) t=t->p;
 PrintTree(t);  //插入后
 cout<<endl;
 return 0;
}
完成环境:
Microsoft Visual Studio 6.0 C++

原创粉丝点击