二叉树懒惰删除相关例程

来源:互联网 发布:c 定义二维数组 编辑:程序博客网 时间:2024/06/01 09:47

在编写二叉树懒惰删除相关例程时,发现findMin和findMax两个方法很是复杂,于是上网百度懒惰删除相关例程的解法,却没有找到。今天硬是用比较粗糙的方法憋了出来,既然网上无法百度的到,那么我就把我的解法贴出来交流交流吧。

首先是节点类

public class TreeNode <T> {private T value;//节点值private TreeNode<T> left;//左节点private TreeNode<T> right;//右节点private TreeNode<T> father;//父节点private boolean delete;//删除标记,若被删除则为true,初始化为false;public TreeNode(T value){this.value = value;}public T getValue() {return value;}public void setValue(T value) {this.value = value;}public TreeNode<T> getLeft() {return left;}public void setLeft(TreeNode<T> left) {this.left = left;}public TreeNode<T> getRight() {return right;}public void setRight(TreeNode<T> right) {this.right = right;}public TreeNode<T> getFather() {return father;}public void setFather(TreeNode<T> father) {this.father = father;}public boolean isDelete() {return delete;}public void setDelete(boolean delete) {this.delete = delete;}}

接着是二叉树类,采用懒惰删除思想

public class BinaryTree <T extends Comparable<? super T>> {private TreeNode<T> root;/** * 从根部打印树 */public void print(){this.print(root);}/** * 递归打印树 * @param node 树根结点 */public void print(TreeNode<T> node){//若根节点不为空可进行递归打印,采用中序遍历if(node != null){//1.打印左节点this.print(node.getLeft());//2.若未被删除打印节点if(!node.isDelete()){System.out.print(node.getValue() + "\t");}//3.打印右节点this.print(node.getRight());}}/** * 从根部寻找节点 * @param value 节点值 * @return  */public boolean contain(T value){return contain(value, root);}/** * 递归寻找节点 * @param value 寻找节点值 * @param node 树根结点 * @return */public boolean contain(T value, TreeNode<T> node){if(node == null){return false;}//1.比较大小int result = value.compareTo(node.getValue());//2.若小则从左节点寻找if(result < 0){return contain(value, node.getLeft());}//3.若大则从右节点寻找else if(result > 0){return contain(value, node.getRight());}//4.若相等并且被删除返回falseelse if(result == 0 && node.isDelete()){return false;}//5.若相等并且未被删除返回trueelse{return true;}}/** * 从根部开始添加节点 * @param value 被添加节点值 */public void add(T value){root = add(value, root);}/** * 递归添加节点 * @param value 被添加节点值 * @param node 树根结点 * @return 树根结点 */public TreeNode<T> add(T value, TreeNode<T> node){if(node == null){return new TreeNode<T>(value);}//1.比较大小int result = value.compareTo(node.getValue());//2.若小则在左子树进行添加操作if(result < 0){TreeNode<T> temp = add(value, node.getLeft());//连接操作,防止当子节点为空时丢失子树node.setLeft(temp);temp.setFather(node);}//3.若大则在右子树进行添加操作else if(result > 0){TreeNode<T> temp = add(value, node.getRight());//连接操作,防止当子节点为空时丢失子树node.setRight(temp);temp.setFather(node);}//4.相等并且被删除则修改删除标记为false;else if(result == 0 && node.isDelete()){node.setDelete(false);}return node;}/** * 从根部开始删除节点 * @param value 目标节点值 */public void remove(T value){remove(value, root);}/** * 递归懒惰删除节点 * @param value 目标节点值 * @param node 树根结点 * @return 树根结点 */public void remove(T value, TreeNode<T> node){if(node == null){return;}//1.比较大小int result = value.compareTo(node.getValue());//2.若小在左子树进行删除操作if(result < 0){remove(value, node.getLeft());}//3.若大在右子树进行删除操作else if(result > 0){remove(value, node.getRight());}//4.若相等并且未被删除则修改标记为trueelse if(!node.isDelete()){node.setDelete(true);}}/** * 从根节点寻找最小节点 * @return 最小节点 */public TreeNode<T> findMin(){return this.findMin(root);}/** * 递归寻找最小节点 * 先找到最小节点,再根据是否被删除进行后续处理 * @param node 树根节点 * @return 最小节点 */public TreeNode<T> findMin(TreeNode<T> node){if(node == null){return null;}else if(node.getLeft() == null)//找到最小节点{//1.未被删除则为最小节点if(!node.isDelete()){return node;}//2.已被删除进行后续判断else{//2.1若右子节点不为空,则在右子树中寻找最小节点if(node.getRight() != null){return this.findMin(node.getRight());}//2.2若右节点为空并且父节点为空else if(node.getFather() == null){return null;}//2.3若右节点为空并且父节点不为空else{TreeNode<T> father = node.getFather();//2.3.1取得下一个较大的父节点while(father.getLeft() != node && father != null){node = father;father = father.getFather();}//2.3.2若父节点不为空if(father != null){father.setLeft(null);TreeNode<T> min = this.findMin(father);node.setLeft(node);return min;}//2.3.3若父节点为空else{return null;}}}}//递归寻找最小节点else{return this.findMin(node.getLeft());}}}
总结:懒惰删除方便了删除方法,省去了删除的额外操作,也方便了添加节点,当想要添加的节点已经处于被删除状态时,只需要修改删除标志即可。

懒惰删除比较麻烦的处理是在findMin和findMax两个方法中,由于两者相似,例子中只给出了findMin的实现,需要进行一系列周全的考虑,很是繁琐。其实可以通过给每个节点设置上下节点这种方式,来简化findMin和findMax这两个方法,相当于构建有序的链表。

0 0
原创粉丝点击