一、二叉排序树定义

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. Android 开源项目源码解析(第二期)

    Android 开源项目源码解析(第二期) 阅读目录 android-Ultra-Pull-To-Refresh 源码解析 DynamicLoadApk 源码解析 NineOldAnimations ...

  2. android水平循环滚动控件

    CycleScrollView.java package com.example.test; import android.content.Context; import android.graphi ...

  3. 黑马程序猿————OC在Foundation框架结构和字符串

    ------<a href="http://www.itheima.com" target="blank">Java火车.Android火车.iOS ...

  4. 阿里2016实习offer五面经验与总结(转)

    前言 目前楼主已经拿到阿里实习offer,一共经历了5次面试,其中4轮技术面,1轮HR面试.在这里分享一下自己的面试经验和学习总结.写这篇面经主要是希望能够帮助更多的小伙伴.我本科毕业于中南大学信管专 ...

  5. 金句: "對比MBA學位,我們更需要PSD學位的人!" Poor, Smart and Deep Desire to… | consilient_lollapalooza on Xanga

    金句: "對比MBA學位,我們更需要PSD學位的人!" Poor, Smart and Deep Desire to… | consilient_lollapalooza on X ...

  6. 字典实体类:DictionaryEntry类

    DictionaryEntry类是一个字典集合,主要包括的内容是键/值对.这样的组合方式能够方便地定位数据,当中的"键"具备唯一性,类似于数据库中的"id",一 ...

  7. Amazon S3数据一致性模型

    左右Amazon S3有两种类型的数据的一致性模型的: 最后,一致性和读一致性. 有下面几种行为: 1 写一个新的object,然后開始读它.直到全部的变化都传播完(副本),你才干读到它,否则就是ke ...

  8. Django写的投票系统4(转)

    原文地址:http://www.cnblogs.com/djangochina/archive/2013/06/04/3114269.html 现在已经可以在后台管理投票了,现在就差怎么在前台显示和如 ...

  9. Nginx对某个文件夹或整个站点进行登录认证的方法

    比方要对 站点文件夹下的 test 文件夹 进行加密认证 首先须要在opt 的主文件夹中 /opt/ 创建一个新文件 htpasswd 此文件的书写格式是 username:password 每行一个 ...

  10. 查看mysql当前表使用的存储引擎(转)

    说明:当我们创建表 “test”表时 CREATE TABLE test ( id INT(11) default NULL auto_increment, s char(60) default NU ...