package practice;

public class TestMain {
public static void main(String[] args) {
int[] ao = {50,18,97,63,56,3,71,85,54,34,9,62,45,94,66,65,7,19,22,86};
Integer[] a = new Integer[20];
for (int i = 0; i < a.length; i++) {
a[i] = new Integer(ao[i]);
}
BinarySortTree<Integer, String> tree = new BinarySortTree<Integer, String>();
for (int i = 0; i < a.length; i++) {
tree.put(a[i], a[i].toString());
}
/*tree.delete(3);
System.out.println("min = "+tree.min()+" max = "+tree.max());
tree.delete(97);
System.out.println("min = "+tree.min()+" max = "+tree.max());
tree.delete(19);
tree.delete(18);
tree.delete(85);
System.out.println();
tree.delete(99);*/ }
}
/*
* 二叉查找树及其操作的递归实现
* 二叉查找树:左节点比根节点小,左节点比根节点大。
*/
class BinarySortTree<K extends Comparable<K>, V>{ Node root;
/*
* Node结点类
*/
class Node{
private Node left, right; //左右子树
private K key;
private V value;
private int N; //节点所在树的子节点数(包括自己) private Node(K key, V value) {
this.key = key;
this.value = value;
this.N = 1;
} public K getKey() {
return key;
}
}
/*
* 插入新节点
* O(lgn)
*/
public void put(K key, V value) {
root = put(key, value, root);
} private Node put(K key, V value, Node node) {
if (node == null) { return new Node(key, value);} if (compare(key, node.key) == 0) { node.value = value;} //如果key相等则更新值
else if (compare(key, node.key) < 0) { node.left = put(key, value, node.left);} //进入左子树
else if (compare(key, node.key) > 0) { node.right = put(key, value, node.right);} //进入右子树
node.N = size(node.left) + size(node.right) + 1; //子节点数 return node;
}
/*
* 查找
*/
public V get(K key) {
return get(key, root);
} private V get(K key, Node node) {
if (node == null) { return null;} if (compare(key, node.key) < 0) { return get(key, node.left);}
else if (compare(key, node.key) > 0) { return get(key, node.right);}
else { return node.value;} //递归结束条件,找到key
}
/*
* 获取最大最小值
*/
public K min() {
return min(root).key;
} private Node min(Node node) {
if (node.left == null) { return node;}
else { return min(node.left);}
} public K max() {
return max(root).key;
} private Node max(Node node) {
if (node.right == null) { return node;}
else { return max(node.right);}
}
/*
* 获取键的排名
*/
public int rank(K key) {
return rank(key, root);
} private int rank(K key, Node node) {
if (node == null) { return 0;} //键不存在返回0 if (compare(key, node.key) < 0) { return rank(key, node.left);}
else if (compare(key, node.key) > 0) { return size(node.left) + 1 + rank(key, node.right);}
//当查找进入右子树时,加上同级左子树的大小,再加1(父节点本身)
else { return size(node.left);} //该节点左子树的大小(它的左子树的key全部比它小)
}
/*
* 根据排名获取键
*/
public Node select(int N) {
return select(N, root);
} private Node select(int N, Node node) { int t = size(node.left) + 1; //获取当前节点在以它为根节点的树中的排名(从1开始排)
if (N < t) { return select(N, node.left);} //与当前排名比较,选择进入左子树还是右子树
else if (N > t) { return select(N - t, node.right);}
//进入右子树时,右子树所有的节点的排名都要加上"同级左子树的大小,再加1(父节点本身)",所以 N - t
else { return node;}
}
/*
* 删除最小键
*/
public void deleteMin() {
root = deleteMin(root);
}
private Node deleteMin(Node node) {
if (node.left == null) { return node.right;} //将最小节点的右子树连在他的父节点上即将它删除
node.left = deleteMin(node.left);
node.N = size(node.left) + size(node.right) + 1; //更新树的大小
return node;
}
/*
* 删除指定键
*/
public void delete(K key) {
root = delete(key, root);
}
private Node delete(K key, Node node) {
if (node == null) { return null;} //找不到键,不做任何处理,原样返回 if (compare(key, node.key) < 0) { node.left = delete(key, node.left);} //向左向右找
else if (compare(key, node.key) > 0) { node.right = delete(key, node.right);}
else {
if (node.right == null) { return node.left;} //如果要删的节点有一边时null,直接把另一条子树连到父节点上
if (node.left== null) { return node.right;}
/*Node tnode = min(node.right);
node.right = deleteMin(node.right);
tnode.left = node.left;
tnode.right = node.right;
tnode.N = size(tnode.left) + size(tnode.right) + 1;
return tnode;*/
//上下两段代码实现了同样的功能,充分体现了差距
Node tnode = node; //将右子树中的最小值(后继节点)连到父节点上,或左子树中的最大值(前趋节点)也可以
node = min(tnode.right);
node.right = deleteMin(tnode.right); //把将要连到父节点上的那个后继节点在当前位置删除
node.left = tnode.left; //更新左右子树
} node.N = size(node.left) + size(node.right) + 1; //更新树的大小
return node;
}
/*
* key1 < key2 -1
* key1 > key2 1
* key1 == key2 0
*/
private int compare(K key1, K key2) {
return key1.compareTo(key2);
} private int size(Node node) {
if (node == null) { return 0;}
else { return node.N;}
} /*
* 中序遍历
*/
public void print(Node node) {
if (node == null) {
return;
}
print(node.left);
System.out.print(node.key+" ");
print(node.right);
}
}

算法动态演示

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. CentOS 访问 Windows 共享目录

    起因 由于公司的网络切换后,将所有的服务器都切换到了指定的网段(工作电脑在一个网络,服务器在另一个网络:这样一来,不同部门的 work stations 可以彼此访问,不同部门的服务器(servers ...

  2. TransactionTemplate编程式事务管理方式的进阶使用---自定义拓展模板类

    1, 前面一篇的文章介绍了TransactionTemplate的基本使用方法. 同事在其基础上又做了一层封装,这样更贴合本公司的业务与规范. 2, 首先定义了两个接口: ServiceTemplat ...

  3. IEnumerable & IEnumerator

    IEnumerable 只有一个方法:IEnumerator GetEnumerator(). INumerable 是集合应该实现的一个接口,这样,就能用 foreach 来遍历这个集合. IEnu ...

  4. JavaSE(五)JAVA对象向上转型和向下转型

    今天做了一个测试的题目,发现自己还是很多问题没有静下心来做.很多问题是可以自己解决的但是自己一是没有读清题意,二是自己心里太急躁了.所以这个要自己应以为鉴! 对象的转型问题其实并不复杂,我们记住一句话 ...

  5. 微信开发获取用户OpenID

    第一次开发微信版网页,对最重要的获取微信OpenId,特此记录下来 1.首先得有appid和appsecret . public class WeiXin { public static string ...

  6. mysql的内连接,外连接(左外连接,右外连接)巩固

    1:mysql的内连接: 内连接(inner join):显示左表以及右表符合连接条件的记录: select a.goods_id,a.goods_name,b.cate_name from tdb_ ...

  7. CSS3基础(3)——CSS3 布局属性全接触

    一. 弹性盒模型 1.弹性盒子模型介绍 弹性盒模型(Flexible Box或Flexbox)是一个CSS3新增布局模块,官方称为CSS Flexible Box Layout Module,用于实现 ...

  8. 【LeetCode】数组-1(643)-返回规定长度k的最大子数组的平均数

    好久没有刷LeetCode了,准备重拾并坚持下去,每天刷个两小时.今天算是开始的第一天,不过出师不利,在一道很简单的题目上墨迹半天.不过还好,现在踩过的坑,应该都不会白踩,这些可能都是以后程序员路上稳 ...

  9. LINUX环境并发服务器的三种实现模型

    服务器设计技术有很多,按使用的协议来分有TCP服务器和UDP服务器.按处理方式来分有循环服务器和并发服务器. 1  循环服务器与并发服务器模型 在网络程序里面,一般来说都是许多客户对应一个服务器,为了 ...

  10. 理解javascript中的回调函数(callback)

    以下内容来源于:http://www.jb51.net/article/54641.htm 最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用.如果这个概念理解不了,nodejs ...