数据结构,二叉树搜索树(一)

简介: 本文讲解:二叉搜索树的遍历方式之查找节点。

1. 二叉搜索树的概念

二叉搜索树又称为二叉排序树,它的特点为左子树往后的所有结点都比根节点小,右子树往后的所有结点都比根节点大。根据下图来理解:

image.gif编辑

通过上图我们可以观察到,以20为根节点时左侧的所有节点都比20要小,右侧的所有节点都要比20要大。当以20的左子树18、右子树31作为根节点时也是左边节点比根节点小,右边节点比根节点大。

那么以这种结构组成的二叉树,我们就叫做二叉搜索树。因此我们能得出这些性质:

    • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
    • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
    • 它的左右子树也分别为二叉搜索树

    首先我们要知道,一个节点是由左子树,值,右子树组成,通常左子树用 left 表示,值用 val 表示,右子树用right表示。把三个部分综合起来这样就形成了一个节点,树的根节点用 root 表示因此我们可以定义一个静态内部类 TreeNode 来搭建这个节点:

    //节点结构
        static class TreeNode {
            public TreeNode left;//左子树
            public TreeNode right;//右子树
            public int val;//值
            public TreeNode(int val) {
                this.val = val;//构造方法为成员变量赋值
            }
        }
        public TreeNode root;//根节点

    image.gif

    这样节点的搭建就完成了,我们可以看到这个节点内包含的 left、val、right 这三个代表量。 下面,我们就来讲解二叉搜索树的操作:查找节点、插入节点、删除节点


    2. 二叉搜索树的操作

    2.1 查找节点

    查找二叉树的节点,我们根据二叉搜索树的性质下可以列出以下几个条件,

      1. 若根节点不为空
      2. 根节点等于要查找的节点,返回根节点
      3. 根节点大于要查找的节点,在根节点的左子树查找
      4. 根节点小于要查找的节点,在根节点的右子树查找
      5. 否则,返回null

      (1).根节点为空

      根节点为空代表这个树是不存在的,因此我们直接返回null即可:

      if(root == null) {
              return null;
          }

      image.gif


      (2).根节点等于要查找的节点

      根节点等于要查找的节点我们直接返回根节点即可,这种情况相当于一下子就找到了。因此它的时间复杂度为O(1)

      image.gif编辑

      因此,我们可以写出这样的代码:

      if(root.val == key) {
              return root;
          }

      image.gif

      root.valroot 节点值,key 是我们要查找的数据。注意,我们写代码是一步一步来写的,能实现当前的模块,就写当前的代码。最后综合起来并进行修改这样就能写出一段完整的代码。


      (3).根节点大于要查找的节点,在根节点的左子树查找

      根节点大于要查找的节点,为了满足二叉搜索树的左子树小于根节点的性质,我们要在根节点的左子树进行查找。

      image.gif编辑

      因此,我们可以写出以下代码:

      if(root.val > key) {
              root = root.left;
          }

      image.gif

      如果root.val大于我们要查找的值key,使根节点变为root的left节点。


      (4).根节点小于要查找的节点

      根节点小于要查找的节点,为了满足二叉搜索树的右子树大于根节点的性质,在根节点的右子树查找。

      image.gif编辑

      因此,我们可以写出以下代码:

      if(root.val < key) {
              root = root.right;
          }

      image.gif

      把以上所有的代码综合起来,这样我们就能写出查找结点的方法。我把查找的结点的方法名命为 findNode,方法内的代码根据上方代码进行修改而成。

      方法内的流程为:1.判断节点是否为空,为空则返回null。2.在根节点不为空的情况下,判断要查找的节点是否为根节点是则返回根节点,否则判断该节点在根节点的左子树还是右子树,是左子树就把根节点置为左子树,是右子树就把根节点置为右子树。3.没有该节点,返回null。

      public class BinarySearchTree {
          //节点结构
          static class TreeNode {
              public TreeNode left;//左子树
              public TreeNode right;//右子树
              public int val;//值
              public TreeNode(int val) {
                  this.val = val;//构造方法获取val的值
              }
          }
          //根节点
          public TreeNode root;
          //查找节点
          public TreeNode findNode(int key) {
              TreeNode node = root; //使node为根节点的一个代替
              if (node == null) { //根节点不为空
                  return null;
              }
              while (node != null) { //根节点不为空
                  if (node.val == key) { 
                      return node;//找到根节点就返回node
                  }else if (node.val > key) {
                      node = node.left;//根节点的值大于查找的值
                  }else {
                      node = node.right;//根节点的值小于查找的值
                  }
              }
              return null;//没有该节点返回null
          }
      }

      image.gif

      注意,我们直接使用根节点 root 进行操作的话会改变 root 的位置,这样在其他方法使用 root 结点时不能从最初的根节点(最顶层的根据)进行操作,因此我们可以创建一个代替根节点的代替值 node来进行操作,这样无论如何 root 始终是在最初的根节点。

      相关文章
      |
      6月前
      |
      存储 算法 Java
      算法系列之数据结构-二叉树
      树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
      178 10
       算法系列之数据结构-二叉树
      |
      6月前
      |
      算法 Java
      算法系列之数据结构-Huffman树
      Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
      146 3
       算法系列之数据结构-Huffman树
      |
      6月前
      |
      存储 自然语言处理 数据库
      【数据结构进阶】AVL树深度剖析 + 实现(附源码)
      在深入探讨了AVL树的原理和实现后,我们不难发现,这种数据结构不仅优雅地解决了传统二叉搜索树可能面临的性能退化问题,还通过其独特的平衡机制,确保了在任何情况下都能提供稳定且高效的查找、插入和删除操作。
      477 19
      |
      8月前
      |
      存储 C++
      【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
      【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
      188 14
      【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
      |
      8月前
      |
      Java C++
      【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
      本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
      179 12
      |
      8月前
      |
      C++
      【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
      本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
      160 10
      |
      8月前
      |
      存储 算法 测试技术
      【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
      本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
      253 3
      |
      9月前
      |
      数据库
      数据结构中二叉树,哈希表,顺序表,链表的比较补充
      二叉搜索树,哈希表,顺序表,链表的特点的比较
      数据结构中二叉树,哈希表,顺序表,链表的比较补充
      |
      10月前
      |
      存储 算法
      非递归实现后序遍历时,如何避免栈溢出?
      后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
      214 59
      |
      3月前
      |
      编译器 C语言 C++
      栈区的非法访问导致的死循环(x64)
      这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
      44 0
      栈区的非法访问导致的死循环(x64)