1. package practice;
  2.  
  3. public class TestMain {
  4. public static void main(String[] args) {
  5. int[] ao = {50,18,97,63,56,3,71,85,54,34,9,62,45,94,66,65,7,19,22,86};
  6. Integer[] a = new Integer[20];
  7. for (int i = 0; i < a.length; i++) {
  8. a[i] = new Integer(ao[i]);
  9. }
  10. BinarySortTree<Integer, String> tree = new BinarySortTree<Integer, String>();
  11. for (int i = 0; i < a.length; i++) {
  12. tree.put(a[i], a[i].toString());
  13. }
  14. /*tree.delete(3);
  15. System.out.println("min = "+tree.min()+" max = "+tree.max());
  16. tree.delete(97);
  17. System.out.println("min = "+tree.min()+" max = "+tree.max());
  18. tree.delete(19);
  19. tree.delete(18);
  20. tree.delete(85);
  21. System.out.println();
  22. tree.delete(99);*/
  23.  
  24. }
  25. }
  26. /*
  27. * 二叉查找树及其操作的递归实现
  28. * 二叉查找树:左节点比根节点小,左节点比根节点大。
  29. */
  30. class BinarySortTree<K extends Comparable<K>, V>{
  31.  
  32. Node root;
  33. /*
  34. * Node结点类
  35. */
  36. class Node{
  37. private Node left, right; //左右子树
  38. private K key;
  39. private V value;
  40. private int N; //节点所在树的子节点数(包括自己)
  41.  
  42. private Node(K key, V value) {
  43. this.key = key;
  44. this.value = value;
  45. this.N = 1;
  46. }
  47.  
  48. public K getKey() {
  49. return key;
  50. }
  51. }
  52. /*
  53. * 插入新节点
  54. * O(lgn)
  55. */
  56. public void put(K key, V value) {
  57. root = put(key, value, root);
  58. }
  59.  
  60. private Node put(K key, V value, Node node) {
  61. if (node == null) { return new Node(key, value);}
  62.  
  63. if (compare(key, node.key) == 0) { node.value = value;} //如果key相等则更新值
  64. else if (compare(key, node.key) < 0) { node.left = put(key, value, node.left);} //进入左子树
  65. else if (compare(key, node.key) > 0) { node.right = put(key, value, node.right);} //进入右子树
  66. node.N = size(node.left) + size(node.right) + 1; //子节点数
  67.  
  68. return node;
  69. }
  70. /*
  71. * 查找
  72. */
  73. public V get(K key) {
  74. return get(key, root);
  75. }
  76.  
  77. private V get(K key, Node node) {
  78. if (node == null) { return null;}
  79.  
  80. if (compare(key, node.key) < 0) { return get(key, node.left);}
  81. else if (compare(key, node.key) > 0) { return get(key, node.right);}
  82. else { return node.value;} //递归结束条件,找到key
  83. }
  84. /*
  85. * 获取最大最小值
  86. */
  87. public K min() {
  88. return min(root).key;
  89. }
  90.  
  91. private Node min(Node node) {
  92. if (node.left == null) { return node;}
  93. else { return min(node.left);}
  94. }
  95.  
  96. public K max() {
  97. return max(root).key;
  98. }
  99.  
  100. private Node max(Node node) {
  101. if (node.right == null) { return node;}
  102. else { return max(node.right);}
  103. }
  104. /*
  105. * 获取键的排名
  106. */
  107. public int rank(K key) {
  108. return rank(key, root);
  109. }
  110.  
  111. private int rank(K key, Node node) {
  112. if (node == null) { return 0;} //键不存在返回0
  113.  
  114. if (compare(key, node.key) < 0) { return rank(key, node.left);}
  115. else if (compare(key, node.key) > 0) { return size(node.left) + 1 + rank(key, node.right);}
  116. //当查找进入右子树时,加上同级左子树的大小,再加1(父节点本身)
  117. else { return size(node.left);} //该节点左子树的大小(它的左子树的key全部比它小)
  118. }
  119. /*
  120. * 根据排名获取键
  121. */
  122. public Node select(int N) {
  123. return select(N, root);
  124. }
  125.  
  126. private Node select(int N, Node node) {
  127.  
  128. int t = size(node.left) + 1; //获取当前节点在以它为根节点的树中的排名(从1开始排)
  129. if (N < t) { return select(N, node.left);} //与当前排名比较,选择进入左子树还是右子树
  130. else if (N > t) { return select(N - t, node.right);}
  131. //进入右子树时,右子树所有的节点的排名都要加上"同级左子树的大小,再加1(父节点本身)",所以 N - t
  132. else { return node;}
  133. }
  134. /*
  135. * 删除最小键
  136. */
  137. public void deleteMin() {
  138. root = deleteMin(root);
  139. }
  140. private Node deleteMin(Node node) {
  141. if (node.left == null) { return node.right;} //将最小节点的右子树连在他的父节点上即将它删除
  142. node.left = deleteMin(node.left);
  143. node.N = size(node.left) + size(node.right) + 1; //更新树的大小
  144. return node;
  145. }
  146. /*
  147. * 删除指定键
  148. */
  149. public void delete(K key) {
  150. root = delete(key, root);
  151. }
  152. private Node delete(K key, Node node) {
  153. if (node == null) { return null;} //找不到键,不做任何处理,原样返回
  154.  
  155. if (compare(key, node.key) < 0) { node.left = delete(key, node.left);} //向左向右找
  156. else if (compare(key, node.key) > 0) { node.right = delete(key, node.right);}
  157. else {
  158. if (node.right == null) { return node.left;} //如果要删的节点有一边时null,直接把另一条子树连到父节点上
  159. if (node.left== null) { return node.right;}
  160. /*Node tnode = min(node.right);
  161. node.right = deleteMin(node.right);
  162. tnode.left = node.left;
  163. tnode.right = node.right;
  164. tnode.N = size(tnode.left) + size(tnode.right) + 1;
  165. return tnode;*/
  166. //上下两段代码实现了同样的功能,充分体现了差距
  167. Node tnode = node; //将右子树中的最小值(后继节点)连到父节点上,或左子树中的最大值(前趋节点)也可以
  168. node = min(tnode.right);
  169. node.right = deleteMin(tnode.right); //把将要连到父节点上的那个后继节点在当前位置删除
  170. node.left = tnode.left; //更新左右子树
  171. }
  172.  
  173. node.N = size(node.left) + size(node.right) + 1; //更新树的大小
  174. return node;
  175. }
  176. /*
  177. * key1 < key2 -1
  178. * key1 > key2 1
  179. * key1 == key2 0
  180. */
  181. private int compare(K key1, K key2) {
  182. return key1.compareTo(key2);
  183. }
  184.  
  185. private int size(Node node) {
  186. if (node == null) { return 0;}
  187. else { return node.N;}
  188. }
  189.  
  190. /*
  191. * 中序遍历
  192. */
  193. public void print(Node node) {
  194. if (node == null) {
  195. return;
  196. }
  197. print(node.left);
  198. System.out.print(node.key+" ");
  199. print(node.right);
  200. }
  201. }

算法动态演示

http://www.cs.usfca.edu/~galles/visualization/BST.html

递归的二叉查找树Java实现的更多相关文章

  1. 数据结构二叉树的递归与非递归遍历之java,javascript,php实现可编译(1)java

    前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序 ...

  2. 二叉树3种递归和非递归遍历(Java)

    import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...

  3. 算法——快速排序迭代式和递归式的Java实现

    快速排序迭代式和递归式的Java实现 快速排序基于分治法的思想,在待排序表中任选一值作为中枢值 pivot,一趟快排将所有大于该值的元素置于一边,小于该值的元素置于另一边,这样一个元素在排序中的最终位 ...

  4. 数据结构实现(四)二叉查找树java实现

    转载 http://www.cnblogs.com/CherishFX/p/4625382.html 二叉查找树的定义: 二叉查找树或者是一颗空树,或者是一颗具有以下特性的非空二叉树: 1. 若左子树 ...

  5. 化繁为简 经典的汉诺塔递归问题 in Java

    问题描述   在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑 ...

  6. 递归-归并排序 思想 JAVA实现

    已知一个数组   15.58.61.75.21.32.89.4.78.83.采用递归实现的归并排序将数组有序. 分治策略:(摘自<算法导论>) 在分治策略中,我们采用递归解决问题 分解:将 ...

  7. 二叉查找树--java

    package com.test.tree; public class BinarySearchTree<T extends Comparable<? super T>> { ...

  8. 非递归遍历二叉树Java版的实现代码(没写层次遍历)

    直接上代码呵呵,里面有注解 package www.com.leetcode.specificProblem; import java.util.ArrayList; import java.util ...

  9. 二叉树的递归插入【Java实现】

    C++中由于有指针的存在,可以让二叉树节点指针的指针作为插入函数的实参,在函数体内通过*操作实现对真实节点指针.节点左孩子指针.节点右孩子指针的改变,这样很容易使用递归将大树问题转化到小树问题.但在J ...

随机推荐

  1. Maven常用的几个核心概念

    在使用Maven的过程中,经常会遇到几个核心的概念,准确的理解这些概念将会有莫大的帮助. 1. POM(Project Object Model)项目对象模型 POM 与 Java 代码实现了解耦,当 ...

  2. 白话ASP.NET MVC之一:Url 路由

    好久没有写关于ASP.NET MVC的东西了,虽然<ASP.NET MVC4框架揭秘>已经完完整整的看完一遍,但是感觉和一锅粥差不多,没什么可写的,因为我自己不理解,也就写不出来.现在开始 ...

  3. 13. leetcode 453. Minimum Moves to Equal Array Elements

    Given a non-empty integer array of size n, find the minimum number of moves required to make all arr ...

  4. html、js简单实现含中文csv文件下载(后端为django)

    1.在django  views.py中使用HttpResponse views.py首行加上utf-8编码,将默认unicode编码变为utf-8 # -*- coding:utf-8 -*- 下面 ...

  5. mybatis中的mapper接口文件以及example类的实例函数以及详解

    ##Example example = new ##Example(); example.setOrderByClause("字段名 ASC"); //升序排列,desc为降序排列 ...

  6. HDU 6097---Mindis(二分)

    题目链接 Problem Description The center coordinate of the circle C is O, the coordinate of O is (0,0) , ...

  7. 前端开发工具Brackets介绍,安装及安装Emme插件时踩过的坑

    对于前端开发的园友来说有可能IDE工具有很多,层次不穷,还有每个人的喜好及习惯也不一样,因为我是一名后端开发的.Net程序员,但是大家都知道,现在都提倡什么全栈工程师,所以也得会点前端开发,所以我对于 ...

  8. 第7章 DNS & bind从基础到深入

    本文目录: 7.1 DNS必懂基础 7.1.1 域的分类 7.1.2 主机名.域名.FQDN 7.1.3 域的分层授权 7.1.4 DNS解析流程 7.2 DNS术语 7.2.1 递归查询和迭代查询 ...

  9. 【NO.11】Jmeter - 构建1个可供Linux使用的Jmeter测试脚本 - 共3个步骤

    在Linux使用Jmeter做性能测试需要4个前提条件,这4个前提条件已经在之前的文档里提到了,重复一下加深印象: (1) 在本地已安装xshell 参考<SecureCRT-转换密钥-Xshe ...

  10. C语言开篇

    Linux下使用最广泛的C/C++编译器是GCC,大多数的Linux发行版本都默认安装,不管是开发人员还是初学者,一般都将GCC作为Linux下首选的编译工具. 1.小程序test_gets.c #i ...