基于Java的二叉树实现
来源:互联网 发布:淘宝购物,如何返利? 编辑:程序博客网 时间:2024/05/21 04:43
简介:二叉搜索树的插入与删除图解_Linux编程_Linux公社-Linux系统门户网站
1.node
public class Node { public int data; public Node leftChild;//左子树 public Node rightChild;//右子树 public Node(int data) { this.data = data; leftChild = null; rightChild = null; }}
2.MyTree
public class MyTree { private Node root; /*增*/ public void insert(int value) { Node node = new Node(value); if (root == null) { root = node;//根节点 } else { Node current = root; Node parent = root; while (true) { //左小右大 if (current.data > node.data) { //先找左边 parent = current; current = current.leftChild; if (current == null) { parent.leftChild = node;// System.out.println("左边插入之后current==node" + (current == node));// System.out.println("左边插入之后current==node" + (root.leftChild == node)); return; } } else { //再找右 parent = current; current = current.rightChild; if (current == null) { parent.rightChild = node;// System.out.println("右边边插入之后current==node" + (current == node));// System.out.println("右边插入之后current==node" + (root.leftChild == node)); return; } } } } } /*查询*/ public Node find(int value) { //查找 if (root == null) { return null; } Node current = root; while (current.data != value) { if (current.data > value) { //左边 current = current.leftChild; } else { current = current.rightChild; } if (current == null) { return null; } } return current; } public boolean update(int oldValue, int newValue) { if (root == null) { return false; } Node current = root; while (current.data != oldValue) { if (current.data > oldValue) { current = current.leftChild; } else { current = current.rightChild; } if (current == null) { return false; } } current.data = newValue; return true; } /*** * 前序遍历:根->左->右 * @param localNode */ public void frontOrder(Node localNode) { if (localNode == null) { return; } else { System.out.print(localNode.data + " ,"); //节点的左子树 frontOrder(localNode.leftChild); frontOrder(localNode.rightChild); } } /*** * 中序遍历:左->根->右 * @param localNode */ public void inOrder(Node localNode) { if (localNode == null) { return; } else { //节点的左子树 inOrder(localNode.leftChild); System.out.print(localNode.data + " ,"); inOrder(localNode.rightChild); } } /*** * 后序遍历:左->右->根 * @param localNode */ public void afterOrder(Node localNode) { if (localNode == null) { return; } else { //节点的左子树 afterOrder(localNode.leftChild); afterOrder(localNode.rightChild); System.out.print(localNode.data + " ,"); } } public boolean delete(int value) { //首先查询需要删除的节点先 if (root == null) { return false; } Node current = root; Node parent = root; boolean isLeftChild = false;//存储被删结点是左子树还是右子树 while (current.data != value) { parent = current;//存储当前结点,作为下一次循环的上一次结点 if (current.data > value) { //左子树 current = current.leftChild; isLeftChild = true; } else { //右子树 current = current.rightChild; isLeftChild = false; } if (current == null) { return false; } } //找到那个符合条件的结点了,来到这里的current不会为空 if (current.leftChild == null && current.rightChild == null) { //被删结点叶子结点(即是:被删结点的左子树为空,右子树也为空) if (isLeftChild) { parent.leftChild = null; } else { parent.rightChild = null; } } else if (current.leftChild == null) { //被删结点的左子树为空,但右子树一定不为空 if (isLeftChild) { //被删结点是左子树(对于它父亲而言) parent.leftChild = current.rightChild; } else { parent.rightChild = current.rightChild; } } else if (current.rightChild == null) { //被删结点的右子树为空,但左子树一定不为空 if (isLeftChild) { //被删结点是左子树(对于它父亲而言) parent.leftChild = current.leftChild; } else { parent.rightChild = current.leftChild; } } else { //被删结点的右子树不为空,但左子树不为空 //中序后继,帮助被删结点找出他的继承结点(min(x>被删结点)) Node successor = getSuccessor(current); if (current == root) { root = successor; } else { //需要连接新点 if (isLeftChild) { parent.leftChild = successor; } else { parent.rightChild = successor; } } //把被删结点的左子树移交给被继承结点 successor.leftChild = current.leftChild; } return true; } /*找到被删结点的继承结点*/ private Node getSuccessor(Node delNode) { Node successorParent = delNode; Node success = delNode; Node current = delNode.rightChild;//在右边才能找到比它大的点 while (current != null) { successorParent = success; success = current; current = current.leftChild;//这样才能找到min(x>被删结点) } if (success != delNode.rightChild) { //把它右子树给它老爸(它本身一定不会有左子树) success.rightChild = successorParent.leftChild; success.rightChild = delNode.rightChild; } return success; } public Node getRoot() { return root; } public boolean isEmpty() { return root == null; }}
3.测试代码
MyTree mt = new MyTree(); mt.insert(10); mt.insert(20); mt.insert(15); mt.insert(3); mt.insert(4); mt.insert(90);// Node node = mt.find(0);// System.out.println(node.data);// boolean update = mt.update(2, 5);// System.out.println(update);//// Node node = mt.find(5);// System.out.println(node.data);// Node root = mt.getRoot();// System.out.println(root.data);//3// System.out.println("root.leftChild:" + root.leftChild.data);//null// System.out.println("root.rightChild:" + root.rightChild.data);//null// System.out.print("前序遍历:");// mt.frontOrder(mt.getRoot());//// System.out.println();//// System.out.print("中序遍历:");// mt.inOrder(mt.getRoot());// System.out.println();//// System.out.print("后序遍历:");// mt.afterOrder(mt.getRoot()); mt.delete(11); System.out.print("中序遍历:"); mt.inOrder(mt.getRoot()); System.out.println();
上文中删除有点小问题,如果是仅有左子树或者右子树的根结点被删除的时候,会有bug,修正代码如下:
/** * 删除节点 * @param value */ public boolean delete(long value) { //引用当前节点,从根节点开始 Node current = root; //应用当前节点的父节点 Node parent = root; //是否为左节点 boolean isLeftChild = true; while(current.data != value) { parent = current; //进行比较,比较查找值和当前节点的大小 if(current.data > value) { current = current.leftChild; isLeftChild = true; } else { current = current.rightChild; isLeftChild = false; } //如果查找不到 if(current == null) { return false; } } //删除叶子节点,也就是该节点没有子节点 if(current.leftChild == null && current.rightChild == null) { if(current == root) { root = null; } else if(isLeftChild) { parent.leftChild = null; } else { parent.rightChild = null; } } else if(current.rightChild == null) { if(current == root) { root = current.leftChild; }else if(isLeftChild) { //这里的isLeftChild是相对于parent跟current连接而言的 parent.leftChild = current.leftChild; } else { parent.rightChild = current.leftChild; } } else if(current.leftChild == null) { if(current == root) { root = current.rightChild; } else if(isLeftChild) { parent.leftChild = current.rightChild; } else { parent.rightChild = current.rightChild; } } else { //中序后继 Node successor = getSuccessor(current); if(current == root) { root = successor; } else if(isLeftChild) { parent.leftChild = successor; } else{ parent.rightChild = successor; } successor.leftChild = current.leftChild; } return true; } public Node getSuccessor(Node delNode) { Node successor = delNode; Node successorParent = delNode; Node current = delNode.rightChild; while(current != null) { successorParent = successor; successor = current; current = current.leftChild; } if(successor != delNode.rightChild) { successorParent.leftChild = successor.rightChild; successor.rightChild = delNode.rightChild; } return successor; }
阅读全文
0 0
- 基于Java实现的基本二叉树
- 基于Java的二叉树实现
- 数据结构之基于Java的二叉树实现
- 二叉树的java实现
- Java二叉树的实现
- java二叉树的实现
- 二叉树的java实现
- java二叉树的实现
- 二叉树的Java实现
- 二叉树的java实现
- 二叉树的实现Java
- 二叉树的Java实现
- ## java实现的二叉树 ##
- 基于java的数据结构学习手记14-二叉树的实现
- Java二叉树的实现(链式实现)
- 基于二叉树的思路实现的“十叉树”
- 基于二叉搜索树的map的c++实现
- 二叉树基于遍历的进一步操作c++实现
- 小福利贴-chrome实用插件
- React Native通信机制详解
- 百练_2722:学分绩点
- 题目1017:还是畅通工程
- 面试题8月真题汇总
- 基于Java的二叉树实现
- IntelliJ Idea 2017 免费激活方法
- VARNISH
- Android 优雅的为RecyclerView添加HeaderView和FooterView
- springMVC+hibernate+spring干净的一个配置文件
- LintCode 二叉树的前序,中序,后序,层次遍历
- 有损服务
- Gym
- 110. Balanced Binary Tree