这几天学习和实现了《数据结构(c语言版)》(李建中等人翻译的那本)里介绍的2-3树!
说实在,我若过一段时间来看这里的代码,估计我也看不懂了,不过结合书和书里的笔记,我想我还看得懂。
对以下代码有兴趣的学者,应该结合那本书来看吧!!!
大概说下:
插入:
a:待插入点,是2节点的,就往这里插入即可。
b: 待插入点,是3节点的,拆分这个节点。(小值留下,中值待定,大值放入新节点)。同时还得分这个被split的节点是左中右节点来分别处理。
删除:
....看书吧,情况分为7种或8种........
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
//INT_MAX
#define NODE_SIZE 100
typedef struct two_three *two_three_ptr;
typedef int element;
struct two_three{
element data_l,data_r;
two_three_ptr left_child,middle_child,right_child;
};
two_three_ptr node[NODE_SIZE];//for insert
int nodetop=0;
two_three_ptr nodedel[NODE_SIZE];//for delete
int nodedeltop=0;
int compare(two_three_ptr t,element x);
void pushnode(two_three_ptr t,two_three_ptr *n,int *top);
two_three_ptr popnode(two_three_ptr *n,int *top);
two_three_ptr search23(two_three_ptr t,element x);//search
void insert23(two_three_ptr *t,element y);//insert
void new_root(two_three_ptr *t,element y,two_three_ptr q);//新的根节点
two_three_ptr find_node(two_three_ptr t,element y,two_three_ptr *n,int *top);//关键字在否
void put_in(two_three_ptr p,element y,two_three_ptr q);
void split(two_three_ptr p,element *y,two_three_ptr *q);
void delete23(two_three_ptr *t,element y);//delete
two_three_ptr change(two_three_ptr d,element y);//交换节点
void deleteleaf(two_three_ptr *t,two_three_ptr d,element y);//删除叶子d节点上的y元素
void deleteone(two_three_ptr *t,two_three_ptr d);
void a_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s);
void b_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s);
void c_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s);
void a_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s);
void b_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s);
void c_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s);
void d_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s);
void e_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s);
two_three_ptr search23(two_three_ptr t,element x)//search
{
int i=0;
while(t)
{
++i;
switch( compare(t,x) )
{
case 1:t=t->left_child;break;
case 2:t=t->middle_child;break;
case 3:t=t->right_child;break;
case 4:{printf("%d层",i); return t;}
default:
fprintf(stderr,"have a error in search23\n");
}
}
return NULL;
}
void insert23(two_three_ptr *t,element y)//insert
{//y是元素, p是栈上的节点,q是新节点
two_three_ptr q,p;
if( !(*t) )//tree is empty
new_root(t,y,NULL);
else{
p=find_node(*t,y,node,&nodetop);//关键字在否
if(!p)
{
fprintf(stderr,"the key is currently in the tree\n");
exit(1);
}
q=NULL;
while(1)
{
if(p->data_r == INT_MAX)
{//2 node
put_in(p,y,q);
break;
}
else{
split(p,&y,&q);
if(p == *t)
{//split the root
new_root(t,y,q);
break;
}
else
p=popnode(node,&nodetop);//remote a node from stack
}
}
}
}
int compare(two_three_ptr t,element x)//查找元素在哪里
{
if (x < t->data_l)
return 1;
else if(x == t->data_l)
return 4;
else if(x > t->data_l && x < t->data_r)
return 2;
else if(x == t->data_r)
return 4;
else if(x > t->data_r)
return 3;
return 0;
}
void new_root(two_three_ptr *t,element y,two_three_ptr q)//新的根节点
{
two_three_ptr n=(two_three_ptr)calloc(1,sizeof(two_three));
n->data_l=y;
n->data_r=INT_MAX;
n->left_child=*t;
n->middle_child=q;
n->right_child=NULL;
*t=n;
}
two_three_ptr find_node(two_three_ptr t,element y,two_three_ptr *n,int *top)//关键字在否
{
while(t)
{
pushnode(t,n,top);
switch( compare(t,y) )
{
case 1:t=t->left_child;break;
case 2:t=t->middle_child;break;
case 3:t=t->right_child;break;
case 4:return NULL;//有这个关键字了,返回NULL
}
}
return n[--(*top)];//返回关键字应该插入的地方
}
void put_in(two_three_ptr p,element y,two_three_ptr q)
{
if (y < p->data_l)
{
p->right_child=p->middle_child;
p->middle_child=q;
p->data_r=p->data_l;
p->data_l=y;
}
else //y>p->data_l
{
p->data_r=y;
p->right_child=q;
}
}
void split(two_three_ptr p,element *y,two_three_ptr *q)
{
//分为 小值(左孩子过来),中值(中孩子过来的),大值(右孩子过来的)
element temp;
two_three_ptr n=(two_three_ptr)calloc(1,sizeof(two_three));
if (*y < p->data_l)//小值(左孩子过来),
{
n->data_l=p->data_r;
n->left_child=p->middle_child;
n->middle_child=p->right_child;
temp=p->data_l;
p->data_l=*y;
p->middle_child=*q;
*y=temp;
}
else if (*y > p->data_l && *y < p->data_r)//中值(中孩子过来的)
{
n->data_l=p->data_r;
n->left_child=*q;
n->middle_child=p->right_child;
}
else if (*y > p->data_r)//大值(右孩子过来的)
{
n->data_l=*y;
n->left_child=p->right_child;
n->middle_child=*q;
*y=p->data_r;
}
*q=n;
p->data_r=INT_MAX;
p->right_child=NULL;
n->data_r=INT_MAX;
}
void pushnode(two_three_ptr t,two_three_ptr *n,int *top)
{
if (*top == NODE_SIZE)
{
printf("error :nodetop is too high");
}
n[(*top)++]=t;//++的优先级高于 * ;这里一开始错了我
}
two_three_ptr popnode(two_three_ptr *n,int *top)
{
if (*top == 0)
{
printf("error :nodetop is less zero");
}
return n[--(*top)];
}
void delete23(two_three_ptr *t,element y)//delete
{
two_three_ptr temp;
if(find_node(*t,y,nodedel,&nodedeltop) == NULL)
{//存在
temp=popnode(nodedel,&nodedeltop);
if (temp->left_child == NULL){//是叶子节点
deleteleaf(t,temp,y);
}
else{//非叶子节点,这里找左子树的最大值来做替换
pushnode(temp,nodedel,&nodedeltop);
temp=change(temp,y);
deleteleaf(t,temp,y);
}
}
else{//不存在
printf("element is not exist\n");
}
}
void deleteleaf(two_three_ptr *t,two_three_ptr d,element y)//删除叶子d节点上的y元素
{
if (d->data_r == y)//两个值的最右值
{
d->data_r=INT_MAX;
}
else if (d->data_l == y && d->data_r !=INT_MAX )//两个值的最左值
{
d->data_l=d->data_r;
d->data_r=INT_MAX;
}
else//一个节点的,删除后要旋转或合并,大头啊!!!
{
deleteone(t,d);
}
}
void deleteone(two_three_ptr *t,two_three_ptr d)
{
d->data_l=INT_MAX;
while(d->data_l == INT_MAX)
{
if (d == *t)
{
*t=d->left_child;
break;
}
two_three_ptr parent=popnode(nodedel,&nodedeltop);
if (parent->left_child==d && parent->middle_child->data_r != INT_MAX)//a旋转
a_rotate(t,parent,d);
else if (parent->middle_child==d && parent->left_child->data_r != INT_MAX)//b旋转
b_rotate(t,parent,d);
else if (parent->right_child==d && parent->middle_child->data_r != INT_MAX)//c旋转
c_rotate(t,parent,d);
else if (parent->left_child==d && parent->data_r == INT_MAX && parent->middle_child->data_r == INT_MAX)//a合并
a_merge(t,parent,d);
else if (parent->left_child==d && parent->data_r != INT_MAX && parent->middle_child->data_r == INT_MAX)//b合并
b_merge(t,parent,d);
else if (parent->middle_child==d && parent->data_r == INT_MAX && parent->left_child->data_r == INT_MAX)//c合并
c_merge(t,parent,d);
else if (parent->middle_child==d && parent->data_r != INT_MAX && parent->left_child->data_r == INT_MAX)//d合并
d_merge(t,parent,d);
else if (parent->right_child==d && parent->middle_child->data_r == INT_MAX)//e合并
e_merge(t,parent,d);
d=parent;
}
}
void a_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s)
{
s->data_l=p->data_l;
p->data_l=p->middle_child->data_l;
p->middle_child->data_l=p->middle_child->data_r;
p->middle_child->data_r=INT_MAX;
s->middle_child=p->middle_child->left_child;
p->middle_child->left_child=p->middle_child->middle_child;
p->middle_child->middle_child=p->middle_child->right_child;
p->middle_child->right_child=NULL;
}
void b_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s)
{
s->data_l=p->data_l;
p->data_l=p->left_child->data_r;
p->left_child->data_r=INT_MAX;
s->middle_child=s->left_child;
s->left_child=p->left_child->right_child;
p->left_child->right_child=NULL;
}
void c_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s)
{
s->data_l=p->data_r;
p->data_r=p->middle_child->data_r;
p->middle_child->data_r=INT_MAX;
}
void a_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s)
{
s->data_l=p->data_l;
s->data_r=p->middle_child->data_l;
p->data_l=INT_MAX;
s->middle_child=p->middle_child->left_child;
s->right_child=p->middle_child->middle_child;
free(p->middle_child);
p->middle_child=NULL;
}
void b_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s)
{
s->data_l=p->data_l;
s->data_r=p->middle_child->data_l;
p->data_l=p->data_r;
p->data_r=INT_MAX;
s->middle_child=p->middle_child->left_child;
s->right_child=p->middle_child->middle_child;
free(p->middle_child);
p->middle_child=p->right_child;
p->right_child=NULL;
}
void c_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s)
{
p->left_child->data_r=p->data_l;
p->data_l=INT_MAX;
p->left_child->right_child=s->left_child;
free(s);
p->middle_child=NULL;
}
void d_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s)
{
p->left_child->data_r=p->data_l;
p->data_l=p->data_r;
p->data_r=INT_MAX;
p->left_child->right_child=s->left_child;
p->middle_child=p->right_child;
free(s);
p->right_child=NULL;
}
void e_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s)
{
p->middle_child->data_r=p->data_r;
p->data_r=INT_MAX;
p->middle_child->right_child=s->left_child;
free(s);
p->right_child=NULL;
}
two_three_ptr change(two_three_ptr d,element y)//交换节点
{
two_three_ptr temp;
int i=0;
element te;
if (d->data_l==y)//左值
temp=d->left_child;
else//右值
{
temp=d->middle_child;
i=1;
}
pushnode(temp,nodedel,&nodedeltop);
while(temp)
{
if (temp->data_r != INT_MAX && temp->right_child==NULL) //(a,INT_MAX)[x,0,0,]
{
te=temp->data_r;
temp->data_r=y;
break;
}
else if (temp->data_r != INT_MAX && temp->right_child !=NULL)
{
temp=temp->right_child;
pushnode(temp,nodedel,&nodedeltop);
continue;
}
else if (temp->data_r == INT_MAX && temp->middle_child ==NULL)
{
te=temp->data_l;
temp->data_l=y;
break;
}
else if (temp->data_r == INT_MAX && temp->middle_child !=NULL)
{
temp=temp->middle_child;
pushnode(temp,nodedel,&nodedeltop);
continue;
}
}
if (i==0)
d->data_l=te;
else
d->data_r=te;
popnode(nodedel,&nodedeltop);//pop掉这个temp
return temp;
}
int main(int argc, char const *argv[])
{
two_three_ptr t=NULL;
insert23(&t,10);
insert23(&t,40);
insert23(&t,80);
insert23(&t,20);
insert23(&t,70);
insert23(&t,30);
printf("%d %d\n", search23(t,70),search23(t,80));
insert23(&t,60);
insert23(&t,15);
printf("%d %d\n", search23(t,10),search23(t,15));
insert23(&t,35);
printf("%d %d\n", search23(t,35),search23(t,30));
two_three_ptr e=search23(t,40);
two_three_ptr f=search23(t,70);
printf("%d %d\n", e,f);
/*
--------------- 40, MAX
/ /
-----------20,MAX 70, MAX
/ / / /
---10,MAX 30,MAX 60,MAX 80,MAX
*/
///-----------------------------
printf("\n");
delete23(&t,15);
delete23(&t,30);
insert23(&t,9);//(10,15)-->(9,10)
insert23(&t,36);//(30,35)-->(35,36)
printf("%d %d\n", search23(t,9),search23(t,10));
printf("%d %d\n", search23(t,35),search23(t,36));
//arotate
delete23(&t,9);
delete23(&t,10);
insert23(&t,21);
printf("%d %d\n", search23(t,20),search23(t,21));
//brotate
delete23(&t,36);
insert23(&t,22);
printf("%d %d\n", search23(t,22),search23(t,35));
//crotate
insert23(&t,30);
insert23(&t,25);
delete23(&t,35);
printf("%d %d\n", search23(t,21),search23(t,25));
//amerge
printf("amerge\n");
two_three_ptr t1=NULL;
insert23(&t1,10);
insert23(&t1,20);
insert23(&t1,40);
delete23(&t1,10);
printf("%d %d\n", search23(t1,20),search23(t1,40));
//bmerge
printf("bmerge\n");
delete23(&t,20);
printf("%d %d\n", search23(t,21),search23(t,22));
//cmerge
printf("cmerge\n");
two_three_ptr t2=NULL;
insert23(&t2,10);
insert23(&t2,20);
insert23(&t2,40);
delete23(&t2,40);
printf("%d %d\n", search23(t2,10),search23(t2,20));
//dmerge
insert23(&t,26);
insert23(&t,27);
delete23(&t,22);
delete23(&t,26);
printf("%d %d\n", search23(t,21),search23(t,25));
//cmerge和dmerge是可以合并的,c按照d的方法来即可
//emerge
insert23(&t,28);
insert23(&t,29);
delete23(&t,30);
printf("%d %d\n", search23(t,28),search23(t,29));
return 0;
}