超时了呀。。。。。
查看原帖
超时了呀。。。。。
403702
Frank_rucer楼主2021/12/21 14:26
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <climits>
#include <stack>
using namespace std;
typedef int ElemType;
//B-tree结点的结构
typedef struct BNode
{
	bool is_leaf;//是否为孩子节点
	int size;//当前节点关键字个数
	std::vector<ElemType>key;//该节点的关键字
	std::vector<BNode*>child;//该节点的孩子节点
}BNode;
typedef struct search_return
{
	BNode* node;//所在节点位置
	int k;//所在节点第k个关键字
}search_return;

class BTree
{
//private:
public:
	BNode* root;//Btree
	int t;//B树的度
private:
	void split_child(BNode* R,int k);//将R结点k孩子拆分
	int merge_child(BNode* R, int k);//合并左右结点
	int fix_child(BNode* R, int index);//保证R的k结点关键字个数符合条件
	ElemType node_delete(BNode* T, unsigned index);
	unsigned node_Insert(BNode* T, ElemType x);
	unsigned find_index(BNode* T, ElemType x);
	int node_num(BNode* T);//计算该树节点个数
public:
	BTree(int degree);
	search_return search(ElemType x);
	void insert(ElemType x);
	void eraser(ElemType x);
	int node_rank(ElemType x);//查询x的排名
	ElemType search_rank(int rank);//查询排名为rank的关键字
	ElemType prev_node(ElemType x);//找到x的前驱节点
	ElemType next_node(ElemType x);//找到x的后继节点
	void traverse();
};

//B树的初始化
BTree::BTree(int degree)
{
	root = new BNode;
	root->size = 0;
	root->is_leaf = true;
	t = degree;
	/*
	* B树的度为t,t>=2;
	* 除根结点外至少t-1个关键字,t个孩子
	* 至多含有2t-1个关键字,2t个孩子
	*/
}

//查找元素的位置
//search_return BTree::search(ElemType x)
//{
//	BNode* curr = root;//从根节点开始
//	while (true)
//	{
//		int index = 0;
//		while (index < curr->size)//遍历所在结点关键字
//		{
//			if (curr->key[index] < x)
//				++index;
//			else
//				break;
//		}
//		if (index != curr->size && curr->key[index] == x)
//		{
//			search_return re;
//			re.k = index;
//			re.node = curr;
//			return re;
//		}
//		if (curr->is_leaf)
//			break;
//		curr = curr->child[index];
//	}
//	search_return re;
//	re.k = -1;
//	re.node = NULL;
//	return re;
//}

//将R结点的k孩子分裂(该孩子结点已满,2t-1个关键字)
void BTree::split_child(BNode* R, int k)
{
	BNode* p = R->child[k];//取出该孩子节点
	BNode* lNode = new BNode;
	BNode* rNode = new BNode;
	lNode->is_leaf = p->is_leaf;
	lNode->size = this->t - 1;
	rNode->is_leaf = p->is_leaf;
	rNode->size = this->t - 1;
	//将前t-1个关键字放入lNode
	for (int i = 0; i < t - 1; ++i)
		lNode->key.push_back(p->key[i]);
	//取出中间关键字,稍后放入R节点中
	int mid_key = p->key[t-1];
	//将后t-1个结点放入rNode
	for (int i = t; i < 2*t - 1; ++i)
		rNode->key.push_back(p->key[i]);
	//如果非叶节点,还需要复制孩子节点
	if (!p->is_leaf)
	{
		//将前m个节点放入lNode
		for (int i = 0; i < t; ++i)
			lNode->child.push_back(p->child[i]);
		//将后m个节点放入rNode中
		for (int i = t; i < 2 * t; ++i)
			rNode->child.push_back(p->child[i]);
	}
	R->key.push_back(mid_key);//将中间节点加入R
	sort(R->key.begin(), R->key.end());//重新非降序排列
	++R->size;//关键字个数+1
	R->child[k] = lNode;
	int n = R->child.size();
	R->child.push_back(R->child[n - 1]);
	for (int i = n - 1; i >= k + 2; --i)
		R->child[i] = R->child[i - 1];
	R->child[k + 1] = rNode;
}

//将x关键字插入B树
void BTree::insert(ElemType x)
{
	//当根节点满时,拆分需要特别处理
	if (root->size == 2 * t - 1)
	{
		BNode* new_root = new BNode;
		new_root->size = 0;
		new_root->is_leaf = false;
		new_root->child.push_back(root);
		root = new_root;
		split_child(root, 0);
	}
	BNode* curr = root;//当前处理的结点,初始时非满
	while (!curr->is_leaf)
	{
		//寻找x应该位于哪个孩子结点
		int index = curr->size - 1;
		while (index >= 0 && x < curr->key[index])
			--index;
		++index;
		if (curr->child[index]->size == 2 * t - 1)//该孩子节点满
		{
			split_child(curr, index);
			if (curr->key[index] < x)
				++index;
		}
		curr = curr->child[index];
	}
	curr->key.push_back(x);
	sort(curr->key.begin(), curr->key.end());//关键字非降序排列
	++curr->size;//关键字+1
}

//新节点2,改变但不是root1,未改变0
//合并R的k结点的左右子节点
int BTree::merge_child(BNode* R, int k)
{
	BNode* lchild = R->child[k];
	BNode* rchild = R->child[k + 1];
	lchild->key.push_back(R->key[k]);//合并R中k关键字
	++lchild->size;
	for (int i = 0; i < rchild->size; ++i)//合并rchild关键字
		lchild->key.push_back(rchild->key[i]);
	lchild->size += rchild->size;//调整lchild的关键字数目
	node_delete(R, k);
	if(!rchild->is_leaf)
		for (int i = 0; i <= rchild->size; ++i)//合并rchild的子节点
			lchild->child.push_back(rchild->child[i]);
	if (!R->size)//如果R结点为空
	{
		R = lchild;
		return 2;
	}
	return 1;
}

//调整R的index孩子结点大小,同时返回是否调整
int BTree::fix_child(BNode* R, int index)
{
	BNode* kid = R->child[index];//定位到所要操作的结点 
	if (kid->size < t)//如果不符合要求就要进行调整
	{
		BNode* lkid = R->child[index - 1];//kid左兄弟
		BNode* rkid = R->child[index + 1];//kid右兄弟
		//向左兄弟节点借
		if (index != 0 && lkid->size >= t)
		{
			node_Insert(kid, R->key[index - 1]);//将R的index-1关键字插入kid中
			if(!kid->is_leaf&&!lkid->is_leaf)
				kid->child[0] = lkid->child[lkid->size];//将lkid的最有孩子节点放到kid中
			R->key[index - 1] = node_delete(lkid, lkid->size - 1);//删除最后一个节点,并赋值给R的index-1
		}
		//向右兄弟借
		else if (index != R->size && rkid->size >= t)
		{
			node_Insert(kid, R->key[index]);
			if (!kid->is_leaf && !rkid->is_leaf)
			{
				kid->child[kid->size] = rkid->child[0];
				rkid->child[0] = rkid->child[1];//删除操作会删除1孩子,所以我们提前将1放在0位置,而0孩子已经被拿走,所以无所谓
			}
			R->key[index] = node_delete(rkid, 0);
		}
		//左右兄弟都不够,都是t-1,合并时需要考虑边界
		//如果不是第一个元素,结合右兄弟合并
		else if (index != 0)//
			return merge_child(kid, index - 1);
		else
			return merge_child(kid, index);
		return 1;
	}
	return 0;
}
//将x关键字删除
void BTree::eraser(ElemType x)
{
	BNode* curr = root;//当前处理的节点
	while (true)
	{
		unsigned index = find_index(curr, x);
		//在当前结点关键字中找到了x
		if (index < curr->size && x == curr->key[index])
		{
			//如果是叶子节点,直接删除
			if (curr->is_leaf)
				node_delete(curr, index);
			//如果不是叶子节点
			else
			{
				BNode* lkid = curr->child[index];
				BNode* rkid = curr->child[index + 1];
				//如果左节点关键字多于t-1
				//取左节点所在子树最右结点顶替index,然后删除该子树中最右结点
				//在查找最右结点的过程,每次调整所在结点大小,保证>=t,这样删除节点时大小合适
				if (lkid->size >= t)
				{
					while (!lkid->is_leaf)
					{
						fix_child(lkid, lkid->size);//不断调整最右孩子,保证找到最后孩子叶结点时删除可行
						lkid = lkid->child[lkid->size];
					}
					curr->key[index] = node_delete(lkid, lkid->size - 1);//删除结点并给kid的index位置 
				}
				//镜像过程
				else if (rkid->size >= t)
				{
					//找到最左结点,也就是最小节点
					while (!rkid->is_leaf)
					{
						fix_child(rkid, 0);
						rkid = rkid->child[0];
					}
					curr->key[index] = node_delete(rkid, 0);
				}
				//做有分支结点都只含有t-1个关键字
				//合并左右子孩子到左子树
				else
				{
					merge_child(curr, index);
					curr = curr->child[index];
					continue;
				}
			}
			return;
		}
		//未在当前结点关键字中找到x
		else
		{
			if (curr->is_leaf)//如果到了叶子节点还没找到
			{
				std::cout << "no exit!\n";
				return;
			}
			int judge = fix_child(curr, index);
			if (judge == 2)
				curr = root;
			else
				curr = curr->child[find_index(curr, x)];
		}
	}
}

//调试,对节点进行层次遍历
void BTree::traverse()
{
	std::queue<BNode*>Q;
	Q.push(root);
	while (!Q.empty())
	{
		BNode* tp = Q.front();
		Q.pop();
		for (int i = 0; i < tp->size; ++i)
			std::cout << tp->key[i] << ' ';
		//std::cout << tp->is_leaf;
		std::cout << std::endl;
		int n = tp->child.size();
		if(!tp->is_leaf)
			for (int i = 0; i < n; ++i)
				Q.push(tp->child[i]);
	}
}

//删除index位置节点,同时如果非叶子节点index+1孩子节点会删除,调用函数需要提前转移
ElemType BTree::node_delete(BNode* T, unsigned index)
{
	ElemType re = T->key[index];
	--T->size;
	while (index < T->size)//由于size已经-1,所以不会越界
	{
		T->key[index] = T->key[index + 1];
		//如果不是叶子节点还要进行孩子节点的处理
		if (!T->is_leaf)
			T->child[index + 1] = T->child[index + 2];
		++index;
	}
	T->key.pop_back();//删除关键字
	if (!T->is_leaf)
		T->child.pop_back();
	return re;
}

//将x关键字插入T,并返回插入index,同时如果非叶子节点,index和index+1孩子节点调用函数需要进行调整
unsigned BTree::node_Insert(BNode* T, ElemType x)
{
	int index = T->size;//从关键字末尾开始遍历
	T->key.push_back(0);//扩展key数组长度
	if(!T->is_leaf)
		T->child.push_back(NULL);//扩展child数组长度
	while (index > 0 && x < T->key[index - 1])
	{
		T->key[index] = T->key[index - 1];
		if(!T->is_leaf)
			T->child[index + 1] = T->child[index];
		--index;
	}
	if(!T->is_leaf)
		T->child[index + 1] = T->child[index];
	T->key[index] = x;
	++T->size;
	return index;
}
//找到k关键字index,如果未找到,则返回所在孩子节点index
unsigned BTree::find_index(BNode* T, ElemType x)
{
	unsigned i = 0;
	while (i < T->size && T->key[i] < x)
		++i;
	return i;
}

//计算T树结点个数
int BTree::node_num(BNode* T)
{
	int re = T->size;//当前节点关键字个数
	if(!T->is_leaf)
		for (int i = 0; i <= T->size; ++i)//孩子节点关键字个数
			re += node_num(T->child[i]);
	return re;
}

//查询x关键字的排名
int BTree::node_rank(ElemType x)
{
	int rank = 0;
	BNode* curr = root;
	while (true)
	{
		int index = find_index(curr, x);
		if (index != curr->size && x == curr->key[index])//如果找到
		{
			if (!curr->is_leaf)//如果不是叶子节点需要加上左侧各子树结点个数
				for (int i = 0; i <= index; ++i)
					rank += node_num(curr->child[i]);
			rank += (index + 1);//最后加上当前结点x前关键字个数
			return rank;
		}
		else
		{
			rank += index;
			if (!curr->is_leaf)//如果不是叶子节点还要往下找,同时加上左侧各子树节点个数
			{
				for (int i = 0; i < index; ++i)
					rank += node_num(curr->child[i]);
				curr = curr->child[index];
			}
			else//如果没找到,且已经到了叶子节点,则就是未找到
				return 0;
		}
	}
	return rank;
}

//查询排名为rank的关键字
ElemType BTree::search_rank(int rank)
{
	BNode* curr = root;//从根节点开始
	int curr_rank = 0;
	while (true)
	{
		if (!curr->is_leaf)//如果不是叶子节点
		{
			for (int i = 0; i <= curr->size; ++i)
			{
				int temp_rank = rank;
				temp_rank += node_num(curr->child[i]);//计算i子树节点个数
				++temp_rank;//加上i关键字个数
				if (temp_rank == rank)
					return curr->key[i];
				else if (temp_rank > rank)//如果不是要在i子树中查找,rank不变
					curr = curr->child[i];
				else
					curr_rank = temp_rank;
			}
		}
		else
		{
			for (int i = 0; i < curr->size; ++i)
			{
				++curr_rank;
				if (curr_rank == rank)
					return curr->key[i];
			}
		}
	}
	return INT_MAX;//没找到
}

//查询x的前驱结点
ElemType BTree::prev_node(ElemType x)
{
	ElemType ans = INT_MIN;
	std::queue<BNode*>Q;
	Q.push(root);
	while (!Q.empty())
	{
		BNode* tp = Q.front();
		Q.pop();
		int index = find_index(tp, x);
		for (int i = 0; i < index; ++i)
			if (tp->key[i]<x && tp->key[i]>ans)
				ans = tp->key[i];
		//if (index != tp->size && tp->key[index] != x)
		if(!tp->is_leaf)
			Q.push(tp->child[index]);
	}
	return ans;
}
ElemType BTree::next_node(ElemType x)
{
	ElemType ans = INT_MAX;
	std::queue<BNode*>Q;
	Q.push(root);
	while (!Q.empty())
	{
		BNode* tp = Q.front();
		Q.pop();
		int index = find_index(tp, x);
		for (int i = index; i < tp->size; ++i)
			if (tp->key[i]>x && tp->key[i]<ans)
				ans = tp->key[i];
		if (!tp->is_leaf)
		{
			if (index != tp->size && tp->key[index] == x)
				Q.push(tp->child[index + 1]);
			else
				Q.push(tp->child[index]);
		}
	}
	return ans;
}

int main()
{
    int n;//操作数
    cin >> n;
    BTree my_tree(20);
    while (n--)
    {
        int choice, x;
        cin >> choice >> x;
        switch (choice)
        {
        case 1:
            my_tree.insert(x);
            break;
        case 2:
            my_tree.eraser(x);
            break;
        case 3:
            cout << my_tree.node_rank(x) << endl;
            break;
        case 4:
            cout << my_tree.search_rank(x) << endl;
            break;
        case 5:
            cout << my_tree.prev_node(x) << endl;
            break;
        case 6:
            cout << my_tree.next_node(x) << endl;
            break;
        default:
            break;
        }
    }
	return 0;
}


2021/12/21 14:26
加载中...