树的基本定义与基本二叉树的基本操作(Binary tree)

树的基本定义与基本二叉树的基本操作

by @WRuperD

一.树的基本定义

可以先浏览一下这个。

和这个

蒟蒻口才不好,这里引用一下dalao @Neon090426 的感性理解

(下图就是一棵树)

可以这么理解:

  1. 树: 一个群
  2. 根: 群主
  3. 节点 \(A\): 编号为 \(A\)的群成员
  4. \(A\)的儿子: 被\(A\)拉进群的群成员 (例: 3是1的儿子)
  5. \(A\)的父亲: 把\(A\)拉进群的群成员 (例: 1是3的父亲)
  6. \(A\)的祖先: \(A\)\(A\)的父亲、 \(A\)父亲的父亲、 \(A\)父亲的父亲的父亲...
  7. \(A\)的后代: \(A\)\(A\)的儿子、 \(A\)儿子的儿子、 \(A\)儿子的儿子的儿子...
  8. 叶子节点: 没有儿子的节点 (例: 10号节点)
  9. A的深度: 从根遍历到\(A\)需要经过的点数 (例: 7的深度为2)
  10. 左子树:对于一个二叉树的非叶子结点,

而在所有树中,oi最常用的就是二叉树,以下将重点讲解二叉树。

二.树的存储

对于一个树的存储,有许多种方式

1.直接存

开一个大数组数组。
这里设为bt(即Binary Tree)

如图:

设树根为1, 对于每个非叶子节点,设这个节点的编号为\(i\) , 则把其左子树存在\(2*k\), 右子树存在\(2*k+1\).

这里就先不给标程了,毕竟不怎么常用,为什么后面再讲。。。

2.左右儿子法

定义一个结构体名叫node,表示一个树的节点,结构体里面定义两个变量left和right,分别表示其的左右儿子的编号。这样就能够顺着跟运用dfs遍历整个树了。

const int MAXN = 1000+10;
struct node
{
	int left, right;
};	node bt[MAXN];

细心的读者可能会发现,这样实现出来的二叉树很难从叶子结点往上搜索。

所以我们可以再在结构体中记录一下他的父亲的信息。

3.总结

先咕着。。。。

三.树的遍历

想必读者读到这应该和我一样:

不着急,我们再来看看树的遍历与实现。

1.前序遍历

别考过csp初赛的应该都知道这是一种什么样的操作。

其实前序就是对二叉树的一种遍历方式。

这里引用一下百度的说法:

前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。

好吧,貌似并不是特别清晰。

举个栗子:

如图:

还是这颗树。

先序遍历的顺序是:

\(1 - 2 - 4 - 5 - 3 - 6 - 7\)

请读者思考一下下图的前序遍历是什么:

公布答案:

\(1 - 2 - 3 - 6 - 4 - 8 - 5 - 7 - 9\)

如何遍历呢?

运用dfs按照顺序从根节点开始遍历整棵树。

试着实现一下吧!

\——————华丽分割线————————/

题解:

首先上文说了,存储左右儿子:

struct node{
	int left, right; 
}; node a[15] = {0,0};

输入:

int n;
	cin>>n;
	for(int i = 1; i <= n; i++)
	{
		cin>>a[i].left>>a[i].right;
	}

然后,dfs遍历整个树。

由于是前序遍历,遍历到哪就输出那的编号:

void dfs(int p)//p表示编号

	cout<<p<<" ";

然后,判断是不是叶子节点:是的话就return:

if(a[p].left == 0 and a[p].right == 0)		return ;

再判断有没有右儿子,有就遍历过去;

if(a[p].left)	dfs(a[p].left);

再判断有没有左儿子,有就遍历过去;

if(a[p].right)	dfs(a[p].right);

回溯;

return ;

连起来:

#include<iostream>
#include<algorithm>
using namespace  std;

struct node{
	int left, right; 
}; node a[15] = {0,0};

void dfs(int p)
{
	cout<<p<<" ";
	if(a[p].left == 0 and a[p].right == 0)		return ;
	if(a[p].left)	dfs(a[p].left);
	if(a[p].right)	dfs(a[p].right);
	return ;
}

int main()
{
	int n;
	cin>>n;
	for(int i = 1; i <= n; i++)
	{
		cin>>a[i].left>>a[i].right;
	}
	dfs(1);
	return 0;
 } 

完美结束!!!

posted @ 2021-12-04 12:48  WRuperD  阅读(109)  评论(0编辑  收藏  举报

本文作者:DIVMonster

本文链接:https://www.cnblogs.com/guangzan/p/12886111.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

这是一条自定义内容

这是一条自定义内容