数据结构-树

树的基本操作

小编参加第二十一次CSP认证考试时,被第三题的关于树的题卡了好久之后,下定决心对树进行系统的学习。小编经过赛后的练习,确定了自己感觉十分顺手的树的构建方法。

树的数据结构

小编比较喜欢,并且用起来十分顺手的树的数据结构如下(小编对用指针一向不是很擅长,因此选择了用vector数组来代替指针存储孩子的节点):

struct Node
{
	int father; //树节点的父亲节点
	int value;  //树节点的值
	vector<int> child; //树节点的孩子节点
}node[/*根据题目最大节点数来填写*/];

结构体Node代表着树中任意一个节点,存储着节点的信息,例如:节点的父亲节点、节点的数值以及节点的孩子节点。这些都是节点的基本信息,做题的时候,可以根据题目要求,在其中加入更多的其他信息,以满足题目的要求。

树的构建

以结构体数组为基础的数据结构相比于利用指针创建的树,虽然更耗空间,但是一部分操作却更加简单、容易理解,比如树的构建。

  1. 无向树的构建
    假如输入的形式是:(u , v),其中u , v分别代表边上两个节点的序列号,利用如上的数据结构,只需要如下两条语句即可完成对无向树的创建。

     node[u].child.push_back(v);
     node[v].child.push_back(u);
    
  2. 有向树的构建
    有向树的创建类似于无向树的创建,假如输入的形式是:(u , v) ,其中代表从节点u到节点v之间有一个树的边连接着,u是v的父节点,v是u的孩子节点。

     node[u].child.push_back(v);
    

寻找所有叶节点

叶节点相对于其他种类的树节点,具有一个特殊的性质就是其没有孩子节点,因此利用这个特殊的性质即可找到所有叶节点。任意一个节点的孩子节点的数量可以通过节点数据结构中vector数组child的元素数量得到。

for (i = 1; i <= n; i++)
{
	if (node[i].child.size() == 0)
	{
		/*   对叶子节点的操作   */
	}	
}

无向树转有向树

无向树与有向树都具有树的特性,但是无向树并不包含有父子节点的关系,有一些关于树的算法题目,题目给的输入无向树的形式,但是题目经过分析,可以通过将无向树转换成有向树,以此来大幅度提升效率,同时不会对结果产生影响。

  1. 无向树可以通过上面的方法快速创建。
  2. 无向树是没有根节点的,但是要想转成有向树,则必须确定一个根节点。而从无向树中随意抽出一个节点,都可以当作有向树的根节点,用这个方法的时候,要仔细分析确定如此操作不会对题目的结果产生影响。
  3. 无向树的边上的两个节点是双向连接的,要想转换成有向树,可以依据已经建好的无向树,重新创建一个有向树。小编从根节点出发,利用广度优先搜索(BFS)的思想,进行有向树的创建。代码如下:
     memset(vis, 0, sizeof(vis));
     q.push(1);
     vis[1] = 1;
     while (!q.empty())
     {
     	int top = q.front();
     	q.pop();
     	for (j = 0; j < node_temp[top].child.size(); j++)
     	{
     		if (vis[node_temp[top].child[j]] == 0)
     		{
     			q.push(node_temp[top].child[j]);
     			vis[node_temp[top].child[j]] = 1;
     			node[top].child.push_back(node_temp[top].child[j]); //添加孩子节点
     			node[node_temp[top].child[j]].father = top;  //指定孩子节点的父节点
     		}
     	}
     }
    
  4. 上述代码中,node_temp是原本存储无向图的数据结构,而node是存储转换得到的有向图的数据结构。代码中以序号为1的节点为有向树的根节点。

寻找节点的所有父节点

在树中,除了根节点,每一个节点都是有父节点的,一些树的基本修改操作可以通过修改其所有父节点(包括父节点的父节点)来快速完成。在创建树的时候,除了根节点,其他节点的父节点都指向树中的一个节点序号,只有根节点的父节点是没有指向的,因此,将其初始化为-1,以实现对根节点的识别。代码如下(假设要遍历序号为u的节点的所有父节点):

int father = node[u].father;
while (father != -1)
{
	/* 对父节点的操作 */
	father = node[father].father;
}

树的相关练习题

1.洛谷T160512 G - 森林

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值