二叉搜索树

二叉搜索树——算法导论(14)

拥有回忆 提交于 2020-01-30 05:39:41
1. 什么是二叉搜索树 顾名思义,二叉搜索树是以一棵二叉树来组织的。如下图,这样的一棵树可以使用一个链表数据结构来表示,其中的每一个节点是一个对象。除了key和卫星数据之外,每个节点还包含属性left(左孩子)、right(右孩子)、和p(双亲)(若不存在,则值为NIL)。 二叉搜索树中的关键字总是以满足 二叉搜索树性质 的方式存储: 设x是二叉搜索树的一个节点。如果y是x左子树中的一个节点,那么y.key≤x.key。如果y是x右子树中的一个节点,那么y.key≥x.key。 二叉搜索树性质允许我们使用一种简单的递归算法来按一定的顺序输出二叉搜索树中的所有关键字。我们常用的有 先序遍历 (输出的子树根的关键字位置位于左子树关键字和右子树关键字之间)、 中序遍历 、 后序遍历 。 下面给出先序遍历的递归算法: 我们可以证明:遍历一棵有n个节点的二叉搜索树需要花费θ(n)的时间(证明略)。 2. 查询二叉搜索树 (1) 这一小节,我们来讨论二叉搜索树的诸如:SEARCH,MINIMUM,MAXIMUN,SUCCESSOR,PERDECESSOR操作。 (2) search 我们使用如下一种算法去查询一棵二叉搜索树。该方法要求输入一个指向根节点的指针x和待查找的关键字k;输出为指向关键字为k的节点的指针(若存在。否则输出NIL)。 我们很容易知道,该查询算法的时间为O(h)

最优二叉搜索树—动态规划

天涯浪子 提交于 2020-01-28 15:58:22
最优二叉搜索树是建立在搜索树的基础上的一种最优解,一开始我也很纠结为什么会有查找不成功和查找成功的概念,后来才开始明白后来懂了如何去做,如果这点还没有明白那很难去懂什么是最优二叉搜索树,下面按照题目讲解主要内容: 我们先来声明一下如何求二叉搜索树的权重 形状1的平均查找次数 形状2的平均查找次数 计算的方程 知道了如何计算平均查找次数,我们下面求解一下如何求解最优二叉搜索树问题 将四个合起来 拼成一个个基本的子树暂时命名为a1,a2,a3 a1和a2合并有两种情况 计算得出第一种权重较小,故选择第一种形状为T[1][2] 同理计算出T[2][3]应该为第一种模型 这是最终有a1和a2以及a2和a3形成的最小二叉搜索树的子树 当我们求解T[1][3]时,实际上我们求解的是由T[1][2]与a3构成的,以及a1与T[2][3]构成的其中找到最优解 得出最优解由形状一取得 这是动态规划的动态矩阵以及状态转移方程 来源: CSDN 作者: 李小白努力努力努力ing 链接: https://blog.csdn.net/lixindayup/article/details/104098907

700. 二叉搜索树中的搜索

∥☆過路亽.° 提交于 2020-01-28 11:22:09
解题思路: 1.树为null时,返回null 2.要找的值就是根节点的值时,直接返回root 3.要找的值小于当前节点的值时,递归向左判断 4.要找的值大于当前节点的值时,递归向右判断 class Solution { public TreeNode searchBST(TreeNode root, int val) { if(root==null){ return root; } //前序遍历 if(root.val==val){ return root; } //向左遍历 if(root.val>val){ return searchBST(root.left, val); } //向右遍历 else{ return searchBST(root.right, val); } } } 来源: CSDN 作者: 我就是个渴望成长的小菜鸡 链接: https://blog.csdn.net/junjunjiao0911/article/details/104070602

《剑指offer》 二叉搜索树的第k个节点(java)

杀马特。学长 韩版系。学妹 提交于 2020-01-27 22:32:10
题目描述 给定一棵二叉搜索树,请找出其中的第k小的结点。例如,(5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。 解题思路 首先得搞明白二叉搜索树是个啥,下面是我找到的对于二叉搜索树的定义。 二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。 如果还不怎么明白二叉搜索树是啥,可以看看下面这张图,左节点<根节点<右节点。 题目是让寻找第k小的节点,那么就可以先遍历二叉搜索树的左子树的左节点,再遍历左子树的根节点然后是左子树的右节点;左子树完了,再遍历右子树,一直到找到第k小的节点。左-中-右的遍历顺序就是我们学的中序遍历,因此这个题可以用中序遍历来做。每遍历一个非空的节点,k–,一直到我们要找的那个节点为止,k正好是0。 这个题需要注意的是,k是变化的,一开始我直接用k当作变量传进参数去了,结果总是有点意外,于是整了一个成员变量。如果是C++实现的话,使用int &k传到函数里面就行了。 AC代码 /* public class TreeNode { int val = 0; TreeNode left = null;

【LeetCode算法修炼指南】—— 96.不同的二叉搜索树

末鹿安然 提交于 2020-01-26 23:34:14
1. 题目 原题链接 给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3 1.1. 要点 掌握二叉搜索树 假定每一个数字为根结点,并将剩余的数组分配到左右两边继续构造子树。 此时每一个根结点构成二叉树的数量总和为 左边*右边 。 1.2. 递归 这个版本的实现也是勉勉强强的通过的LeetCode,但是性能非常差。 但是毕竟用了二叉树递归特性来实现,所以还是体会一下吧。 1.2.1. 代码片段 func numTrees ( n int ) int { if n == 0 { return 0 } var numTreesMap = make ( map [ string ] int , 0 ) //如果不用一个hash map来记录已经运算过的结果,直接就导致运算超时。 return numTreesHelper ( 1 , n , numTreesMap ) //注意边界位置[1...n] } func numTreesHelper ( left , right int , numTreesMap map [ string ] int ) int { if left

LeetCode 98 验证二叉搜索树

橙三吉。 提交于 2020-01-26 09:16:14
题目 给定一个二叉树,判断其是否是一个有效的二叉搜索树。 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数。 节点的右子树只包含大于当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。 示例 1: 输入: 2 / \ 1 3 输出: true 示例 2: 输入: 5 / \ 1 4 / \ 3 6 输出: false 解释: 输入为: [5,1,4,null,null,3,6]。 根节点的值为 5 ,但是其右子节点值为 4 。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/validate-binary-search-tree 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 题解 中序遍历,组成一个list,检查该list是否有序,若有序则为二叉搜索树 class Solution { public boolean isValidBST ( TreeNode root ) { List < Integer > list = inorder ( root ) ; if ( isSorted ( list ) ) return true ; return false ; } List < Integer > inorder ( TreeNode root ) { if ( root

前端数据结构之二叉搜索树

和自甴很熟 提交于 2020-01-22 17:30:15
欢迎阁下光临我的github前端知识汇总 https://github.com/JimmyLLLL/js 如果您可以慷慨赠予我星星,在下不胜感激! 百度百科:二叉搜索树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的 二叉树 : 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为 二叉排序树 。 二叉搜索树个人解读:比它小放左边,比它大放右边 class Node{ constructor(value){ this.value = value this.left = null this.right = null } } //插入节点函数的辅助函数,用来递归,递归的内容对初学者来讲有点难,但是相信我,时间可以消磨一切,一遍又一遍,你可以看懂的!我也在此陪你,加油~ function insertNodeHelper(node,newNode){ if(node.value < newNode.value){ if(node.right===null){ node.right = newNode }else{ insertNodeHelper(node.right,newNode) } }else{ if(node.left=

【每日刷题】二叉搜索树中的插入操作

那年仲夏 提交于 2020-01-21 23:16:58
题目地址 https://leetcode-cn.com/problems/insert-into-a-binary-search-tree/ 题目描述:二叉搜索树中的插入操作 给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 保证原始二叉搜索树中不存在新值。 注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。 例: 给定二叉搜索树: 4 / \ 2 7 / \ 1 3 以及待插入的值: 5 你可以返回这个二叉搜索树: 4 / \ 2 7 / \ / 1 3 5 或者这个树也是有效的: 5 / \ 2 7 / \ 1 3 \ 4 解答 从题目描述中可以看出,存在多种不同的插入方式。 这里采用的方法是:依据 BST 的定义,首先找到待插入结点适合的位置,然后将结点插入其中。 /** * 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 : TreeNode

判断是否是二叉搜索树

我们两清 提交于 2020-01-20 21:52:48
二叉查找树 二叉查找树(Binary Search Tree),(又: 二叉搜索树 ,二叉排序树)它或者是一棵空树,或者是具有下列性质的 二叉树 : 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为 二叉排序树 解题思路: 利用中序遍历,如果是二叉搜索树,其中序遍历的结果一定是升序的,只需要将中序遍历稍加改变,在每个元素出栈时与前一个元素比较,看其是否大于前一个元素。 import java.util.Stack; /** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ //利用中序遍历 public class Solution { public boolean isValidBST(TreeNode root) { //空树返回ture,空树是二叉搜索树 if(root == null) return true; Stack<TreeNode> stack = new Stack<TreeNode>(); //与前序遍历不同,一开始先不入栈

剑指offer——java刷题总结【三】

最后都变了- 提交于 2020-01-19 03:36:07
Note 题解汇总: 剑指offer题解汇总 代码地址: Github 剑指offer Java实现汇总 点击目录中的题名链接可直接食用题解~ 有些解法博文中未实现,不代表一定很难,可能只是因为博主太懒```(Orz) 如果博文中有明显错误或者某些题目有更加优雅的解法请指出,谢谢~ 目录 题号 题目名称 21 栈的压入、弹出序列 22 从上往下打印二叉树 23 二叉搜索树的后序遍历序列 24 二叉树中和为某一值的路径 25 复杂链表的复制 26 二叉搜索树与双向链表 27 字符串的排列 28 数组中出现次数超过一半的数字 29 最小的K个数 30 连续子数组的最大和 正文 21、栈的压入、弹出序列 题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的) 题目分析 解法一: 设置一个指向pop数组的index指针,遍历push数组,针对每一个遍历值做如下操作: 1、将当前遍历值压入栈中; 2、查看栈顶元素和pop数组的当前弹出值是否相等,如果相等则模拟出栈操作,将stack的栈顶元素弹出,并对pop数组的指针进行后移