二叉搜索树 思想 JAVA实现

二叉搜索树:一棵二叉搜索树是以一棵二叉树来组织的,这样一棵树可以使用链表的数据结构来表示(也可以采用数组来实现)。除了key和可能带有的其他数据外,每个节点还包含Left,Right,Parent,它们分别指节点的左孩子,右孩子,和父节点。

一个二叉搜索树总是满足 :node.left.key<node.key<=node.right.key。

以下是一个用java实现的二叉搜索树,包含了查找最大值,最小值,查找某一节点,插入和删除操作。

接下来通过代码来分析二叉搜索树中的思想:在代码实现二叉搜索树中,大量采用了递归的思想,同样可以采用循环去递归来实现。

插入:自根节点起递归调用“寻找合适位置方法”,使二叉搜索树始终满足条件  node.left.key<node.key<=node.right.key。

查询:自根节点起递归调用“查找孩子的方法”。查找孩子的方法采用的思想是,判断node.key==key 返回,node.key>key 递归查找左子树,node.key<=key 递归查             找右子树。

查询最小值:递归查找左孩子,直到最后一个左孩子。

查询最大值:递归查找右孩子,直到最后一个右孩子。

遍历:

前序遍历:根的关键字输出在左右子树的关键字之前。根 左 右。

中序遍历:根的关键字输出在左右子树的关键字之间。左 根 右。

后序遍历:根的关键字输出在左右子树的关键字之后。左 右 根。

删除:删除一棵搜索树是比较麻烦的。共有以下4种情况

1.删除节点没有孩子,直接断开连接即可

2.a图:删除节点没有左孩子,将右孩子移至删除节点处

3.b图:删除节点没有右孩子,将左孩子移至删除节点处

4.c图:有左右孩子,右孩子 没有 左孩子,将右孩子移动至删除节点处,将左孩子的父节点连接值右孩子。

5.d图:有左右孩子,且右孩子也有左右孩子,则查找右孩子的最小节点,将最小节点移至删除节点处。

public class SearchTree {
                     //树的根节点
      private Node Root = null;
                     //内部类,结点
      private class Node{

         Node parent;//父节点
         Node Left;//左孩子
         Node Right;//右孩子
         int keyValue;//关键字

         public Node(Node parent,
                Node Left,
                Node Right,
                int keyValue) {
          this.parent = parent;
          this.Left = Left;
          this.Right = Right;
          this.keyValue = keyValue;
         }
      }

      public void delete(int value) {
        Node deleteNode = this.search(value);//查找删除节点
        if(deleteNode.Left==null) {//没有左孩子
          transplant(deleteNode, deleteNode.Right);
        }else if(deleteNode.Right==null) {//没有右孩子
          transplant(deleteNode, deleteNode.Left);
        }else {//有左右孩子时
          Node min = this.min(deleteNode.Right);//查找右孩子的最小节点
          if(min.parent!=deleteNode) {
            transplant(min, min.Right);
            min.Right = deleteNode.Right;
            min.Right.parent = min;
          }
        transplant(deleteNode, min);
        min.Left = deleteNode.Left;
        min.Left.parent = min;
        }
      }

//交换子树,将node2 移动至node1的位置。
      private void transplant(Node node1,Node node2) {
        if(node1.parent==null) {
          this.Root = node2;
        }else if(node1==node1.parent.Left) {
          node1.parent.Left = node2;
        }else {
          node1.parent.Right= node2;
        }
        if(node2!=null) {
          node2.parent = node1.parent;
        }
      }

//查找方法
      public Node search(int value) {
        return searchNode(this.Root,value);
      }

      private Node searchNode(Node node,int key) {
        if(node==null || node.keyValue==key) {
          return node;
        }
        if(node.keyValue>key) {
          return this.searchNode(node.Left,key);
        }else {
          return this.searchNode(node.Right, key);
        }
      }

//插入方法
      public void insert(int value) {
        Node child = new Node(null, null, null, value);
        findRightPlace(this.Root,child);
      }

      private void findRightPlace(Node currentRoot,Node insertNode) {
        if(currentRoot!=null) {
            if(currentRoot.keyValue>insertNode.keyValue) {
              if(currentRoot.Left==null) {
                currentRoot.Left = insertNode;
                insertNode.parent = currentRoot;
              }else {
                findRightPlace(currentRoot.Left,insertNode);
                   }
            }else {
              if(currentRoot.Right==null) {
                currentRoot.Right = insertNode;
                insertNode.parent = currentRoot;
              }else {
                findRightPlace(currentRoot.Right,insertNode);
              }
            }
        }else {
            this.Root = insertNode;
        }
      }

//查找最大
      public int findMax() {
        return max(this.Root)==null?-1:max(this.Root).keyValue;
      }

      private Node max(Node node) {
        if(node!=null) {
          if(node.Right!=null) {
            return max(node.Right);
          }else {
            return node;
          }
        }else {
          return null;
        }
      }

//查找最小
      public int findMin() {
        return min(this.Root)==null?-1:min(this.Root).keyValue;
      }

      private Node min(Node node) {
        if(node!=null) {
          if(node.Left!=null) {
            return min(node.Left);
          }else {
            return node;
          }
        }else {
          return null;
        }
      }

//后序遍历
      public void after() {
        afterShow(this.Root);
      }

      private void afterShow(Node node) {
        if(node!=null) {
          afterShow(node.Left);
          afterShow(node.Right);
          System.out.println(node.keyValue);
        }
      }

//中序遍历
      public void mid() {
        midShow(this.Root);
      }

      private void midShow(Node node) {
        if(node!=null) {
          midShow(node.Left);
          System.out.println(node.keyValue);
          midShow(node.Right);
        }
      }

//前序遍历
      public void ahead() {
        aheadShow(this.Root);
      }

      private void aheadShow(Node node) {
        if(node!=null) {
          System.out.println(node.keyValue);
          aheadShow(node.Left);
          aheadShow(node.Right);
        }
}

参考资料 《算法导论》第三版

原文地址:https://www.cnblogs.com/dev1ce/p/10651620.html

时间: 2024-11-08 21:25:21

二叉搜索树 思想 JAVA实现的相关文章

二叉搜索树的Java实现

为了更加深入了解二叉搜索树,博主自己用Java写了个二叉搜索树,有兴趣的同学可以一起探讨探讨. 首先,二叉搜索树是啥?它有什么用呢? 二叉搜索树, 也称二叉排序树,它的每个节点的数据结构为1个父节点指针,1个左孩子指针,1个有孩子指针,还有就是自己的数据部分了,因为只有左右两孩子,所以才叫二叉树,在此基础上,该二叉树还满足另外一个条件:每个结点的左孩子都不大于该结点&&每个结点的右孩子都大于该结点.这样,我们队这棵树进行中序遍历,就能把key从小到大排序了…… 那么问题来了,我都有线性表有

BST(二叉搜索树) Java 实现解析

1.二叉搜索树的定义:一颗树的所有左子树都比根小,所有右子树都比根大,成为二叉搜索树. 2.该BST树实现了9个重要方法,分别是关键字查找,插入,删除,删除节点后续节点查找,前序遍历,中序遍历,后序遍历,获取最大节点,获取最小节点. 3.以下是Java的代码实现: //定义Node类,拥有元素值,节点名称,左孩子节点,右孩子节点,4个成员变量.class Node { int element; String name; Node leftChild; Node rightChild; publi

LeetCode 235. 二叉搜索树的最近公共祖先(Lowest Common Ancestor of a Binary Search Tree) 32

235. 二叉搜索树的最近公共祖先 235. Lowest Common Ancestor of a Binary Search Tree 题目描述 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)." 例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,nul

【Java】 剑指offer(36) 二叉搜索树与双向链表

本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路 二叉搜索树.排序链表,想到使用中序遍历. 要实现双向链表,必须知道当前结点的前一个结点.根据中序遍历可以知道,当遍历到根结点的时候,左子树已经转化成了一个排序的链表了,根结点的前一结点就是该链表的最后一个结点(这个结点必须记录下来,将遍历函数的返回值设置

Java实现二叉搜索树

原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11406176.html 尝试一下用Java实现二叉搜索树/二叉查找树,记录自己的学习历程. 1. 首先先来设计实现一下节点Node. ??一个二叉树的节点需要以下几个元素: key 关键字 value 节点的值(key也可以代替value) parent 父节点 leftChildren 左儿子节点 rightChildren 右儿子节点 那就开始吧! /** * 节点 */ class N

Java数据结构之二叉搜索树

Java数据结构之二叉搜索树 1.二叉搜索树组成 二叉搜索树又称为二叉排序树,它或者是一颗空树,或者是一颗具有如下特性的非空二叉树,需要满足一下三个条件: (1)若它的左子树非空,则左子树上所有结点的关键字均小于根结点的关键字: (2)若它的右子树非空,则右子树上所有结点的关键字均大于(可以等于)根结点的关键字. (3)左子树右子树本身又各是一颗二叉搜索树 在算法描述中,均以结点值的比较来代表其关键字的比较,因为若结点的值为类类型时,该类必须实现系统提供的java.lang.comparable

平衡二叉搜索树(AVL树)的原理及实现源代码(有图文详解和C++、Java实现代码)

一.AVL树(平衡二叉搜索树)是什么? AVL树是根据它的发明者G.M. Adelson-Velsky和E.M. Landis命名的.AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个非叶子结点的左右子树的高度之差的绝对值(平衡因子)最多为1. 例如: 5             5 / \            /  \ 2   6         2   6 / \    \         / \ 1  4   7       1  4

Java实现二叉搜索树的添加,前序、后序、中序及层序遍历,求树的节点数,求树的最大值、最小值,查找等操作

什么也不说了,直接上代码. 首先是节点类,大家都懂得 /** * 二叉树的节点类 * * @author HeYufan * * @param <T> */ class Node<T extends Comparable<? super T>> { /** * 节点储存的值 */ private T data; /** * 左子节点 */ private Node<T> leftNode; /** * 右子节点 */ private Node<T>

二叉树、二叉搜索树、AVL树的java实现

数据结构一直都是断断续续的看,总是觉得理解的不够深入,特别是对树的理解,一直都很浅显,今儿又看了一遍,来做个总结吧. 首先,树中的一些概念: 1.树的节点包含一个数据元素,以及若干指向其子树的分支.节点拥有的子树的数量称为节点的度.节点的最大层次称为树的深度或高度. 2.二叉树是一种树形结构,其特点是每个节点至多有两棵子树,且子树有左右之分,次序不能随意颠倒. 3.满二叉树:一棵深度为k且有2^k - 1个节点的二叉树,称之为满二叉树. 4.完全二叉树:对一个深度为k,节点个数为n的二叉树,当且