详解Java二叉排序树

一、二叉排序树定义
1.二叉排序树的定义
  二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:
①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
③左、右子树本身又各是一棵二叉排序树。
上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。

2.二叉排序树的性质
按中序遍历二叉排序树,所得到的中序遍历序列是一个递增有序序列。

3.二叉排序树的插入
在二叉排序树中插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义。   
插入过程:
若二叉排序树为空,则待插入结点*S作为根结点插入到空树中;   
当非空时,将待插结点关键字S->key和树根关键字t->key进行比较,若s->key = t->key,则无须插入,若s->key< t->key,则插入到根的左子树中,若s->key> t->key,则插入到根的右子树中。而子树中的插入过程和在树中的插入过程相同,如此进行下去,直到把结点*s作为一个新的树叶插入到二叉排序树中,或者直到发现树已有相同关键字的结点为止。

4.二叉排序树的查找
假定二叉排序树的根结点指针为 root ,给定的关键字值为 K ,则查找算法可描述为:
  ① 置初值: q = root ;
  ② 如果 K = q -> key ,则查找成功,算法结束;
  ③ 否则,如果 K < q -> key ,而且 q 的左子树非空,则将 q 的左子树根送 q ,转步骤②;否则,查找失败,结束算法;
  ④ 否则,如果 K > q -> key ,而且 q 的右子树非空,则将 q 的右子树根送 q ,转步骤②;否则,查找失败,算法结束。

5.二叉排序树的删除
假设被删结点是*p,其双亲是*f,不失一般性,设*p是*f的左孩子,下面分三种情况讨论:   
⑴ 若结点*p是叶子结点,则只需修改其双亲结点*f的指针即可。   
⑵ 若结点*p只有左子树PL或者只有右子树PR,则只要使PL或PR 成为其双亲结点的左子树即可。   
⑶ 若结点*p的左、右子树均非空,先找到*p的中序前趋(或后继)结点*s(注意*s是*p的左子树中的最右下的结点,它的右链域为空),然后有两种做法:① 令*p的左子树直接链到*p的双亲结点*f的左链上,而*p的右子树链到*p的中序前趋结点*s的右链上。② 以*p的中序前趋结点*s代替*p(即把*s的数据复制到*p中),将*s的左子树链到*s的双亲结点*q的左(或右)链上。
6、二叉树的遍历
二叉树的遍历有三种方式,如下:
(1)前序遍历(DLR),首先访问根结点,然后遍历左子树,最后遍历右子树。简记根-左-右。
(2)中序遍历(LDR),首先遍历左子树,然后访问根结点,最后遍历右子树。简记左-根-右。
(3)后序遍历(LRD),首先遍历左子树,然后遍历右子树,最后访问根结点。简记左-右-根。

二、代码编写
1、树节点类的定义0

package com.lin;
/**
 * 功能概要: 

 */
public class TreeNode { 

  public Integer data; 

  /*该节点的父节点*/
  public TreeNode parent; 

  /*该节点的左子节点*/
  public TreeNode left; 

  /*该节点的右子节点*/
  public TreeNode right; 

  public TreeNode(Integer data) {
    this.data = data; 

  } 

  @Override
  public String toString() {
    return "TreeNode [data=" + data + "]";
  } 

}

2、二叉排序树的定义

package com.lin; 

/**
 * 功能概要:排序/平衡二叉树 

 */
public class SearchTree { 

   public TreeNode root; 

   public long size; 

  /**
   * 往树中加节点
   * @param data
   * @return Boolean 插入成功返回true
   */
  public Boolean addTreeNode(Integer data) { 

    if (null == root) {
      root = new TreeNode(data);
      System.out.println("数据成功插入到平衡二叉树中");
      return true;
    } 

    TreeNode treeNode = new TreeNode(data);// 即将被插入的数据
    TreeNode currentNode = root;
    TreeNode parentNode; 

    while (true) {
      parentNode = currentNode;// 保存父节点
      // 插入的数据比父节点小
      if (currentNode.data > data) {
        currentNode = currentNode.left;
        // 当前父节点的左子节点为空
        if (null == currentNode) {
          parentNode.left = treeNode;
          treeNode.parent = parentNode;
          System.out.println("数据成功插入到二叉查找树中");
          size++;
          return true;
        }
        // 插入的数据比父节点大
      } else if (currentNode.data < data) {
        currentNode = currentNode.right;
        // 当前父节点的右子节点为空
        if (null == currentNode) {
          parentNode.right = treeNode;
          treeNode.parent = parentNode;
          System.out.println("数据成功插入到二叉查找树中");
          size++;
          return true;
        }
      } else {
        System.out.println("输入数据与节点的数据相同");
        return false;
      }
    }
  } 

  /**
   * @param data
   * @return TreeNode
   */
  public TreeNode findTreeNode(Integer data){
    if(null == root){
      return null;
    }
    TreeNode current = root;
    while(current != null){
      if(current.data > data){
        current = current.left;
      }else if(current.data < data){
        current = current.right;
      }else {
        return current;
      } 

    }
    return null;
  } 

}

这里暂时只放了一个增加和查找的方法
3、前、中、后遍历

package com.lin; 

import java.util.Stack; 

/**
 * 功能概要:
 */
public class TreeOrder { 

  /**
   * 递归实现前序遍历
   * @author linbingwen
   * @since 2015年8月29日
   * @param treeNode
   */
  public static void preOrderMethodOne(TreeNode treeNode) {
    if (null != treeNode) {
      System.out.print(treeNode.data + " ");
      if (null != treeNode.left) {
        preOrderMethodOne(treeNode.left);
      }
      if (null != treeNode.right) {
        preOrderMethodOne(treeNode.right); 

      }
    }
  } 

  /**
   * 循环实现前序遍历
   * @param treeNode
   */
  public static void preOrderMethodTwo(TreeNode treeNode) {
    if (null != treeNode) {
      Stack<TreeNode> stack = new Stack<TreeNode>();
      stack.push(treeNode);
      while (!stack.isEmpty()) {
        TreeNode tempNode = stack.pop();
        System.out.print(tempNode.data + " ");
        // 右子节点不为null,先把右子节点放进去
        if (null != tempNode.right) {
          stack.push(tempNode.right);
        }
        // 放完右子节点放左子节点,下次先取
        if (null != tempNode.left) {
          stack.push(tempNode.left);
        }
      }
    }
  } 

  /**
   * 递归实现中序遍历
   * @param treeNode
   */
  public static void medOrderMethodOne(TreeNode treeNode){
    if (null != treeNode) {
      if (null != treeNode.left) {
        medOrderMethodOne(treeNode.left);
      }
      System.out.print(treeNode.data + " ");
      if (null != treeNode.right) {
        medOrderMethodOne(treeNode.right);
      }
    } 

  } 

  /**
   * 循环实现中序遍历
   * @param treeNode
   */
  public static void medOrderMethodTwo(TreeNode treeNode){
    Stack<TreeNode> stack = new Stack<TreeNode>();
    TreeNode current = treeNode;
    while (current != null || !stack.isEmpty()) {
      while(current != null) {
        stack.push(current);
        current = current.left;
      }
      if (!stack.isEmpty()) {
        current = stack.pop();
        System.out.print(current.data+" ");
        current = current.right;
      }
    }
  } 

  /**
   * 递归实现后序遍历
   * @param treeNode
   */
  public static void postOrderMethodOne(TreeNode treeNode){
    if (null != treeNode) {
      if (null != treeNode.left) {
        postOrderMethodOne(treeNode.left);
      }
      if (null != treeNode.right) {
        postOrderMethodOne(treeNode.right);
      }
      System.out.print(treeNode.data + " ");
    } 

  } 

  /**
   * 循环实现后序遍历
   * @param treeNode
   */
  public static void postOrderMethodTwo(TreeNode treeNode){
    if (null != treeNode) {
      Stack<TreeNode> stack = new Stack<TreeNode>();
      TreeNode current = treeNode;
      TreeNode rightNode = null;
      while(current != null || !stack.isEmpty()) {
        while(current != null) {
          stack.push(current);
          current = current.left;
        }
        current = stack.pop();
        while (current != null && (current.right == null ||current.right == rightNode)) {
          System.out.print(current.data + " ");
          rightNode = current;
          if (stack.isEmpty()){
            System.out.println();
            return;
          }
          current = stack.pop();
        }
        stack.push(current);
        current = current.right;
      }  

    }
  } 

}

4、使用方法

package com.lin;
/**
 * 功能概要:
*/
public class SearchTreeTest { 

  /**
   * @param args
   */
  public static void main(String[] args) {
    SearchTree tree = new SearchTree();
    tree.addTreeNode(50);
    tree.addTreeNode(80);
    tree.addTreeNode(20);
    tree.addTreeNode(60);
    tree.addTreeNode(10);
    tree.addTreeNode(30);
    tree.addTreeNode(70);
    tree.addTreeNode(90);
    tree.addTreeNode(100);
    tree.addTreeNode(40);
    System.out.println("=============================="+"采用递归的前序遍历开始"+"==============================");
    TreeOrder.preOrderMethodOne(tree.root);
    System.out.println();
    System.out.println("=============================="+"采用循环的前序遍历开始"+"==============================");
    TreeOrder.preOrderMethodTwo(tree.root);
    System.out.println();
    System.out.println("=============================="+"采用递归的后序遍历开始"+"==============================");
    TreeOrder.postOrderMethodOne(tree.root);
    System.out.println();
    System.out.println("=============================="+"采用循环的后序遍历开始"+"==============================");
    TreeOrder.postOrderMethodTwo(tree.root);
    System.out.println();
    System.out.println("=============================="+"采用递归的中序遍历开始"+"==============================");
    TreeOrder.medOrderMethodOne(tree.root);
    System.out.println();
    System.out.println("=============================="+"采用循环的中序遍历开始"+"==============================");
    TreeOrder.medOrderMethodTwo(tree.root); 

  } 

}

输出结果:

同样,进行查找过程如下:

TreeNode node = tree.findTreeNode(100);
System.out.println(node); 

结果是正确的

以上就是关于Java二叉排序树的详细介绍,希望对大家的学习java程序设计有所帮助。

(0)

相关推荐

  • Java 实现二叉搜索树的查找、插入、删除、遍历

    由于最近想要阅读下JDK1.8 中HashMap的具体实现,但是由于HashMap的实现中用到了红黑树,所以我觉得有必要先复习下红黑树的相关知识,所以写下这篇随笔备忘,有不对的地方请指出- 学习红黑树,我觉得有必要从二叉搜索树开始学起,本篇随笔就主要介绍Java实现二叉搜索树的查找.插入.删除.遍历等内容. 二叉搜索树需满足以下四个条件: 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 任意节点的左.右子

  • java使用归并删除法删除二叉树中节点的方法

    本文实例讲述了java使用归并删除法删除二叉树中节点的方法.分享给大家供大家参考.具体分析如下: 实现的思想很简单: first:找到要删除的节点 second:如果删除的节点没有右子树那么左子树链到父节点 third:如果删除的节点没有左子树那么右子树链到父节点 forth:如果删除的节点又左右孩子,那么可以归并删除节点后的子树:方法有两种一种是用删除节点的左子树的最右节点,指向删除节点的右子树,另一种是用删除节点的用字数的最左节点指向删除节点的左子树. Java 实现如下: public v

  • JAVA 实现二叉树(链式存储结构)

    二叉树的分类(按存储结构) 树的分类(按存储结构) 顺序存储(用数组表示(静态二叉树))   链式存储 一些特别的二叉根: 完全二叉树,平衡二叉树(AVL),线索二叉树,三叉的(带父亲的指针)    二叉搜索树或者叫二叉 查找树(BST)  所用二叉树如下图所示: 二叉树的Java实现(链式存储结构) class TreeNode { private int key = 0; private String data = null; private boolean isVisted = false

  • Java中二叉树数据结构的实现示例

    来看一个具体的习题实践: 题目 根据二叉树前序遍历序列例如:7,-7,8,#,#,-3,6,#,9,#,#,#,-5,#,#,构建二叉树,并且用前序.中序.后序进行遍历 代码 import java.util.Scanner; public class BinaryTree { public static String[] str; public static int count; /** * 静态内部类,定义二叉树节点 */ static class TreeNode { public Str

  • Java基于二叉查找树实现排序功能示例

    本文实例讲述了Java基于二叉查找树实现排序功能.分享给大家供大家参考,具体如下: /** * 无论排序的对象是什么,都要实现Comparable接口 * * @param <T> */ public class BinaryNode<T extends Comparable<T>> { private static int index = 0; // 排序下标 private static int len = 0; // 最大数组长度 private T t; //

  • Java的二叉树排序以及遍历文件展示文本格式的文件树

    Java二叉树排序算法 排序二叉树的描述也是一个递归的描述, 所以排序二叉树的构造自然也用递归的: 排序二叉树的3个特征: 1:当前node的所有左孩子的值都小于当前node的值: 2:当前node的所有右孩子的值都大于当前node的值: 3:孩子节点也满足以上两点 package test.sort; public class BinaryNode { private int value;//current value private BinaryNode lChild;//left chil

  • 图解二叉树的三种遍历方式及java实现代码

    二叉树(binary tree)是一颗树,其中每个节点都不能有多于两个的儿子. 1.二叉树节点 作为图的特殊形式,二叉树的基本组成单元是节点与边:作为数据结构,其基本的组成实体是二叉树节点(binary tree node),而边则对应于节点之间的相互引用. 如下,给出了二叉树节点的数据结构图示和相关代码: // 定义节点类: private static class BinNode { private Object element; private BinNode lChild;// 定义指向

  • Java实现求二叉树的深度和宽度

    这个是常见的对二叉树的操作.总结一下: 设节点的数据结构,如下: 复制代码 代码如下: class TreeNode {     char val;     TreeNode left = null;     TreeNode right = null; TreeNode(char _val) {         this.val = _val;     } } 1.二叉树深度 这个可以使用递归,分别求出左子树的深度.右子树的深度,两个深度的较大值+1即可. 复制代码 代码如下: // 获取最大

  • java 二叉查找树实例代码

    java 二叉查找树实例代码 1.左边<中间<右边 2.前序遍历 左中右 3.中序遍历 中左右 4.后序遍历 左右中 public class BinaryTree { // 二叉树的根节点 public TreeNode rootNode ; // 记录搜索深度 public int count; /** * 利用传入一个数组来建立二叉树 */ public BinaryTree(int[] data) { for (int i = 0; i < data. length; i++)

  • java实现二叉树的创建及5种遍历方法(总结)

    用java实现的数组创建二叉树以及递归先序遍历,递归中序遍历,递归后序遍历,非递归前序遍历,非递归中序遍历,非递归后序遍历,深度优先遍历,广度优先遍历8种遍历方式: package myTest; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Stack; public class myClass { public static void main(

  • java二叉查找树的实现代码

    本文实例为大家分享了java二叉查找树的具体代码,供大家参考,具体内容如下 package 查找; import edu.princeton.cs.algs4.Queue; import edu.princeton.cs.algs4.StdOut; public class BST<Key extends Comparable<Key>, Value> { private class Node { private Key key; // 键 private Value value;

  • 图解红黑树及Java进行红黑二叉树遍历的方法

    红黑树 红黑树是一种数据结构与算法课堂上常常提到但又不会细讲的树,也是技术面试中经常被问到的树,然而无论是书上还是网上的资料,通常都比较刻板难以理解,能不能一种比较直观的方式来理解红黑树呢?本文将以图形的方式来解释红黑树的插入与删除操作. 对树结构的学习是一个递进的过程,我们通常所接触的树都是二叉树,二叉树简单来说就是每个非叶子节点都有且只有两个孩子,分别叫做左孩子和右孩子.二叉树中有一类特殊的树叫二叉查找树,二叉查找树是一种有序的树,对于每个非叶子节点,其左子树的值都小于它,其右子树的值都大于

随机推荐