定义

树是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由 n(n>0) 个有限节点组成一个具有层次关系的集合。。

二叉搜索树(Binary Search Tree,简称 BST)是一种很常用的的二叉树。它的定义是:一个二叉树中,任意节点的值要大于等于左子树所有节点的值,且要小于等于右边子树的所有节点的值。

如下就是一个符合定义的 BST:

算法模板

void traverse(TreeNode root) {
// root 需要做什么?在这做。
// 其他的不用 root 操心,抛给框架
traverse(root.left);
traverse(root.right);
}

在二叉树框架之上,扩展出一套 BST 遍历框架:

void BST(TreeNode root, int target) {
if (root.val == target)
// 找到目标,做点什么
if (root.val < target)
BST(root.right, target);
if (root.val > target)
BST(root.left, target);
}

前序遍历(递归):

List<int> preorder(TreeNode root) {
List<int> ans = new List<int>();
if (root == null) {
return ans;
} ans.Add(root.Val);
ans.AddRange(preorder(root.Left));
ans.AddRange(preorder(root.Right));
return ans;
}

中序遍历(递归):

List<int> inorder(TreeNode root) {
List<int> ans = new List<int>();
if (root == null) {
return ans;
} ans.AddRange(preorder(root.Left));
ans.Add(root.Val);
ans.AddRange(preorder(root.Right));
return ans;
}

后序遍历(递归):

List<int> postorder(TreeNode root) {
List<int> ans = new List<int>();
if (root == null) {
return ans;
} ans.AddRange(preorder(root.Left));
ans.AddRange(preorder(root.Right));
ans.Add(root.Val);
return ans;
}

前序遍历(迭代/栈):

class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res; //保存结果
stack<TreeNode*> call; //调用栈
if(root!=nullptr) call.push(root); //首先介入root节点
while(!call.empty()){
TreeNode *t = call.top();
call.pop(); //访问过的节点弹出
if(t!=nullptr){
if(t->right) call.push(t->right); //右节点先压栈,最后处理
if(t->left) call.push(t->left);
call.push(t); //当前节点重新压栈(留着以后处理),因为先序遍历所以最后压栈
call.push(nullptr); //在当前节点之前加入一个空节点表示已经访问过了
}else{ //空节点表示之前已经访问过了,现在需要处理除了递归之外的内容
res.push_back(call.top()->val); //call.top()是nullptr之前压栈的一个节点,也就是上面call.push(t)中的那个t
call.pop(); //处理完了,第二次弹出节点(彻底从栈中移除)
}
}
return res;
}
};

中序遍历(迭代/栈):

class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> call;
if(root!=nullptr) call.push(root);
while(!call.empty()){
TreeNode *t = call.top();
call.pop();
if(t!=nullptr){
if(t->right) call.push(t->right);
call.push(t); //在左节点之前重新插入该节点,以便在左节点之后处理(访问值)
call.push(nullptr); //nullptr跟随t插入,标识已经访问过,还没有被处理
if(t->left) call.push(t->left);
}else{
res.push_back(call.top()->val);
call.pop();
}
}
return res;
}
};

后序遍历(迭代/栈):

class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> call;
if(root!=nullptr) call.push(root);
while(!call.empty()){
TreeNode *t = call.top();
call.pop();
if(t!=nullptr){
call.push(t); //在右节点之前重新插入该节点,以便在最后处理(访问值)
call.push(nullptr); //nullptr跟随t插入,标识已经访问过,还没有被处理
if(t->right) call.push(t->right);
if(t->left) call.push(t->left);
}else{
res.push_back(call.top()->val);
call.pop();
}
}
return res;
}
};

要点

  • 二叉树算法设计的总路线:把当前节点要做的事做好,其他的交给递归框架,不用当前节点操心。
  • 如果当前节点会对下面的子节点有整体影响,可以通过辅助函数增长参数列表,借助参数传递信息。
  • 删除二叉搜索树的节点有三种情况:
    1. A 恰好是末端节点,两个子节点都为空,那么它可以当场去世了
    2. A 只有一个非空子节点,那么它要让这个孩子接替自己的位置。
    3. A 有两个子节点,麻烦了,为了不破坏 BST 的性质,A 必须找到左子树中最大的那个节点,或者右子树中最小的那个节点来接替自己。

实战题目

1.树的遍历

2.树的操作

参考资料

树(Tree)解题总结的更多相关文章

  1. 【九度OJ】题目1176:树查找 解题报告

    [九度OJ]题目1176:树查找 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1176 题目描述: 有一棵树,输出某一深度的所有节点 ...

  2. 【LeetCode】297. Serialize and Deserialize Binary Tree 解题报告(Python)

    [LeetCode]297. Serialize and Deserialize Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode ...

  3. 【LeetCode】331. Verify Preorder Serialization of a Binary Tree 解题报告(Python)

    [LeetCode]331. Verify Preorder Serialization of a Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https:/ ...

  4. 树(tree)

    树(tree)[题目描述]从前在森林里面有一棵很大的树,树上住着很多小动物.树上有

  5. JS--插件: 树Tree 开发与实现

    日常在Web项目开发时,经常会碰到树形架构数据的显示,从数据库中获取数据,并且显示成树形.为了方便,我们可以写一个javascript的一个跨浏览器树控件,后续可以重复使用.本节分享一个自己开发的JS ...

  6. 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)

    [LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...

  7. 【LeetCode】109. Convert Sorted List to Binary Search Tree 解题报告(Python)

    [LeetCode]109. Convert Sorted List to Binary Search Tree 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id ...

  8. 【LeetCode】236. Lowest Common Ancestor of a Binary Tree 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  9. 【LeetCode】99. Recover Binary Search Tree 解题报告(Python)

    [LeetCode]99. Recover Binary Search Tree 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/p ...

  10. 【LeetCode】662. Maximum Width of Binary Tree 解题报告(Python)

    [LeetCode]662. Maximum Width of Binary Tree 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.co ...

随机推荐

  1. Python基础教程 (第2+3 版)打包pdf|内附网盘链接提取码

                <Python基础教程 第3版>包括Python程序设计的方方面面:首先,从Python的安装开始,随后介绍了Python的基础知识和基本概念,包括列表.元组.字符 ...

  2. 电脑小知识:Windows 10是用什么语言写的?到底有多少行代码?

    这是微软的内核工程师 Axel Rietschin在Quora的一个回答. Windows 10 的code base 和Windows 8.x , 7 , Vista , XP , 2000 和Wi ...

  3. Multiple dex files define解决记录

    引用多个library时经常会遇到Multiple dex files define错误,最常见的是support库多次定义,此时可用以下gradle命令来查看工程的引用树: gradlew -q d ...

  4. UIPickView的简单使用

    好记性不如烂笔头,勤做笔记. 摘要: 1.UIPickVIew 几个重要的属性 (1)datePickerMode UIDatePickerModeTime, // Displays hour, mi ...

  5. ios textView跟随键盘的移动

    实现效果: textview 能够跟随键盘的移动而移动 效果图如下: 下边贴上主要的代码: 1.创建textview @interface ViewController ()<UITextVie ...

  6. Java并发--基础知识

    一.为什么要用到并发 充分利用多核CPU的计算能力 方便进行业务拆分,提升应用性能 二.并发编程有哪些缺点 频繁的上下文切换 时间片是CPU分配给各个线程的时间,因为时间非常短,所以CPU不断通过切换 ...

  7. Linux下gcc/g++中-I(i的大写)、-L和-l

    -I(i的大写)include头文件非标准库中存在的也不是在当前文件夹下的,需要将地址用-i(大写)包含例:-I /home/src/-L用到的函数或操作非标准库下的,需要将库存在的地址用-L包含,库 ...

  8. day27:异常&反射

    目录 认识异常处理 1.程序错误的种类    2.异常的分类 3.AssertionError(断言assert语句失败) 异常处理的基本语法 1.异常处理的基本语法 2.带有分支的异常处理 3.处理 ...

  9. C#LeetCode刷题之#155-最小栈(Min Stack)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4020 访问. 设计一个支持 push,pop,top 操作,并能 ...

  10. C#LeetCode刷题之#414-第三大的数(Third Maximum Number)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3710 访问. 给定一个非空数组,返回此数组中第三大的数.如果不存 ...