2-3-4树

        前有2-3树,2-3-4树的概念不用多讲,相比2-3树,2-3-4树只需从根结点到叶结点进行一趟扫描,就能完成树的插入操作和删除操作。对2-3树而言,完成这样的操作需要从根结点向下进行一趟扫描,然后再从叶子结点到根结点进行一趟扫描。2-3-4树在插入操作的自顶向下的单趟扫描中,不断对4结点进行拆分,这样确保要插入的叶结点是一个2结点或者3结点。在删除操作的自顶下乡扫描中,可以看成是插入时的逆过程,在定位最终可以替换删除的叶结点的扫描过程中,不断对树进行重建。定义参照文章《2-3树的基本操作实现》中2-3树的定义,性质同2-3树。详见REF[1]的相关内容。

        2-3-4 树红黑树的一种等同,这意味着它们是等价的数据结构。换句话说,对于每个 2-3-4 树,都存在着至少一个数据元素是相同次序的红黑树。在 2-3-4 树上的插入和删除操作也等价于在红黑树中的颜色翻转和旋转。这使得它成为理解红黑树背后的逻辑的重要工具。

代码:

#include <iostream>
#include <iomanip>
#include <assert.h>

using namespace std; 

#define INT_MAX 0x3fffffff

typedef struct Tree234Node * Tree234;
typedef struct Tree234Node
{
	int datal;
	int datam;
	int datar;
	Tree234 lchild,mlchild,mrchild,rchild;
} Tree234Node;

typedef enum { two_node,three_node
} node_typde;
typedef enum {EQ,leaf,goleft,mleft,mright,goright
} compare_type;

void newroot(Tree234 *t,int key)
{
	/* create a new 2-3-4 tree ,only one data contained */
	*t = new Tree234Node;
	(*t)->datal = key;
	(*t)->datam = (*t)->datar = INT_MAX;
	(*t)->lchild = (*t)->rchild = (*t)->mlchild = (*t)->mrchild = NULL; 
} 

bool isfournode(Tree234 t)
{
	/* true returned if node t is four node otherwise false */
	assert(t != NULL);
	if (t->datar != INT_MAX)
		return true;
	return false; 
}

void splitRoot(Tree234 *t)
{
	/* create two new node p and q as lchild and mlchild of *t */
	Tree234 p,q;
	newroot(&p,(*t)->datal);
	newroot(&q,(*t)->datar);
	p->lchild = (*t)->lchild;
	p->mlchild = (*t)->mlchild;
	q->lchild = (*t)->mrchild;
	q->mlchild = (*t)->rchild;
	/* do some clear job for *t */
	(*t)->datal = (*t)->datam;
	(*t)->datam = (*t)->datar = INT_MAX;
	(*t)->lchild = p;
	(*t)->mlchild = q;
	(*t)->mrchild = (*t)->rchild = NULL;
}

node_typde typeOfNode(Tree234 t)
{

	if (t->datar == INT_MAX) {
		if (t->datam != INT_MAX) {
			return three_node;
		}
		else if (t->datal != INT_MAX) {
			return two_node;
		}
		else
			;
	}

}

void splitChildOf2(Tree234 *p,Tree234 *r)
{
	Tree234 q;
	newroot(&q,(*p)->datar);
	q->lchild = (*p)->mrchild;
	q->mlchild = (*p)->rchild;
	(*p)->mrchild = (*p)->rchild = NULL;
	
	if (*p == (*r)->lchild) {
		/* *p is the goleft child of *r */ 
		(*r)->datam = (*r)->datal;
		(*r)->datal = (*p)->datam;
		(*r)->mrchild = (*r)->mlchild;
		(*r)->mlchild = q;
	}
	else {
		/* *p is the mlchild of *r */
		(*r)->datam = (*p)->datam;
		(*r)->mrchild = q;	
	} 
	(*p)->datam = (*p)->datar = INT_MAX; 
}

void splitChildOf3(Tree234 *p,Tree234 *r)
{
	Tree234 q;
	newroot(&q,(*p)->datar);
	q->lchild = (*p)->mrchild;
	q->mlchild = (*p)->rchild;
	(*p)->mrchild = (*p)->rchild = NULL;
	(*p)->datar = INT_MAX;
	
	if(*p == (*r)->lchild) {
		/* *p is the lchild of *r */
		(*r)->datar = (*r)->datam;
		(*r)->datam = (*r)->datal;
		(*r)->datal = (*p)->datam;
		(*r)->rchild = (*r)->mrchild;
		(*r)->mrchild = (*r)->mlchild;
		(*r)->mlchild = q; 
	}
	else if (*p == (*r)->mlchild) {
		/* *p is mlchild of *r */
		(*r)->datar = (*r)->datam;
		(*r)->datam = (*p)->datam;
		(*r)->rchild = (*r)->mrchild;
		(*r)->mrchild = q; 
	}
	else {
		/* *p is the mrchild of *r */
		(*r)->datar = (*p)->datam;
		(*r)->rchild = q;
	}
	(*p)->datam = INT_MAX;
} 

bool isleaf(Tree234 t)
{
	if (t && t->lchild == NULL && t->mlchild == NULL && t->mrchild == NULL &&
			t->rchild == NULL)
		return true;
	else
		return false;
}

compare_type compare(int key, Tree234 t)
{
	if (isleaf(t))
		return leaf;
	if (key < t->datal)
		return goleft;
	else if (key > t->datar)
		return goright;
	else if (key < t->datar && key > t->datam)
		return mright;
	else if(key < t->datam && key > t->datal)
		return mleft; 
	else 
		return EQ;
} 

void putin(Tree234 *t,int key)
{
	/* insert key into a leaf node the leaf node is 2 node or 3 node */
	assert(*t != NULL);
	if (key < (*t)->datal) {
		(*t)->datar = (*t)->datam;
		(*t)->datam = (*t)->datal;
		(*t)->datal = key;
	}
	else if (key < (*t)->datam) {
		(*t)->datar = (*t)->datam;
		(*t)->datam = key;
	}
	else {
		(*t)->datar = key;
	}
}

void insert234(Tree234 *root, int key)
{
	/* insert key into a 2-3-4 tree root */
	Tree234 p,r;
	if (*root == NULL) {
		newroot(root,key);
	}
	else {
		if (isfournode(*root))
			splitRoot(root);
		p = *root;
		r = NULL;
		for (;;) {
			if (isfournode(p)) {
				if (typeOfNode(r) == two_node)
					splitChildOf2(&p,&r);
				else
					splitChildOf3(&p,&r);
				p = r;				
			}
			r = p;
			switch (compare(key,p)) {
				case EQ:		cout<<"Key = "<<key<<\
								" is already in the 2-3-4 tree"<<endl;
								return;
				case leaf :		putin(&p,key);
								return;
				case goleft:		p = p->lchild;
								break;
				case mleft:		p = p->mlchild;
								break;
				case mright:	p = p->mrchild;
								break;
				case goright: 	p = p->rchild;
			}
		}
	}
}

int childPos(Tree234 p,Tree234 q)
{
	/* p is parent of q */
	if (p->lchild == q)
		return 1;
	if (p->mlchild == q)
		return 2;
	if (p->mrchild == q)
		return 3;
	if (p->rchild == q)
		return 4;
} 
void combineRoot(Tree234 *p,Tree234 *q)
{
	/* q is  2-node and p is 2-node 
	and the nearest sibling r is 2-node 
	p is parent of q                  */
	Tree234 t =NULL;
	if (*q == (*p)->lchild){
		/* q is the lchild of p*/
		t = (*p)->mlchild;
		/* set data member */
		(*p)->datam = (*p)->datal;
		(*p)->datal = (*q)->datal;
		(*p)->datar = t->datal;
		/* set the sub tree link */
		(*p)->lchild = (*q)->lchild;
		(*p)->mlchild = (*q)->mlchild;
		(*p)->mrchild = t->lchild;
		(*p)->rchild = t->mlchild;
	}
	else{
		t = (*p)->lchild;
		/*set data member*/
		(*p)->datam = (*p)->datal;
		(*p)->datal = t->datal;
		(*p)->datar = (*q)->datal;
		/* set sub tree link*/
		(*p)->lchild = t->lchild;
		(*p)->rchild = t->mlchild;
		(*p)->mrchild = (*q)->lchild;
		(*p)->rchild = (*q)->mlchild; 
	}
	delete (*q);
	delete t;
	*q  = NULL;	
}
void combineX22(Tree234 *p,Tree234 *q, Tree234 *t,int pos)
{
	/* p is parent of q and t and t is by the right 
	side of q, p is 4-node                       */
	if (pos == 1) {
		/* q and t are at the left side */
		(*q)->datam = (*p)->datal;
		(*q)->datar = (*t)->datal;
		(*p)->datal = (*p)->datam;
		(*p)->datam = (*p)->datar;
		(*p)->datar = INT_MAX;
		/* sub tree link*/
		(*q)->mrchild = (*t)->lchild;
		(*q)->rchild = (*t)->mlchild;
		delete (*t);
		(*p)->mlchild = (*p)->mrchild;
		(*p)->mrchild = (*p)->rchild;
		(*p)->rchild = NULL;
		
	}
	else if (pos == 2) {
		/* q and t  in the midddle */
		/*data member*/
		(*q)->datam = (*p)->datam;
		(*q)->datar = (*t)->datal;
		(*p)->datam = (*p)->datar;
		(*p)->datar = INT_MAX;
		/*sub tree link*/ 
		(*q)->mrchild = (*t)->lchild;
		(*q)->rchild = (*t)->mlchild;
		(*p)->mrchild = (*p)->rchild;
		(*p)->rchild = NULL;
		delete (*t);
	}
	else {
		/* q and t are on the right side*/
		/*data member*/
		(*q)->datam = (*p)->datar;
		(*q)->datar = (*t)->datal;
		(*p)->datar = INT_MAX;
		/*sub tree link*/
		(*q)->mrchild = (*t)->lchild;
		(*q)->rchild = (*t)->mlchild;
		(*p)->rchild = NULL;
		delete (*t);				
	}			
}

void combineX234(Tree234 *p, Tree234 *q,Tree234 *t,int pos)
{
	switch (pos) {
		case 1:	/*q and t on the left side*/
				/*data move*/
				(*q)->datam = (*p)->datal;
				(*p)->datal = (*t)->datal;			
				break;
		case 2: /* q and t are in the middle */
				 /*data move*/
				(*q)->datam = (*p)->datam;
				(*p)->datam = (*t)->datal;
				break;
		case 3:	/* q and t are on the right side*/
				 /*data move*/
				(*q)->datam = (*p)->datar;
				(*p)->datar = (*t)->datal;
				break;
	}
	/*data move*/
	(*t)->datal = (*t)->datam;
	(*t)->datam = (*t)->datar;
	(*t)->datar = INT_MAX;
	/*sub tree link redirection*/
	(*q)->mrchild = (*t)->lchild;
	(*t)->lchild = (*t)->mlchild;
	(*t)->mlchild = (*t)->mrchild;
	(*t)->mrchild = (*t)->rchild;
	(*t)->rchild = NULL;
} 

Tree234 goDown(Tree234 p,int key)
{
	/* child link according key */
	if (key > p->datar)
		return p->rchild;
	if (key < p->datal)
		return p->lchild;
	if (key > p->datal && key < p->datam)
		return p->mlchild;
	if (key > p->datam && key < p->datar)
		return p->mrchild;
	return p;
}
Tree234 goLeftmost(Tree234 p)
{
	assert(p != NULL); 
	if (p->lchild)
		return p->lchild; 
}

bool keyIn(Tree234 t,int key)
{
	assert(t != NULL);
	if (key == t->datal || key == t->datam || key == t->datar)
		return true;
	return false;
}

bool deletex(Tree234 t,int key)
{
	/*delete key in leaf node t*/
	if (key == t->datar){
		t->datar = INT_MAX;
		return true;
	}
	else if (key == t->datam) {
		t->datam = t->datar;
		t->datar = INT_MAX;
		return true;
	}
	else if (key == t->datal) {
		t->datal = t->datam;
		t->datam = t->datar;
		t->datar = INT_MAX;
		return true; 
	}
	else {
		cout<<"Key = "<<key<<" is not in 2-3-4 tree."<<endl;
		return false; 
	} 
	
}
bool delete234(Tree234 *root, int key)
{
	/*delete a key from the 2-3-4 tree root*/
	Tree234 p,q,t,r;
	Tree234 target;
	bool isRoot = false;
	bool flag = false;
	int pos;
	if (isleaf(*root)){
		if (deletex(*root,key)){
			if ((*root)->datal == INT_MAX){
				delete *root;
				*root = NULL;
			}
			return true;
		}
	}
	else{
		p = *root;
		for (;;) {
			if (isleaf(p))
				break;
			if (keyIn(p,key)){
				target = p;
				flag = true;
				if (key == p->datal ){					
					pos = 1;
					q = p->mlchild;
				}
				else if (key == p->datam){
					pos = 2;
					q = p->mrchild;
				}
				else if (key == p->datar){
					pos = 3;
					q = p->rchild;
				}
			}
			else if (!flag) {
				q = goDown(p,key);
			}
			else{
				q = p->lchild;
			}
			
			if (typeOfNode(q) != two_node){
				p = q;
				continue;
			}
			else {
				isRoot = false;
				switch (childPos(p,q)) {
					case 1: t = p->mlchild;
							if (typeOfNode(t) == two_node){
								if (typeOfNode(p) == two_node){ 
									isRoot = true;
									combineRoot(&p,&q);
								}
								else
									combineX22(&p,&q,&t,1);
							}
							else 
								combineX234(&p,&q,&t,1);
							if (isRoot)
								q = p; 
							break;
					case 2: t = p->lchild;
							r = t;
							t = q;
							q = r;
							if (typeOfNode(q) == two_node) {
								if (typeOfNode(p) == two_node){
									isRoot = true;
									combineRoot(&p,&q);
								}
								else
									combineX22(&p,&q,&t,1);							
							}
							else
								combineX234(&p,&q,&t,1);
							if (isRoot)
								q = p;
							break;
					case 3: t = p->mlchild;
							r = t;
							t = q;
							q = r;
							if (typeOfNode(q) == two_node) {
								combineX22(&p,&q,&t,2);
							}
							else
								combineX234(&p,&q,&t,2);
							break;
					case 4: t = p->mrchild; 
							r = t;
							t = q;
							q = r;
							if (typeOfNode(q) == two_node) {
								combineX22(&p,&q,&t,3);
							}
							else
								combineX234(&p,&q,&t,3); 
							break;
							
				}
				p = q; 
				if (keyIn(p,key)){
					target = p;
					flag = true;
					if (key == p->datal ){					
						pos = 1;
					}
					else if (key == p->datam){
						pos = 2;
					}
					else if (key == p->datar){
						pos = 3;
					}
				} 
			}					
		} 
		if (flag){
			switch (pos) {
				case 1: target->datal = p->datal;
						break;
				case 2: target->datam = p->datal;
						break;
				case 3: target->datar = p->datal;
						break;		 
			}
			return deletex(p,p->datal);
		}
		else {
			return deletex(p,p->datal);
		}
	}
	
}

void visit(Tree234 t)
{
	if (t->datar != INT_MAX) {
		cout<<"("<<t->datal<<","<<t->datam<<","<<t->datar<<")";
	}
	else if (t->datam != INT_MAX) {
		cout<<"("<<t->datal<<","<<t->datam<<",)";
	}
	else
		cout<<"("<<t->datal<<",,)";
	
}

void trav(Tree234 t)
{
	if(t) {
		visit(t);
		if (t->lchild == NULL)	
			return;
		cout<<"(";
		trav(t->lchild);
		cout<<",";
		trav(t->mlchild);
		cout<<",";
		trav(t->mrchild);
		cout<<",";
		trav(t->rchild);
		cout<<")";
	}			
	
}
int main()
{
	Tree234 T = NULL;
	int i;
	for(i = 0; i < 12; i++){
		insert234(&T,i);
		cout<<"Key  =  "<<i<<"  inserted :"<<endl;
		trav(T);
		cout<<endl<<"----------------------------------------"
				"--------------------------"<<endl; 
	}
	int a[12] = {7,6,8,4,3,2,1,0,5,9,10,11};
	for (i = 0;i < 12; i++){
		delete234(&T,a[i]);
		cout<<"Key  =  "<<a[i]<<" deleted :"<<endl;
		trav(T);
		cout<<endl<<"----------------------------------------"
					"--------------------------"<<endl; 
	}
} 

(初实现版本,后面有时间再优化吧~哎)

测试输出:


Key  =  0  inserted :
(0,,)
------------------------------------------------------------------
Key  =  1  inserted :
(0,1,)
------------------------------------------------------------------
Key  =  2  inserted :
(0,1,2)
------------------------------------------------------------------
Key  =  3  inserted :
(1,,)((0,,),(2,3,),,)
------------------------------------------------------------------
Key  =  4  inserted :
(1,,)((0,,),(2,3,4),,)
------------------------------------------------------------------
Key  =  5  inserted :
(1,3,)((0,,),(2,,),(4,5,),)
------------------------------------------------------------------
Key  =  6  inserted :
(1,3,)((0,,),(2,,),(4,5,6),)
------------------------------------------------------------------
Key  =  7  inserted :
(1,3,5)((0,,),(2,,),(4,,),(6,7,))
------------------------------------------------------------------
Key  =  8  inserted :
(3,,)((1,,)((0,,),(2,,),,),(5,,)((4,,),(6,7,8),,),,)
------------------------------------------------------------------
Key  =  9  inserted :
(3,,)((1,,)((0,,),(2,,),,),(5,7,)((4,,),(6,,),(8,9,),),,)
------------------------------------------------------------------
Key  =  10  inserted :
(3,,)((1,,)((0,,),(2,,),,),(5,7,)((4,,),(6,,),(8,9,10),),,)
------------------------------------------------------------------
Key  =  11  inserted :
(3,,)((1,,)((0,,),(2,,),,),(5,7,9)((4,,),(6,,),(8,,),(10,11,)),,)
------------------------------------------------------------------
Key  =  7 deleted :
(3,,)((1,,)((0,,),(2,,),,),(5,9,)((4,,),(6,8,),(10,11,),),,)
------------------------------------------------------------------
Key  =  6 deleted :
(3,,)((1,,)((0,,),(2,,),,),(5,9,)((4,,),(8,,),(10,11,),),,)
------------------------------------------------------------------
Key  =  8 deleted :
(3,,)((1,,)((0,,),(2,,),,),(9,,)((4,5,),(10,11,),,),,)
------------------------------------------------------------------
Key  =  4 deleted :
(1,3,9)((0,,),(2,,),(5,,),(10,11,))
------------------------------------------------------------------
Key  =  3 deleted :
(1,9,)((0,,),(2,5,),(10,11,),)
------------------------------------------------------------------
Key  =  2 deleted :
(1,9,)((0,,),(5,,),(10,11,),)
------------------------------------------------------------------
Key  =  1 deleted :
(9,,)((0,5,),(10,11,),,)
------------------------------------------------------------------
Key  =  0 deleted :
(9,,)((5,,),(10,11,),,)
------------------------------------------------------------------
Key  =  5 deleted :
(10,,)((9,,),(11,,),,)
------------------------------------------------------------------
Key  =  9 deleted :
(10,11,)
------------------------------------------------------------------
Key  =  10 deleted :
(11,,)
------------------------------------------------------------------
Key  =  11 deleted :

------------------------------------------------------------------

REF:

1,数据结构(C语言版)  Ellis Horowitz等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值