【4】树的基本概念、二叉树、树和森林

树的基本概念

(1) 树是由根节点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的节点,所定义的关系称为父子关系。父子关系在树的节点之间建立了一个层次结构。在这种层次结构中有一个节点具有特殊的地位,这个节点称为该树的根节点,或称为树根。
(2) 空集合也是树,称为空树。空树中没有节点;
(3) 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
(4) 节点的度:一个节点含有的子节点的个数称为该节点的度;
(5) 叶节点或终端节点:度为0的节点称为叶节点;
(6) 非终端节点或分支节点:度不为0的节点;
(7) 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
(8) 兄弟节点:具有相同父节点的节点互称为兄弟节点;
(9) 树的度:一棵树中,最大的节点的度称为树的度;
(10) 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
(11) 树的高度或深度:树中节点的最大层次;
(12) 节点的祖先:从根到该节点所经分支上的所有节点;
(13) 子孙:以某节点为根的子树中任一节点都称为该节点的子孙;
(14) 森林:由棵互不相交的树的集合称为森林。

二叉树

(1) 二叉树的定义及其主要特征
	a. 二叉树的基本形态:空二叉树、单节点二叉树、左子树、右子树
	b. 性质:
		[1] 在非空二叉树中,第i层上至多有2^(i-1) 个结点。
		[2] 深度为k的二叉树至多有2^k - 1个结点
		[3] 对任何一颗二叉树,若其叶子结点数为n0,度为2的结点数为n2,则n0 = n2 + 1。
		[4] n个结点的完全二叉树深度为:log2(n)向下取整 + 1
		[5] 二叉树的堆式存储: 节点p的左儿子:2x,右儿子:2x+1
	c. 两种特殊的二叉树
		[1] 满二叉树:一颗深度为k且有2^k-1个结点的二叉树
		[2] 如果深度为k,有n个结点的二叉树,当且仅当其每个结点都与深度为k的满二叉树中编号从1到n的结点一一对应,该二叉树称为完全二叉树
(2) 二叉树的顺序存储结构和链式存储结构
(3) 二叉树的遍历
	a. 前序遍历
	b. 中序遍历
	c. 后序遍历
	d. 根据前序 + 中序重建二叉树
(4) 线索二叉树的基本概念和构造
	对二叉树节点的指针域做如下规定:
		a. 若节点有左孩子,则Lchild指向左孩子,否则指向直接前驱;右孩子同理(后继);
		b. 增加两个标志域,Ltag表示指向的是子节点还是前驱;Rtag同理
		c. 指向前驱和后继的指针叫做线索。按照某种次序遍历,加上线索的二叉树称之为线索二叉树

已知儿子求父结点:
根据儿子求父结点
前序:根 左 右
中序:左 根 右
后序:左 右 根
当所有节点都有两个子树或者度为空时,才能根据前序和后序唯一确定一棵树否则无法确定节点时左孩子还是右孩子
在这里插入图片描述
前+中 后+中 层+中可以构造二叉树
重建二叉树
输入一棵二叉树前序遍历和中序遍历的结果,请重建该二叉树。
注意:

  • 二叉树中每个节点的值都互不相同;
  • 输入的前序遍历和中序遍历一定合法;

数据范围
树中节点数量范围 [ 0 , 100 ] [0,100] [0,100]
样例

给定:
前序遍历是:[3, 9, 20, 15, 7]
中序遍历是:[9, 3, 15, 20, 7]

返回:[3, 9, 20, null, null, 15, 7, null, null, null, null]
返回的二叉树如下所示:
    3
   / \
  9  20
    /  \
   15   7
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    unordered_map<int, int> pos;
    vector<int> preorder, inorder;
    TreeNode* build(int a, int b, int x, int y){
        if(a > b) return NULL;
        auto root = new TreeNode(preorder[a]);
        int k = pos[root->val];
        root->left = build(a + 1, a + 1 + k - 1 - x, x , k - 1);
        root->right = build(a + 1 + k - 1 - x + 1, b, k + 1, y);
        return root;
    }
    TreeNode* buildTree(vector<int>& _preorder, vector<int>& _inorder) {
        preorder = _preorder, inorder = _inorder;
        int n = inorder.size();
        for(int i = 0; i < n; i++) pos[inorder[i]] = i;
        return build(0, n - 1, 0, n - 1);
    }
};

树、森林

(1) 树的存储结构
	a. 只存父节点
	b. 邻接表存储所有子节点
	c. 左儿子右兄弟
(2) 森林F与二叉树T的转换
	a. 原树中叶子节点数 = 转换后的树中有右儿子的节点数 + 1
	b. F的前序遍历就是T的前序遍历
	c. F的后序遍历就是T的中序遍历
(3) 树和森林的遍历
	a. 前序遍历
	b. 后序遍历

左儿子右兄弟:
在这里插入图片描述
二叉树的带权路径长度
二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和,也就是每个叶结点的深度与权值之积的总和。

给定一棵二叉树 T T T,请你计算并输出它的 WPL。

注意,根节点的深度为 0 0 0

样例

输入:二叉树[8, 12, 2, null, null, 6, 4, null, null, null, null]如下图所示:
    8
   / \
  12  2
     / \
    6   4

输出:32

数据范围
二叉树结点数量不超过 1000 1000 1000
每个结点的权值均为不超过 100 100 100 的非负整数。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int dfs(TreeNode* root, int depth){
        if(!root) return 0;
        if(!root->left && !root->right) return root->val * depth;
        return dfs(root->left , depth + 1) + dfs(root->right, depth + 1);
    }
    int pathSum(TreeNode* root) {
        return dfs(root, 0);
    }
};

包含n个节点的二叉树的数量是第n个卡特兰数
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值