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++
- 2-3树的建树(即插入)过程
- 线段树的建树
- 数据结构——二叉树的建立和遍历(递归建树&层序遍历建树)
- PAT (Advanced Level) 1066. Root of AVL Tree (25) AVL树的插入建树
- 二叉搜索树(BST)的常用操作:建树、插入、查询、删除、排序打印
- 【原创】一维线段树的建树、插入、遍历和删除
- 二叉树的建树方法
- BST 二叉搜索树 (动态建树与静态建树)
- trie树(静态建树)
- 线段树(建树,查询)
- sdibt 2746 二叉树的输入 (先序建树)
- 【FZU 2185】 Problem 2185 树的路径覆盖(建树)
- UVA 548 Tree(建树树的遍历)
- POJ2528 Mayor's poster 线段树+插入节点建树解法
- 字典树学习——建树、插入、查找
- 完全二叉树 链式 非递归 插入建树
- 线段树的两种建树模型
- HDU 5444-二叉树的遍历+建树
- [VB.NET]私匙加密,用公匙解密,
- Struts1.2实现动态多文件(不定个数)上传
- [VB.NET]DATAGRIDVIEW如何赋值入下面的两个TEXTBOX
- Linux系统内核文件Cache管理机制简介
- [VB.NET]vb.net里如何实现多表关联查询并将结果集放入dataset中呢?请举个例子吧!
- 2-3树的建树(即插入)过程
- [VB.NET]帮我看看菜鸟代码??
- 我在实施CMMI开发项目时候的一些经验
- 使用ADSL上网会经常遇到网页打不开、下载中断、或者在线视、qq掉线、游戏掉线等现象
- 关于控制只能一个用户登陆的方法!
- [VB.NET]在vb.net中怎样来改变datagridview上一行的颜色??
- 两个超大数的相加
- [VB.NET]关于datagridviewr
- [VB.NET]关于更新