多路查找树:2-3-4树

1 定义

2 2-3-4树的插入

  

3 2-3-4树的删除

 

 

4 2-3-4树的删除的另外一种描述

5 2-3-4树代码实现

 

#include<iostream>
#include<cstring>
#include<cmath>

#define SUC
//#define PREDEC

using namespace std;

class Node{
private:
	int key[4];
	int cap;
	Node* parent;
	Node* child[5];
public:
	Node()
	{
		cap = 0;
		for(int i = 0; i < 5; i++)
			child[i] = NULL;
	}
	void put_key(int k)
	{
		int i;
		for(i = 0; i < cap; i++)
			if(key[i] > k)
				break;
		for(int j = cap; j > i; j--)
			key[j] = key[j - 1];
		key[i] = k;
		cap++;
	}
	int del_key(int k)
	{
		int i;
		for(i = 0; i < cap; i++)
			if(key[i] == k)
				break;
		for(int j = i; j < cap - 1; j++)
			key[j] = key[j + 1];
		cap--;
		return i;
	}
	int ret_key(int i)
	{
		return key[i];
	}
	int ret_cap()
	{
		return cap;
	}
	void set_parent(Node* p)
	{
		parent = p;
	}
	Node* ret_parent()
	{
		return parent;
	}
	void set_child(int i, Node* c)
	{
		child[i] = c;
	}
	Node* ret_child(int i)
	{
		return child[i];
	}
};


class Tree{
private:
	Node* root;
	int dep;
public:
	Tree()
	{
		root = new Node();
		root->set_parent(NULL);
		dep = 1;
	}
	Node* find_node(int k)
	{
		Node *now = root;
		for(int i = 0; i < dep; i++)
		{
			int j = 0;
			for(; j < now->ret_cap(); j++)
				if(now->ret_key(j) >= k)
					break;
			if(j < now->ret_cap() && now->ret_key(j) == k)
				return now;
			if(i != dep -1)
				now = now->ret_child(j);
		}
		return now;
	}
	int find_key(int k)
	{
		Node* now = root;
		for(int i = 0; i < dep; i++)
		{
			int j;
			for(j = 0; j < now->ret_cap(); j++)
				if(now->ret_key(j) >= k)
					break;
			if(j < now->ret_cap() && now->ret_key(j) == k)
				return 1;
			if(i != dep -1)
				now = now->ret_child(j);
		}
		return 0;
	}
	void insert_key(int k)
	{
		if(find_key(k))
		{
			cout << k << " ALREADY EXISTS" << endl;
			return ;
		}
		Node *now = find_node(k);
		now->put_key(k);
		while(now->ret_cap() > 3)
		{
			if(now == root)
			{
				Node *new_root = new Node();
				new_root->set_parent(NULL);
				new_root->set_child(0, now);
				now->set_parent(new_root);
				root = new_root;
				dep++;
			}
			Node *p = now->ret_parent();
			Node *new_node = new Node();
			new_node->set_parent(p);
			new_node->set_child(0, now->ret_child(3));
			new_node->set_child(1, now->ret_child(4));
			new_node->put_key(now->ret_key(3));
			now->set_child(3, NULL);
			now->set_child(4, NULL);
			p->put_key(now->ret_key(2));
			now->del_key(now->ret_key(2));
			now->del_key(now->ret_key(2));
			int i;
			for(i = 0; i < p->ret_cap() + 1; i++)
				if(p->ret_child(i) == now)
					break;
			for(int j = p->ret_cap(); j > i; j--)
				p->set_child(j, p->ret_child(j - 1));
			p->set_child(i + 1, new_node);
			if(new_node->ret_child(0) != NULL && new_node->ret_child(1) != NULL)
			{
				new_node->ret_child(0)->set_parent(new_node);
				new_node->ret_child(1)->set_parent(new_node);
			}
			now = p;
		}
	}
	void delete_key(int k)
	{
		if(!find_key(k))
		{
			cout << k << " NOT FOUND" << endl;
			return ;
		}
		int loc;
		Node *now = find_node(k), *ch;
		loc = now->del_key(k);
#ifdef SUC
		ch = now->ret_child(loc + 1);
		while(ch != NULL)
		{
			if(ch->ret_child(0) == NULL)
			{
				now->put_key(ch->ret_key(0));
				ch->del_key(ch->ret_key(0));
				now = ch;
				break;
			}
			ch = ch->ret_child(0);
		}
#endif
#ifdef PREDEC
		ch = now->ret_child(loc);
		while(ch != NULL)
		{
			if(ch->ret_child(0) == NULL)
			{
				now->put_key(ch->ret_key(ch->ret_cap() - 1));
				ch->del_key(ch->ret_key(ch->ret_cap() - 1));
				now = ch;
				break;
			}
			ch = ch->ret_child(ch->ret_cap());
		}
#endif
		while(now->ret_cap() == 0)
		{
			int i;
			Node *p = now->ret_parent();
			if(p == NULL)
			{
				if(now->ret_child(0) == NULL)
					break;
				root = now->ret_child(0);
				root->set_parent(NULL);
				dep--;
				delete now;
				break;
			}
			Node *adj;
			for(i = 0; i < p->ret_cap() + 1; i++)
				if(p->ret_child(i) == now)
					break;
			if(i == 0)
				adj = p->ret_child(1);
			else
				adj = p->ret_child(i - 1);
			if(adj->ret_cap() == 1)
			{
				adj->put_key(p->ret_key(i > 0? i - 1 : 0));
				for(int j = i; j < p->ret_cap(); j++)
					p->set_child(j, p->ret_child(j + 1));
				p->del_key(p->ret_key(i > 0? i - 1 : 0));
				if(i == 0)
				{
					for(int j = adj->ret_cap(); j > 0; j--)
						adj->set_child(j, adj->ret_child(j - 1));
					adj->set_child(0, now->ret_child(0));
				}
				else
					adj->set_child(adj->ret_cap(), now->ret_child(0));
				if(now->ret_child(0) != NULL)
					now->ret_child(0)->set_parent(adj);
				delete now;
			}
			else
			{
				if(i == 0)
				{
					now->put_key(p->ret_key(0));
					p->del_key(p->ret_key(0));
					p->put_key(adj->ret_key(0));
					adj->del_key(adj->ret_key(0));
					now->set_child(1, adj->ret_child(0));
					for(int j = 0; j < adj->ret_cap() + 1; j++)
						adj->set_child(j, adj->ret_child(j + 1));
				}
				else
				{
					now->put_key(p->ret_key(i - 1));
					p->del_key(p->ret_key(i - 1));
					p->put_key(adj->ret_key(adj->ret_cap() - 1));
					adj->del_key(adj->ret_key(adj->ret_key(adj->ret_cap() - 1)));
					for(int j = now->ret_cap(); j > 0; j--)
						now->set_child(j, now->ret_child(j - 1));
					now->set_child(0, adj->ret_child(adj->ret_cap() + 1));
				}
			}
			now = p;
		}
	}
	void rec_show(Node *now, int d)
	{
		if(now == NULL)
			return ;
		for(int i = 0; i < d; i++)
			cout << "    ";
		cout << now->ret_key(0);
		for(int i = 1; i < now->ret_cap(); i++)
			cout << "," << now->ret_key(i);
		cout << endl;
		for(int i = 0; i <= now->ret_cap(); i++)
			rec_show(now->ret_child(i), d + 1);
	}
	void show_tree()
	{
		Node *now = root;
		if(now->ret_cap() == 0)
		{
			cout << "NO KEYS" << endl;
			return;
		}
		rec_show(now, 0);
	}
	void free_tree(Node *now)
	{
		if(now == NULL)
			return ;
		for(int i = 0; i <= now->ret_cap(); i++)
			free_tree(now->ret_child(i));
		delete now;
	}
	~Tree()
	{
		free_tree(root);
	}
};

int main()
{
	int key;
	char op[10] = {0, };
	Tree t;
	while(1)
	{
		cin >> op;
		if(!strcmp(op, "s"))
			t.show_tree();
		else if(!strcmp(op, "i"))
		{
			cin >> key;
			t.insert_key(key);
		}
		else if(!strcmp(op, "d"))
		{
			cin >> key;
			t.delete_key(key);
		}
		else if(!strcmp(op, "q"))
			break;
	}

	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值