2-3-4树实现

本文深入探讨了2-3-4树数据结构的核心概念、设计原理及其实现细节,通过实例展示了如何高效地进行插入、删除、查找等操作,并提供了完整的源代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//==================2-3-4树的异常处理类=========================
#ifndef TWO_THREE_FOUR_TREE_EXCEPTION_H_
#define TWO_THREE_FOUR_TREE_EXCEPTION_H_
#include<string>
#include<stdexcept>
class TtfTreeException:public std::logic_error
{
	public:
		TtfTreeException(const std::string &message="")
			:std::logic_error(message.c_str())
		{}
};
#endif


 

//===================two_three_four_tree_item.h=====================
#ifndef TWO_THREE_FOUR_TREE_ITEM_H_
#define TWO_THREE_FOUR_TREE_ITEM_H_
template<class ValT,class KeyT>
class Item
{
	public:
		Item()
		{}
		Item(ValT &_val,KeyT &_key)
			:val(_val),key(_key)
		{}
		KeyT getKey()const
		{
			return key;
		}
		ValT getVal()const
		{
			return val;
		}
		void set(ValT &_val,KeyT &_key)
		{
			val=_val;
			key=_key;
		}

	private:
		ValT val;
		KeyT key;
};
#endif


 

 

//====================two_three_four_tree_node.h=========================
// 2-3-4树的节点,
#ifndef TWO_THREE_FOUR_TREE_NODE_H_
#define TWO_THREE_FOUR_TREE_NODE_H_
template<class ItemT,class KeyT> class TtfTree;
template<class ItemT,class KeyT>
class Node
{
	private:
		enum {SIZE=3};
		//定义一个含有3个ItemT元素的数组,用于存放数据
		ItemT item[SIZE];
		//定义一个含有4个节点指针元素的数组,用于存放子树
		Node *childPtr[SIZE+1];
		//当前节点中数据项的数目;
		int size;

		Node(ItemT &_item,Node *fchildPtr,Node *lchildPtr)
		{
			item[0]=_item;
			childPtr[0]=fchildPtr;
			childPtr[1]=lchildPtr;
			size=1;
			childPtr[2]=childPtr[3]=NULL;
		}
		friend class TtfTree<ItemT,KeyT>;

};
#endif


 

//======================two_three_four_tree.h=========================
//2-3-4树的主体文件
#ifndef TWO_THREE_FOUR_TREE_H_
#define TWO_THREE_FOUR_TREE_H_
#include"two_three_four_tree_exception.h"
#include"two_three_four_tree_node.h"
template<class ItemT,class KeyT>
class TtfTree
{
	public:
		//默认构造函数
		TtfTree();
		//复制构造函数
		TtfTree(TtfTree &ttftree);
		~TtfTree();

		bool empty()const;

		void insert(ItemT &_item)throw(TtfTreeException);
		
		void remove(KeyT &_key)throw(TtfTreeException);
		//遍历2-3-4树
		void traverse(void (*visit)(ItemT _item));
		//检索2-3-4树
		void retrieve(KeyT &_key,ItemT &_item)throw(TtfTreeException);

	protected:
		void insertNode(Node<ItemT,KeyT>*&treePtr,ItemT &_item)throw(TtfTreeException);
		
		void removeNode(Node<ItemT,KeyT>*&treePtr,KeyT &_key,int &pos)throw(TtfTreeException);

		void traverseNode(Node<ItemT,KeyT>*&treePtr,void (*visit)(ItemT _item));

		void retrieveNode(Node<ItemT,KeyT>*&treePtr,KeyT &_key,ItemT &_item)throw(TtfTreeException);
		
		void copy(Node<ItemT,KeyT>*&treePtr,Node<ItemT,KeyT> *&oldPtr)throw(TtfTreeException);

		void destroy(Node<ItemT,KeyT>*&treePtr);

		// get the index of the childPtr the next child should retrieve
		int getIndex(Node<ItemT,KeyT>*&treePtr,KeyT &_key)const;

		//get the index of the item whose searchkey equal to _key;
		int getEqual(Node<ItemT,KeyT>*&treePtr,KeyT &_key)const;

		//分解具有三项数据的节点
		void spliteNode(Node<ItemT,KeyT>*&treePtr,int n)throw(TtfTreeException);
		//修复只含有一个数据项的节点,使其包含2或3项
		void repairNode(Node<ItemT,KeyT>*&treePtr,int n);
		//判断是否为根
		bool isRoot(Node<ItemT,KeyT>*&treePtr);
	private:
		Node<ItemT,KeyT> *root;
};
#endif


 

//==================two_three_four_tree.cpp=========================
//  2-3-4树的实现文件
#include<cstddef>
#include"two_three_four_tree.h"
template<class ItemT,class KeyT>
TtfTree<ItemT,KeyT>::TtfTree()
{
	root=NULL;
}

template<class ItemT,class KeyT>
TtfTree<ItemT,KeyT>::TtfTree(TtfTree &ttftree)
{
	copy(root,ttftree.root);
}

template<class ItemT,class KeyT>
TtfTree<ItemT,KeyT>::~TtfTree()
{
	destroy(root);
}

template<class ItemT,class KeyT>
bool TtfTree<ItemT,KeyT>::empty()const
{
	return root==NULL;
}
template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::insert(ItemT &_item)throw(TtfTreeException)
{
	if(empty())
	{
		root=new Node<ItemT,KeyT>(_item,NULL,NULL);
		if(root==NULL)
			throw TtfTreeException("allocate memory failded !");
	}
	else
	{
		if(root->size==3)
		{
			Node<ItemT,KeyT> *tempPtr=
				new Node<ItemT,KeyT>(root->item[2],root->childPtr[2],root->childPtr[3]);
			if(tempPtr==NULL)
				throw TtfTreeException("allocate memory failed !");
			root->childPtr[2]=root->childPtr[3]=NULL;
			Node<ItemT,KeyT> *tranPtr=
				new Node<ItemT,KeyT>(root->item[1],root,tempPtr);
			if(tranPtr==NULL)
				throw TtfTreeException("allocate memory failed !");
			root->size=1;
			root=tranPtr;
		}
		try{
			insertNode(root,_item);
		}catch(TtfTreeException &e)
		{
			throw;
		}
	}
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::remove(KeyT &_key)throw(TtfTreeException)
{
	if(empty())
		throw TtfTreeException("empty tree !");
	try{
		int index=-1;
		removeNode(root,_key,index);
	}catch(TtfTreeException &e)
	{
		throw;
	}
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::traverse(void (*visit)(ItemT _item))
{
	traverseNode(root,visit);
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::retrieve(KeyT &_key,ItemT &_item)throw(TtfTreeException)
{
	if(empty())
		throw TtfTreeException("empty tree !");
	try{
		retrieveNode(root,_key,_item);
	}catch(TtfTreeException &e)
	{
		throw;
	}
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::insertNode(Node<ItemT,KeyT>*&treePtr,ItemT &_item)throw(TtfTreeException)
{
	if(treePtr->childPtr[0]==NULL)
	{
		int index=getIndex(treePtr,_item.getKey());
		for(int i=treePtr->size;i>index;i--)
			treePtr->item[i]=treePtr->item[i-1];
		treePtr->item[index]=_item;
		(treePtr->size)++;
	}
	else
	{
		int index=getIndex(treePtr,_item.getKey());
		if(treePtr->childPtr[index]->size==3)
		{
				try{
					spliteNode(treePtr,index);
				}catch(TtfTreeException &e)
				{
					throw;
				}
		}
		//重新获取下一步要检索的孩子指针
		index=getIndex(treePtr,_item.getKey());
		insertNode(treePtr->childPtr[index],_item);
	}
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::removeNode(Node<ItemT,KeyT> *&treePtr,KeyT &_key,int &pos)throw(TtfTreeException)
{
	pos=getEqual(treePtr,_key);
	if(pos==-1)
	{
		if(treePtr->childPtr[0]==NULL)
			throw TtfTreeException("key item not exist !");

		pos=getIndex(treePtr,_key);
		if(treePtr->childPtr[pos]->size==1)
			repairNode(treePtr,pos);
		pos=getIndex(treePtr,_key);
		removeNode(treePtr->childPtr[pos],_key,pos);
	}
	else
	{
		Node<ItemT,KeyT>*tempPtr=treePtr->childPtr[pos+1];
		if(tempPtr==NULL)
		{
			for(int i=pos;i<treePtr->size-1;i++)
				treePtr->item[i]=treePtr->item[i+1];
			(treePtr->size)--;
		}
		else
		{
			while(tempPtr->childPtr[0]!=NULL)
				tempPtr=tempPtr->childPtr[0];
			treePtr->item[pos]=tempPtr->item[0];
			KeyT newkey=tempPtr->item[0].getKey();
			removeNode(treePtr->childPtr[pos+1],newkey,pos);
		}
	}
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::traverseNode(Node<ItemT,KeyT> *&treePtr,void (*visit)(ItemT _item))
{
	if(treePtr!=NULL)
	{
		int i=0;
		for(i=0;i<treePtr->size;i++)
		{
			traverseNode(treePtr->childPtr[i],visit);
			visit(treePtr->item[i]);
		}
		traverseNode(treePtr->childPtr[i],visit);
	}
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::retrieveNode(Node<ItemT,KeyT>*&treePtr,KeyT &_key,ItemT &_item)throw(TtfTreeException)
{
	int pos=getEqual(treePtr,_key);
	if(pos==-1)
	{
		if(treePtr->childPtr[0]==NULL)
			throw TtfTreeException("key item not exist !");
		pos=getIndex(treePtr,_key);
		retrieveNode(treePtr->childPtr[pos],_key,_item);
	}
	else
	{
		_item=treePtr->item[pos];
	}
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::copy(Node<ItemT,KeyT>*&treePtr,Node<ItemT,KeyT>*&oldPtr)throw(TtfTreeException)
{
	if(oldPtr!=NULL)
	{
		treePtr=new Node<ItemT,KeyT>(oldPtr->item[0],NULL,NULL);
		if(treePtr==NULL)
			throw TtfTreeException("allocate memory failed !");
		treePtr->size=oldPtr->size;
		int i=0;
		for(i=0;i<oldPtr->size;i++)
		{
			copy(treePtr->childPtr[i],oldPtr->childPtr[i]);
			treePtr->item[i]=oldPtr->item[i];
			
		}
		copy(treePtr->childPtr[i],oldPtr->childPtr[i]);
	}
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::destroy(Node<ItemT,KeyT>*&treePtr)
{
	if(treePtr!=NULL)
	{
		for(int i=0;i<=treePtr->size;i++)
		{
			destroy(treePtr->childPtr[i]);
		}
		delete treePtr;
		treePtr=NULL;
	}
}

template<class ItemT,class KeyT>
int TtfTree<ItemT,KeyT>::getIndex(Node<ItemT,KeyT> *&treePtr,KeyT &_key)const
{
	int i=0;
	while((i<treePtr->size)&&(treePtr->item[i].getKey()<_key))
		i++;
	return i;
}

template<class ItemT,class KeyT>
int TtfTree<ItemT,KeyT>::getEqual(Node<ItemT,KeyT> *&treePtr,KeyT &_key)const
{
	int i=0;
	while((i<treePtr->size)&&(treePtr->item[i].getKey()!=_key))
		i++;
	if(i>=treePtr->size)
		return -1;
	else
		return i;
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::spliteNode(Node<ItemT,KeyT>*&treePtr,int n)throw(TtfTreeException)
{
	Node<ItemT,KeyT> *tempPtr=treePtr->childPtr[n];
	Node<ItemT,KeyT> *tranPtr=
		new Node<ItemT,KeyT>(tempPtr->item[2],tempPtr->childPtr[2],tempPtr->childPtr[3]);
	if(tranPtr==NULL)
		throw TtfTreeException("allocate memory failed !");
	
	tempPtr->childPtr[2]=tempPtr->childPtr[3]=NULL;
	tempPtr->size=1;
	
	int i=0;
	for(i=treePtr->size;i>n;i--)
	{
		treePtr->item[i]=treePtr->item[i-1];
	    treePtr->childPtr[i+1]=treePtr->childPtr[i];
	}
	treePtr->item[i]=tempPtr->item[1];
	treePtr->childPtr[i+1]=tranPtr;
	(treePtr->size)++;
}

template<class ItemT,class KeyT>
void TtfTree<ItemT,KeyT>::repairNode(Node<ItemT,KeyT>*&treePtr,int n)
{
	if(n==treePtr->size)
		n=n-1;
	if((treePtr->childPtr[n]->size==1)&&(treePtr->childPtr[n+1]->size==1))
	{
		//合并treePtr->childPtr[n]和treePtr->childPtr[n+1]项
		treePtr->childPtr[n]->item[1]=treePtr->item[n];
		treePtr->childPtr[n]->item[2]=treePtr->childPtr[n+1]->item[0];
		treePtr->childPtr[n]->childPtr[2]=treePtr->childPtr[n+1]->childPtr[0];
		treePtr->childPtr[n]->childPtr[3]=treePtr->childPtr[n+1]->childPtr[1];
		treePtr->childPtr[n+1]->childPtr[0]=treePtr->childPtr[n+1]->childPtr[1]=NULL;
		treePtr->childPtr[n]->size=3;
		(treePtr->size)--;
		delete treePtr->childPtr[n+1];
		treePtr->childPtr[n+1]=NULL;
		
		if(isRoot(treePtr)&&(treePtr->size==1))
		{
			Node<ItemT,KeyT>*tempPtr=treePtr;
			treePtr=treePtr->childPtr[n];
			tempPtr->childPtr[n]=NULL;
			delete tempPtr;
		}
		else
		{
			int i=0;
			for(i=n;i<treePtr->size-1;i++)
			{
				treePtr->item[i]=treePtr->item[i+1];
				treePtr->childPtr[i+1]=treePtr->childPtr[i+2];
			}
			treePtr->childPtr[i+1]=NULL;
		}

	}
	else if(treePtr->childPtr[n]->size==1)
	{

		treePtr->childPtr[n]->item[1]=treePtr->item[n];
		treePtr->childPtr[n]->childPtr[2]=treePtr->childPtr[n+1]->childPtr[0];
		(treePtr->childPtr[n]->size)++;
		
		treePtr->item[n]=treePtr->childPtr[n+1]->item[0];

		int numb=treePtr->childPtr[n+1]->size;
		int i=0;
		for(i=0;i<numb-1;i++)
		{
			treePtr->childPtr[n+1]->item[i]=treePtr->childPtr[n+1]->item[i+1];
			treePtr->childPtr[n+1]->childPtr[i]=treePtr->childPtr[n+1]->childPtr[i+1];
		}
		treePtr->childPtr[n+1]->childPtr[i]=treePtr->childPtr[n+1]->childPtr[numb];
		treePtr->childPtr[n+1]->childPtr[numb]=NULL;
		(treePtr->childPtr[n+1]->size)++;
	}
	else
	{
		treePtr->childPtr[n+1]->item[1]=treePtr->childPtr[n+1]->item[0];
		treePtr->childPtr[n+1]->item[0]=treePtr->item[n];
		for(int i=2;i>0;i--)
			treePtr->childPtr[n+1]->childPtr[i]=treePtr->childPtr[n+1]->childPtr[i-1];
		int numb=treePtr->childPtr[n]->size;
		treePtr->childPtr[n+1]->childPtr[0]=treePtr->childPtr[n]->childPtr[numb];
		(treePtr->childPtr[n+1]->size)++;

		treePtr->item[n]=treePtr->childPtr[n]->item[numb-1];

		treePtr->childPtr[n]->childPtr[numb]=NULL;
		(treePtr->childPtr[n]->size)--;
	}
}

template<class ItemT,class KeyT>
bool TtfTree<ItemT,KeyT>::isRoot(Node<ItemT,KeyT>*&treePtr)
{
	return &treePtr==&root;
}


 

//================测试程序========================
#include<iostream>
#include<string>
#include<ctime>
#include<cstdlib>
#include"two_three_four_tree_item.h"
#include"two_three_four_tree.h"
#include"two_three_four_tree.cpp"
using namespace std;
void display(Item<string,string> _item);
int main()
{
	srand(time(0));
	TtfTree<Item<string,string>,string> atree;
	Item<string,string> newitem;
	string thekey,theval;
	cout<<"creating avl tree atree with 100 datas !"<<endl;
	for(int i=0;i<100;i++)
	{
		for(int j=0;j<10;j++)
		{
			thekey=thekey+char(rand()%26+'a');
			theval=theval+char(rand()%10+'0');
		}
		newitem.set(theval,thekey);
		try{
		atree.insert(newitem);
		thekey.clear();
		theval.clear();
		}catch(TtfTreeException &e)
		{
			cout<<e.what()<<endl;
		}
	}
	cout<<"the data in atree are :"<<endl;
	atree.traverse(display);
	cout<<"traverse the tree atree over !"<<endl;
	cout<<"enter the key word of the item (q to quit ):"<<endl;
	Item<string,string> aitem;
	string keyword;
	cin>>keyword;
	while(keyword!="q")
	{
		try{
			atree.retrieve(keyword,aitem);
			display(aitem);
		}catch(TtfTreeException &e)
		{
			cout<<e.what()<<endl;
		}
		cout<<"enter other one key (q to quit): "<<endl;
		cin>>keyword;
	}
	cout<<"enter the key word of the item you want to delete (q to quit):"<<endl;
	cin>>keyword;
	while(keyword!="q")
	{
		try{
			atree.remove(keyword);
		}catch(TtfTreeException &e)
		{
			cout<<e.what()<<endl;
		}
		cout<<"enter other one key (s to stop):"<<endl;
		cin>>keyword;
	}
	cout<<"create a tree same as atree !"<<endl;
	TtfTree<Item<string,string>,string> btree(atree);
	cout<<"the date in btree :"<<endl;
	btree.traverse(display);
	cout<<"over !"<<endl;
	return 0;

}
void display(Item<string,string> _item)
{
	cout<< _item.getKey()<<'\t'<<_item.getVal()<<endl;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值