2-3树

这几天学习和实现了《数据结构(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;



}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

紫云的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值