森林和二叉树的转换 (孩子兄弟表示法+数组模拟

#include <iostream>
#include<queue>
#include<algorithm>
#pragma warning(disable:4996)
//#define father 3
using namespace std;
int k, m, n;
int Q, op; int flag;
int trees[5105][3];
int btree[5105][3];
int* troot; int btroot;
bool cmp(int a,int b) {
	return a < b;
}
int re=0;
void test0(int root) {
	if (root == -1) {
		return ;
	}
	// << root <<" ";
	re = re ^ root;
	test0(trees[root][1]);
	test0(trees[root][2]);
}
void test1(int root) {
	if (root == -1) {
		return;
	}
	// << root <<" ";
	re = re ^ root;
	test1(btree[root][1]);
	test1(btree[root][2]);
}
void pre() {
  for(int i=0;i<5105;i++)
	  for (int j = 0; j < 3; j++)
	  {
		  trees[i][j] = -1; btree[i][j] = -1;
	  }
}
void deleteroot(int node) {
	int mark = 0;
	for (int j = 0; j < m; j++)if (troot[j] == node)mark = j;//troot = troot + 1;
	while (mark < m - 1) {
		troot[mark] = troot[mark + 1]; mark++;
	}troot[mark] = -1;
	m--;
}
void testout() {
	for (int j = 0; j < m; j++)cout << "根:" << troot[j] << " ";
	cout << endl;
	for (int j = 0; j < m; j++)
	{
		test0(troot[j]); cout << endl;
	}
}
void clone(int kind) {
	if (kind == 1) {//将二叉树数组复制为森林
		for (int i = 0; i < 5105; i++)
			for (int j = 0; j < 3; j++)
				trees[i][j] = btree[i][j];
	}
	if (kind == 0) {//森林复制为二叉树
		for (int i = 0; i < 5105; i++)
			for (int j = 0; j < 3; j++)
				btree[i][j]= trees[i][j];
	}
}
void trans(int flag) {
if (flag == 0) {//森林转二叉树
	sort(troot, troot + m, cmp);
	int p = troot[0];
	for (int i = 1; i < m; i++) {
		trees[p][2] = troot[i];
		p = troot[i];
	}
	for (int j = 1; j < m; j++)troot[j] = -1;
	m = 1; btroot = troot[0];
	//testout();
	clone(0);

}
else if (flag == 1) {//二叉树转森林
	int p = btroot; int pp =p;
	//test1(btroot);
	while (p != -1) {
		pp = p;
		troot[m - 1] = pp;
		p = btree[p][2];
		btree[pp][2] = -1;
		m++;
	}
	m--;
	clone(1);
	sort(troot, troot + m, cmp);
	//testout();

}

}
void insertbt() {
	int ops, fa, node;
	cin >> ops >> fa >> node;
	if (ops == 0) {
		btree[fa][2] = node;
	}
	if (ops == 1) {
		btree[fa][1] = node;
	}
}
void meun() {
	pre();
	cin >> k >> m >> n;
	troot = new int[m+1000]; for (int i = 0; i <m+1000; i++)troot[i] = -1;
	//cout << trees[11][1] << "  vdfv  " << trees[11][2] << endl;
	if (k == 0) {
		flag = 0;
		for (int i = 0; i < m; i++)cin >> troot[i]; 
		for (int i = 0; i < n; i++) {
			int a, b, * nodes;
			cin >> a >> b;  nodes = new int[b + 1]; for (int j = 0; j < b; j++)nodes[j] = -1; nodes[b] = -1;
			for (int j = 0; j < b; j++)cin >> nodes[j];
			sort(nodes, nodes + b, cmp);
			if (b != 0) {
				trees[a][0] = 0;
				trees[a][1] = nodes[0];
				int p = 1; int j = nodes[0];
				while (nodes[p] != -1) {
					trees[j][0]=0;
					trees[j][2] = nodes[p];
					j = nodes[p];     p++;
				}
			}
			else {
				trees[a][0] = 0;
			}
		}
	}
	if (k == 1) {
		flag = 1;
		cin >> btroot;
		for (int i = 0; i < n; i++) {
			int a, l, r;
			cin >> a >> l >> r;
			btree[a][1] = l; if (l != -1)btree[l][0] = a;
			btree[a][2] = r; if (r != -1)btree[r][0] = a;
		}
	}


	cin >> Q;
	for (int i = 0; i < Q; i++) {
		cin >> op;
		switch (op) {
		case 1:
		{
			int fa, node;
			cin >> fa >> node;
			if (fa == -1) {  trees[node][0] = 0; troot[m] = node; m++; }//插入根节点
			else//非根节点
			{
				trees[node][0] = 0;
				int p = trees[fa][1];
				if (node <= p || p == -1) {//若小于等于孩子节点||没孩子 则成为该fa的孩子
					int ppp = trees[fa][1];
					trees[fa][1] = node;
					trees[node][2] = ppp;
				}
				else {
					int pp=0;
					while (node > p&& p != -1) {
						pp = p;
						p = trees[p][2];
					}
					trees[pp][2] = node;
					trees[node][2] = p;
				}
			}
			sort(troot, troot + m, cmp);
			break;
		}
		case 2:
		{
			int fa, node; cin >> fa >> node;
			if (fa == -1) {//删掉根节点  则其子节点都会成为新树
				deleteroot(node);
				if (trees[node][1] != -1) {//删掉的根有孩子
					int p = 0;
					p = trees[node][1]; int pp;
					while (p != -1) {
					    troot[m] = p;
						pp = p;
						p = trees[p][2];
						trees[pp][2] = -1;
						m++;
					}
					trees[node][0] = -1; trees[node][1] = -1; trees[node][2] = -1;
					sort(troot, troot + m, cmp);
				}
				else {//没孩子
					trees[node][0] = -1; trees[node][1] = -1; trees[node][2] = -1;
				}
			}
			else if (fa != -1) {//待删除的点不是根节点 其所有孩子都成为新的树
				if (node == trees[fa][1]) {  //分情况 1待删除点是其父节点第一个孩子 2其他孩子//我叫白小飞 我遭遇了无法想象的bug,我要活下去,并且干掉更多的bug。awsl
					int p = node; trees[fa][1] = trees[p][2];//父节点孩子改变为待删除节点兄弟;
					if (trees[p][1]!=-1) {//待删除节点有孩子
						int pp = 0; pp = trees[p][1]; int ppp;
						while (pp != -1) {
							troot[m] = pp;
							ppp = pp; 
							pp = trees[pp][2];
							trees[ppp][2] = -1;
							m++;
						}
						sort(troot, troot + m, cmp);
						trees[p][0] = -1; trees[p][1] = -1; trees[p][2] = -1;
					}
					else if(trees[p][1]==-1) {//待删除节点无孩子  删除该节点
						trees[p][0] = -1; trees[p][1] = -1; trees[p][2] = -1;
					}
				}
				else {                        //分情况 2其他孩子
					int p = trees[fa][1]; int pp=0;
					while (p!=-1&&p != node) {
						pp = p; p = trees[p][2];
					}
					trees[pp][2] = trees[p][2];//p此时为待删除节点
					if (trees[p][1] != -1) {//待删除节点有孩子
						int pp = 0;pp= trees[p][1]; int ppp;
						while (pp != -1) {
							troot[m] = pp;
							ppp = pp;
							pp = trees[pp][2];
							trees[ppp][2] = -1;
							m++;
						}
						sort(troot, troot + m, cmp);
						trees[p][0] = -1; trees[p][1] = -1; trees[p][2] = -1;
					}
					else if (trees[p][1] == -1) {//待删除节点无孩子  删除该节点
						trees[p][0] = -1; trees[p][1] = -1; trees[p][2] = -1;
					}
					
				}
			}
			break;
		}
		case 3:
		{
			int a, b; cin >> a >> b;
			deleteroot(b);
			int p = trees[a][1]; int pp=0;
			if (p == -1)trees[a][1] = b;
			else {
				while (p < b && p != -1) {
					pp = p;
					p = trees[p][2];
				}
				if (p == trees[a][1]) {
					trees[a][1] = b;
					trees[b][2] = p;
				}
				else {
					trees[pp][2] = b;
					trees[b][2] = p;
				}

			}
			break;
		}
		case 4:
		{
			trans(flag);
			flag = (flag + 1) % 2;
			//testout();
			break;
		}
		case 5:
		{
			insertbt();
			break;
		}
		case 6:
		{
			if (flag == 0) {
				sort(troot, troot + m, cmp);
				for (int j = 0; j < m; j++)
				{
					re = 0;
					test0(troot[j]);
					cout << re << " ";
				}
				cout << endl;
			}
			else if (flag == 1) {
				re = 0;
				test1(btroot);
				cout << re << endl;
			}
			break;
		}


		}
	}

}




int main()
{

	//freopen("input13.txt", "r", stdin); 
	//freopen("output13.txt", "w", stdout); 
	meun();
	//fclose(stdin);
//fclose(stdout);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值