二叉树:

和链表一样,动态数据结构。

二叉树具有唯一根节点

二叉树具有天然的递归结构

二分搜索树是二叉树

二分搜索树的每个节点的值:

1.大于其左子树的所有节点的值

2.小于其右子树的所有节点的值

每一颗子数也是二分搜索树

  1. public class BST<E extends Comparable<E>> {
  2. private class Node{
  3. public E e;
  4. public Node left,right;
  5. public Node(E e){
  6. this.e=e;
  7. left=null;
  8. right=null;
  9. }
  10. }
  11. private Node root;
  12. private int size;
  13. public BST(){
  14. root=null;
  15. size=0;
  16. }
  17. public int size(){
  18. return size;
  19. }
  20. public boolean isEmpty(){
  21. return size==0;
  22. }
  23.  
  24. public void add(E e){
  25. if(root==null){
  26. root=new Node(e);
  27. size++;
  28. }else{
  29. add(root,e);
  30. }
  31. }
  32. 向以Node为跟节点的二分搜索树中插入元素E递归算法
  33. private void add(Node node,E e){
  34. if(e.equals(node.e)) return ;
  35. else if(e.compareTo(node.e)<0&&node.left==null){
  36. node.left=new Node(e);
  37. size++;
  38. return ;
  39. }else if(e.compareTo(node.e)>0&&node.right==null){
  40. node.right=new Node(e);
  41. size++;
  42. return;
  43. }
  44. if(e.compareTo(node.e)<0)
  45. add(node.left,e);
  46. else
  47. add(node.right, e);
  48.  
  49. public void add(E e){
  50. root=add(root, e);
  51. }
  52. private Node add(Node node,E e){
  53. if(node==null){
  54. size++;
  55. return new Node(e);
  56. }
  57. if(e.compareTo(node.e)<0)
  58. node.left=add(node.left, e);
  59. else if(e.compareTo(node.e)>0)
  60. node.right=add(node.right, e);
  61. return node;
  62. }
  63. //看二分搜索树中是否包含元素e
  64. public boolean contains(E e){
  65. return contains(root,e)
  66. }
  67. //以node为根的二分搜索树中是否包含元素e,递归算法
  68. public boolean contains(Node node,E e){
  69. if(node==null)
  70. return false;
  71. if(e.compareTo(node.e)==0)
  72. return true;
  73. else if(e.compareTo(node.e)<0)
  74. return contains(node.left,e);
  75. else
  76. return contains(node.right, e);
  77. }
  78.  
  79. }

  二分搜索树的前序遍历:

  1. //二分搜索树的前序遍历
  2. public void preOrder(){
  3. preOrder(root);
  4. }
  5. //前序遍历以node为根的二分搜索树,递归算法
  6. private void preOrder(Node node){
  7. if(node==null)
  8. return;
  9. System.out.println(node.e);
  10. preOrder(node.left);
  11. preOrder(node.right);
  12. }
  13.  
  14. @Override
  15. public String toString(){
  16. StringBuilder res=new StringBuilder();
  17. generateBSTString(root,0,res);
  18. return res.toString();
  19. }
  20. //生成node为根节点,深度为depth的描述二叉树的字符串
  21. private void generateBSTString(Node node,int dept,StringBuilder res){
  22. if(node==null){
  23. res.append(generateDepthString(dept)+"null\n");
  24. return;
  25. }
  26. res.append(generateDepthString(dept)+node.e+"\n");
  27. generateBSTString(node.left,dept+1,res);
  28. generateBSTString(node.right,dept+1,res);
  29. }
  30. private String generateDepthString(int dept) {
  31. StringBuilder res=new StringBuilder();
  32. for(int i=0;i<dept;i++)
  33. res.append("--");
  34. return res.toString();
  35. }

  测试:

  1. public class Main {
  2. public static void main(String[] args){
  3. BST<Integer> bst=new BST<>();
  4. int[] nums={5,3,6,8,4,2};
  5. for(int num:nums)
  6. bst.add(num);
  7. bst.preOrder();
  8. System.out.println();
  9. System.out.println(bst);
  10. }
  11. }

  二分搜索树的中序遍历和后续遍历

  1. //二分搜索树的中序遍历
  2. public void inOrder(){
  3. inOrder(root);
  4. }
  5. //中序遍历以node为根的二分搜索树,递归算法
  6. private void inOrder(Node node){
  7. if(node==null)
  8. return ;
  9. inOrder(node.left);
  10. System.out.println(node.e);
  11. inOrder(node.right);
  12. }
  13. //二分搜索树的后续遍历
  14. public void postOrder(){
  15. postOrder(root);
  16. }
  17. //后续遍历以node为根的二分搜索树,递归算法
  18. private void postOrder(Node node){
  19. if(node==null)
  20. return ;
  21. postOrder(node.left);
  22. postOrder(node.right);
  23.  
  24. System.out.println(node.e);
  25. }

  测试:

  1. bst.preOrder();
  2. System.out.println();
  3. bst.inOrder();
  4. System.out.println();
  5. bst.postOrder();
  6. System.out.println();

  

  1. //二分搜索树的非递归前序遍历
  2. public void preOrderNR(){
  3. Stack<Node> stack=new Stack<>();
  4. stack.push(root);
  5. while (!stack.isEmpty()) {
  6. Node cur=stack.pop();
  7. System.out.println(cur.e);
  8. if(cur.right!=null)
  9. stack.push(cur.right);
  10. if(cur.left!=null)
  11. stack.push(cur.left);
  12. }
  13. }
  1. //二分搜索树的层序遍历
  2. public void levelOrder(){
  3. Queue<Node> queue=new LinkedList<>();
  4. queue.add(root);
  5. while (!queue.isEmpty()) {
  6. Node cur=queue.remove();
  7. System.out.println(cur.e);
  8. if(cur.left!=null)
  9. queue.add(cur.left);
  10. if(cur.right!=null)
  11. queue.add(cur.right);
  12. }
  13. }

  

  1. //寻找二分搜索树的最小元素
  2. public E mininum(){
  3. if(size==0)
  4. throw new IllegalArgumentException("BST is empty");
  5. return mininum(root).e;
  6. }
  7. //返回以node为根的二分搜索树的最小值所在的节点
  8. private Node mininum(Node node){
  9. if(node.left==null)
  10. return node;
  11. return mininum(node.left);
  12. }
  13. //寻找二分搜索树的最大元素
  14. public E maximum(){
  15. if(size==0)
  16. throw new IllegalArgumentException("BST is empty");
  17. return maximum(root).e;
  18. }
  19. //返回node为根的二分搜索树的最大值所在的节点
  20. private Node maximum(Node node){
  21. if(node.right==null)
  22. return node;
  23. return maximum(node.right);
  24. }
  25.  
  26. //从二分搜索树中删除最小值所在节点,并返回最小值
  27. public E removeMin(){
  28. E ret=mininum();
  29. root=removeMin(root);
  30. return ret;
  31. }
  32. //删除掉以node为根的二分搜索树中的最小节点
  33. //返回删除节点后新的二分搜索树的根
  34. private Node removeMin(Node node){
  35. if(node.left==null){
  36. Node rightNode=node.right;
  37. node.right=null;
  38. size--;
  39. return rightNode;
  40. }
  41. node.left= removeMin(node.left);
  42. return node;
  43. }
  44.  
  45. //从二分搜索树中删除最大值所在节点
  46. public E removeMax(){
  47. E ret=maximum();
  48. root=removeMax(root);
  49. return ret;
  50. }
  51. //删除掉以node为根的二分搜索树中的最大节点
  52. //返回删除节点后新的二分搜索树的根
  53. public Node removeMax(Node node){
  54. if(node.right==null){
  55. Node leftNode=node.left;
  56. node.left=null;
  57. size--;
  58. return leftNode;
  59. }
  60. node.right=removeMax(node.right);
  61. return node;
  62. }

  测试

  1. public class Main {
  2. public static void main(String[] args){
  3. BST<Integer> bst=new BST<>();
  4. Random random=new Random();
  5. int n=1000;
  6. for(int i=0;i<n;i++)
  7. bst.add(random.nextInt(10000));
  8. ArrayList<Integer> nums=new ArrayList<>();
  9. while(!bst.isEmpty())
  10. nums.add(bst.removeMin());
  11. System.out.println(nums);
  12.  
  13. for(int i=1;i<nums.size();i++)
  14. if(nums.get(i-1)>nums.get(i))
  15. throw new IllegalArgumentException("Error");
  16. System.out.println("removeMin test completed.");
  17.  
  18. //test removeMax
  19. for(int i=0;i<n;i++)
  20. bst.add(random.nextInt(10000));
  21. nums=new ArrayList<>();
  22. while(!bst.isEmpty())
  23. nums.add(bst.removeMax());
  24. System.out.println(nums);
  25.  
  26. for(int i=1;i<nums.size();i++)
  27. if(nums.get(i-1)<nums.get(i))
  28. throw new IllegalArgumentException("Error");
  29. System.out.println("removeMax test completed.");
  30.  
  31. }
  32. }

  

  1. //从二分搜索树中删除元素为e的节点
  2. public void remove(E e){
  3. root=remove(root,e);
  4. }
  5. //删除以node为根的二分搜索树中值为e的节点,递归算法
  6. //返回删除节点后新的二分搜索树的根
  7. private Node remove(Node node,E e){
  8. if(node==null)
  9. return null;
  10. if(e.compareTo(node.e)<0){
  11. node.left=remove(node.left, e);
  12. return node;
  13. }
  14. else if(e.compareTo(node.e)>0){
  15. node.right= remove(node.right, e);
  16. return node;
  17. }else {
  18. //待删除节点左子树为空的情况
  19. if(node.left==null){
  20. Node rightNode=node.right;
  21. node.right=null;
  22. size--;
  23. return rightNode;
  24. }
  25. //待删除节点右子数为空的情况
  26. if(node.right==null){
  27. Node leftNode=node.left;
  28. node.left=null;
  29. size--;
  30. return leftNode;
  31. }
  32. //待删除节点左右子数均不为空的情况
  33. //找到比待删除节点大的最小节点,即待删除节点右子树的最小节点
  34. //用这个节点顶替待删除节点的位置
  35. Node successor=mininum(node.right);
  36. successor.right=removeMin(node.right);
  37.  
  38. successor.left=node.left;
  39.  
  40. node.left=node.right=null;
  41. return successor;
  42. }
  43. }

  

JAVA二分搜索树的更多相关文章

  1. java——二分搜索树 BST(递归、非递归)

    ~ package Date_pacage; import java.util.Stack; import java.util.ArrayList; import java.util.LinkedLi ...

  2. 7 二分搜索树的原理与Java源码实现

    1 折半查找法 了解二叉查找树之前,先来看看折半查找法,也叫二分查找法 在一个有序的整数数组中(假如是从小到大排序的),如果查找某个元素,返回元素的索引. 如下: int[] arr = new in ...

  3. 二分搜索树实现Java的Map(下)

    二分搜索树Map public class BSTMap<K extends Comparable<K>,V> implements Map<K,V> { priv ...

  4. Java的二分搜索树

    定义 二分搜索树是二叉树(不包含重复元素). 二分搜索树的每个节点的值,大于左子树的所有节点的值,小于其右子树的所有节点的值. 每一棵子树也是二分搜索树. 二叉树搜索树必须要有比较,继承Compara ...

  5. 浅析二分搜索树的数据结构的实现(Java 实现)

    目录 树结构简介 二分搜索树的基础知识 二叉树的基本概念 二分搜索树的基本概念 二分搜索树的基本结构代码实现 二分搜索树的常见基本操作实现 添加操作 添加操作初步实现 添加操作改进 查询操作 遍历操作 ...

  6. 【LeetCode题解】530_二分搜索树的最小绝对值差

    目录 [LeetCode题解]530_二分搜索树的最小绝对值差 描述 方法一.中序遍历二分搜索树 思路 Java 代码 Python 代码 [LeetCode题解]530_二分搜索树的最小绝对值差 描 ...

  7. 【二分搜索树】1、二分查找法的实现 - Binary Search

    简单记录 - bobo老师的玩转算法系列–玩转算法 - 二分搜索树 二叉搜索树 Binary Search Tree 查找问题 Searching Problem 查找问题是计算机中非常重要的基础问题 ...

  8. [LeetCode] Closest Binary Search Tree Value II 最近的二分搜索树的值之二

    Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...

  9. [LeetCode] Closest Binary Search Tree Value 最近的二分搜索树的值

    Given a non-empty binary search tree and a target value, find the value in the BST that is closest t ...

随机推荐

  1. Debian9 使用 Docker 安装 gitlab完整过程

    一. 安装Docker CE (参考 官网指南) 1. 卸载老版本 sudo apt-get remove docker docker-engine docker.io  2. Update the ...

  2. 必须要学会webpack打包,并到特别精通的程度

    必须要学会webpack打包,并到特别精通的程度

  3. Linux内存分配小结--malloc、brk、mmap【转】

    转自:https://blog.csdn.net/gfgdsg/article/details/42709943 http://blog.163.com/xychenbaihu@yeah/blog/s ...

  4. Luogu:P1600 天天爱跑步

    来一发清新的80行 树剖 $LCA$ + 树上差分 题解. -----from Judge 本题题意大概是给出一棵 n 个节点的树以及 m 条有向路径, 并且每个点 i 都有一个权值 $w[i]$,如 ...

  5. PHPExcel导出数据时字段超过26列出错Invalid cell coordinate [1

    http://blog.csdn.net/dl425134845/article/details/46650961 以下是解决方案函数 /** *   方法名:    getExcel *   作用  ...

  6. 51nod--1240莫比乌斯函数 (数论)

    题目: 1240 莫比乌斯函数 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 莫比乌斯函数,由德国数学家和天文学家莫比乌斯提出.梅滕斯(Mertens)首先 ...

  7. Linux之 nginx-redis-virtualenv-mysql

    mysql maraidb相关 .yum安装好,启动 安装: yum install mariadb-server mariadb 启动mabiadb: systemctl start mariadb ...

  8. postman 设置api_token,测试数据等操作

    在postman的环境变量中先设置好一个用户的token(事先你的数据库里面要有用户的这个数据),如下图: 然后在api请求的url 的head头部添加对应的token键名,value值用花括号{{t ...

  9. ant自动编译打包android项目

    源代码及可执行文件下载地址:http://files.cnblogs.com/rainboy2010/antdemo.zip Android打包APK的流程如下:  下面我们开始尝试使用ant进行ap ...

  10. Linux安装nodejs和npm

    先安装,nvm,即是Node Version Manager(Node版本管理器) curl -o- https://raw.githubusercontent.com/creationix/nvm/ ...