一、二叉排序树定义

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、树节点类的定义

  1. package com.lin;
  2. /**
  3. * 功能概要:
  4. *
  5. * @author linbingwen
  6. * @since  2015年8月29日
  7. */
  8. public class TreeNode {
  9. public Integer data;
  10. /*该节点的父节点*/
  11. public TreeNode parent;
  12. /*该节点的左子节点*/
  13. public TreeNode left;
  14. /*该节点的右子节点*/
  15. public TreeNode right;
  16. public TreeNode(Integer data) {
  17. this.data = data;
  18. }
  19. @Override
  20. public String toString() {
  21. return "TreeNode [data=" + data + "]";
  22. }
  23. }

2、二叉排序树的定义

  1. package com.lin;
  2. /**
  3. * 功能概要:排序/平衡二叉树
  4. *
  5. * @author linbingwen
  6. * @since  2015年8月29日
  7. */
  8. public class SearchTree {
  9. public TreeNode root;
  10. public long size;
  11. /**
  12. * 往树中加节点
  13. * @author linbingwen
  14. * @since  2015年8月29日
  15. * @param data
  16. * @return Boolean 插入成功返回true
  17. */
  18. public Boolean addTreeNode(Integer data) {
  19. if (null == root) {
  20. root = new TreeNode(data);
  21. System.out.println("数据成功插入到平衡二叉树中");
  22. return true;
  23. }
  24. TreeNode treeNode = new TreeNode(data);// 即将被插入的数据
  25. TreeNode currentNode = root;
  26. TreeNode parentNode;
  27. while (true) {
  28. parentNode = currentNode;// 保存父节点
  29. // 插入的数据比父节点小
  30. if (currentNode.data > data) {
  31. currentNode = currentNode.left;
  32. // 当前父节点的左子节点为空
  33. if (null == currentNode) {
  34. parentNode.left = treeNode;
  35. treeNode.parent = parentNode;
  36. System.out.println("数据成功插入到二叉查找树中");
  37. size++;
  38. return true;
  39. }
  40. // 插入的数据比父节点大
  41. } else if (currentNode.data < data) {
  42. currentNode = currentNode.right;
  43. // 当前父节点的右子节点为空
  44. if (null == currentNode) {
  45. parentNode.right = treeNode;
  46. treeNode.parent = parentNode;
  47. System.out.println("数据成功插入到二叉查找树中");
  48. size++;
  49. return true;
  50. }
  51. } else {
  52. System.out.println("输入数据与节点的数据相同");
  53. return false;
  54. }
  55. }
  56. }
  57. /**
  58. * 查找数据
  59. * @author linbingwen
  60. * @since  2015年8月29日
  61. * @param data
  62. * @return TreeNode
  63. */
  64. public TreeNode findTreeNode(Integer data){
  65. if(null == root){
  66. return null;
  67. }
  68. TreeNode current = root;
  69. while(current != null){
  70. if(current.data > data){
  71. current = current.left;
  72. }else if(current.data < data){
  73. current = current.right;
  74. }else {
  75. return current;
  76. }
  77. }
  78. return null;
  79. }
  80. }

这里暂时只放了一个增加和查找的方法

3、前、中、后遍历

  1. package com.lin;
  2. import java.util.Stack;
  3. /**
  4. * 功能概要:
  5. *
  6. * @author linbingwen
  7. * @since  2015年8月29日
  8. */
  9. public class TreeOrder {
  10. /**
  11. * 递归实现前序遍历
  12. * @author linbingwen
  13. * @since  2015年8月29日
  14. * @param treeNode
  15. */
  16. public static void preOrderMethodOne(TreeNode treeNode) {
  17. if (null != treeNode) {
  18. System.out.print(treeNode.data + "  ");
  19. if (null != treeNode.left) {
  20. preOrderMethodOne(treeNode.left);
  21. }
  22. if (null != treeNode.right) {
  23. preOrderMethodOne(treeNode.right);
  24. }
  25. }
  26. }
  27. /**
  28. * 循环实现前序遍历
  29. * @author linbingwen
  30. * @since  2015年8月29日
  31. * @param treeNode
  32. */
  33. public static void preOrderMethodTwo(TreeNode treeNode) {
  34. if (null != treeNode) {
  35. Stack<TreeNode> stack = new Stack<TreeNode>();
  36. stack.push(treeNode);
  37. while (!stack.isEmpty()) {
  38. TreeNode tempNode = stack.pop();
  39. System.out.print(tempNode.data + "  ");
  40. // 右子节点不为null,先把右子节点放进去
  41. if (null != tempNode.right) {
  42. stack.push(tempNode.right);
  43. }
  44. // 放完右子节点放左子节点,下次先取
  45. if (null != tempNode.left) {
  46. stack.push(tempNode.left);
  47. }
  48. }
  49. }
  50. }
  51. /**
  52. * 递归实现中序遍历
  53. * @author linbingwen
  54. * @since  2015年8月29日
  55. * @param treeNode
  56. */
  57. public static void medOrderMethodOne(TreeNode treeNode){
  58. if (null != treeNode) {
  59. if (null != treeNode.left) {
  60. medOrderMethodOne(treeNode.left);
  61. }
  62. System.out.print(treeNode.data + "  ");
  63. if (null != treeNode.right) {
  64. medOrderMethodOne(treeNode.right);
  65. }
  66. }
  67. }
  68. /**
  69. * 循环实现中序遍历
  70. * @author linbingwen
  71. * @since  2015年8月29日
  72. * @param treeNode
  73. */
  74. public static void medOrderMethodTwo(TreeNode treeNode){
  75. Stack<TreeNode> stack = new Stack<TreeNode>();
  76. TreeNode current = treeNode;
  77. while (current != null || !stack.isEmpty()) {
  78. while(current != null) {
  79. stack.push(current);
  80. current = current.left;
  81. }
  82. if (!stack.isEmpty()) {
  83. current = stack.pop();
  84. System.out.print(current.data+"  ");
  85. current = current.right;
  86. }
  87. }
  88. }
  89. /**
  90. * 递归实现后序遍历
  91. * @author linbingwen
  92. * @since  2015年8月29日
  93. * @param treeNode
  94. */
  95. public static void postOrderMethodOne(TreeNode treeNode){
  96. if (null != treeNode) {
  97. if (null != treeNode.left) {
  98. postOrderMethodOne(treeNode.left);
  99. }
  100. if (null != treeNode.right) {
  101. postOrderMethodOne(treeNode.right);
  102. }
  103. System.out.print(treeNode.data + "  ");
  104. }
  105. }
  106. /**
  107. * 循环实现后序遍历
  108. * @author linbingwen
  109. * @since  2015年8月29日
  110. * @param treeNode
  111. */
  112. public static void postOrderMethodTwo(TreeNode treeNode){
  113. if (null != treeNode) {
  114. Stack<TreeNode> stack = new Stack<TreeNode>();
  115. TreeNode current = treeNode;
  116. TreeNode rightNode = null;
  117. while(current != null || !stack.isEmpty()) {
  118. while(current != null) {
  119. stack.push(current);
  120. current = current.left;
  121. }
  122. current = stack.pop();
  123. while (current != null && (current.right == null ||current.right == rightNode)) {
  124. System.out.print(current.data + "  ");
  125. rightNode = current;
  126. if (stack.isEmpty()){
  127. System.out.println();
  128. return;
  129. }
  130. current = stack.pop();
  131. }
  132. stack.push(current);
  133. current = current.right;
  134. }
  135. }
  136. }
  137. }

4、使用方法

  1. package com.lin;
  2. /**
  3. * 功能概要:
  4. *
  5. * @author linbingwen
  6. * @since  2015年8月29日
  7. */
  8. public class SearchTreeTest {
  9. /**
  10. * @author linbingwen
  11. * @since  2015年8月29日
  12. * @param args
  13. */
  14. public static void main(String[] args) {
  15. SearchTree tree = new SearchTree();
  16. tree.addTreeNode(50);
  17. tree.addTreeNode(80);
  18. tree.addTreeNode(20);
  19. tree.addTreeNode(60);
  20. tree.addTreeNode(10);
  21. tree.addTreeNode(30);
  22. tree.addTreeNode(70);
  23. tree.addTreeNode(90);
  24. tree.addTreeNode(100);
  25. tree.addTreeNode(40);
  26. System.out.println("=============================="+"采用递归的前序遍历开始"+"==============================");
  27. TreeOrder.preOrderMethodOne(tree.root);
  28. System.out.println();
  29. System.out.println("=============================="+"采用循环的前序遍历开始"+"==============================");
  30. TreeOrder.preOrderMethodTwo(tree.root);
  31. System.out.println();
  32. System.out.println("=============================="+"采用递归的后序遍历开始"+"==============================");
  33. TreeOrder.postOrderMethodOne(tree.root);
  34. System.out.println();
  35. System.out.println("=============================="+"采用循环的后序遍历开始"+"==============================");
  36. TreeOrder.postOrderMethodTwo(tree.root);
  37. System.out.println();
  38. System.out.println("=============================="+"采用递归的中序遍历开始"+"==============================");
  39. TreeOrder.medOrderMethodOne(tree.root);
  40. System.out.println();
  41. System.out.println("=============================="+"采用循环的中序遍历开始"+"==============================");
  42. TreeOrder.medOrderMethodTwo(tree.root);
  43. }
  44. }

输出结果:

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

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

结果是正确的

http://blog.csdn.net/evankaka/article/details/48088241

Java二叉排序树(转)的更多相关文章

  1. java二叉排序树

    二叉排序树又称二叉查找树.它或者是一颗空树,或者是具有如下性质的二叉树: 1.如果左子树不空,那么左子树上的所有节点均小于它的根节点的值: 2.如果右子树不空,那么右子树上的所有节点均大于它的根节点的 ...

  2. 算法8 五大查找之:二叉排序树(BSTree)

    上一篇总结了索引查找,这一篇要总结的是二叉排序树,又称为二叉搜索树(BSTree) . 构造一棵二叉排序树的目的,其实并不是为了排序,而是为了提高查找和插入删除的效率. 什么是二叉排序树呢?二叉排序树 ...

  3. 算法08 五大查找之:二叉排序树(BSTree)

    上一篇总结了索引查找,这一篇要总结的是二叉排序树(Binary Sort Tree),又称为二叉查找树(Binary Search Tree) ,即BSTree. 构造一棵二叉排序树的目的,其实并不是 ...

  4. (转)查找算法:二叉排序树(BSTree)

    二叉排序树(Binary Sort Tree),又称为二叉查找树(Binary Search Tree) ,即BSTree. 构造一棵二叉排序树的目的,其实并不是为了排序,而是为了提高查找和插入删除的 ...

  5. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  6. Java 7之集合类型 - 二叉排序树、平衡树、红黑树---转

    http://blog.csdn.net/mazhimazh/article/details/19961017 为了理解 TreeMap 的底层实现,必须先介绍排序二叉树和平衡二叉树,然后继续介绍红黑 ...

  7. 【Java】 大话数据结构(11) 查找算法(2)(二叉排序树/二叉搜索树)

    本文根据<大话数据结构>一书,实现了Java版的二叉排序树/二叉搜索树. 二叉排序树介绍 在上篇博客中,顺序表的插入和删除效率还可以,但查找效率很低:而有序线性表中,可以使用折半.插值.斐 ...

  8. 二叉排序树的理解和实现(Java)

    二叉排序树的定义和性质 二叉排序树又称二叉排序树.它或者是一个空树,或者是一个具有下列性质的二叉树: 若它的左子树不空,则左子树上所有节点的值均小于它的根结构的值 若它的右子树不空,则右子树上所有结点 ...

  9. 【LeetCode-面试算法经典-Java实现】【109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)】

    [109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 ...

随机推荐

  1. 60s 经济学探奇

    理解经济学 什么是经济学.对于学习金融的同学,一定会给你搬出一大堆定义.例证.学派.说经济学是一门研究研究价值的生产.流通.分配.消费的规律的理论. 非常高大上的感觉,可是对于我这样没有什么金融学理论 ...

  2. 魔棒工具--RegionGrow算法简介

    原地址:http://www.cnblogs.com/easymind223/archive/2012/07/04/2576964.html ps里面的魔棒工具非常好用,是图像处理中非常常用的一个工具 ...

  3. Mod in math

    An Introduction to Modular Math When we divide two integers we will have an equation that looks like ...

  4. WebService的相关使用

    近期公司项目使用WebService ,这里简单做个总结. 事实上详细使用细节有些情况下须要改,还须要看实际情况,须要与server联调,详细沟通. 比方公司连接,非要把envelope.dotNet ...

  5. SmartDraw2008破解过程总结

    SmartDraw2008破解过程总结作者:chszs  原创转载请保留作者名. 按下列步骤完毕,保证能够支持中文. 一.所需软件:1)SmartDraw2008安装软件:2)SmartDraw200 ...

  6. java多线程:ReentrantReadWriteLock读写锁使用

    Lock比传统的线程模型synchronized更多的面向对象的方式.锁和生活似,应该是一个对象.两个线程运行的代码片段要实现同步相互排斥的效果.它们必须用同一个Lock对象. 读写锁:分为读锁和写锁 ...

  7. C#语言实现ArcGIS数据源重置之Set Data Source功能

    1.须要:依据选择的Mxd路径和目标数据源路径进行重置数据源.此处以(.Mdb为例): 主要利用到的接口: (1)IMapDocument    (2)IMapControl2     (3)IWor ...

  8. C语言文件操作之fgets()

        来说一说fgets(..)函数.     原型  char *  fgets(char * s, int n,FILE *stream);     參数:          s: 字符型指针, ...

  9. Android开发之使用URL訪问网络资源

    Android开发之使用URL訪问网络资源 URL (UniformResource Locator)对象代表统一资源定位器,它是指向互联网"资源"的指针. 资源能够是简单的文件或 ...

  10. NEU月赛Segment Balls(线段树)

    问题 D: Segment Balls 时间限制: 1 Sec  内存限制: 128 MB 提交: 253  解决: 37 题目描述 Small K has recently earn money i ...