中序线索二叉树

来源:互联网 发布:网络捕鱼电玩 编辑:程序博客网 时间:2024/05/16 05:12

1.首先创建线索节点类

public class ClueNode <T>{private T value;//节点值private ClueNode<T> left;//左节点private ClueNode<T> right;//右节点private boolean isLeftClue;//左线索标志private boolean isRightClue;//右线索标志public ClueNode(T value){this.value = value;}public boolean isLeftClue() {return isLeftClue;}public void setLeftClue(boolean isLeftClue) {this.isLeftClue = isLeftClue;}public boolean isRightClue() {return isRightClue;}public void setRightClue(boolean isRightClue) {this.isRightClue = isRightClue;}public T getValue() {return value;}public void setValue(T value) {this.value = value;}public ClueNode<T> getLeft() {return left;}public void setLeft(ClueNode<T> left) {this.left = left;}public ClueNode<T> getRight() {return right;}public void setRight(ClueNode<T> right) {this.right = right;}}
2.接着创建线索树类

public class ClueTree <T extends Comparable<? super T>>{private ClueNode<T> root;/** * 线索二叉树的优点,非递归打印,节省栈空间 */public void print(){ClueNode<T> temp = root;if(temp != null){while(!temp.isLeftClue()){temp = temp.getLeft();}while(temp != null){System.out.print(temp.getValue() + "\t");if(temp.isRightClue()){temp = temp.getRight();}else{temp = temp.getRight();while(!temp.isLeftClue()){temp = temp.getLeft();}}}}}/** * 从根节点开始判断节点存在性 * @param value * @return */public boolean contains(T value){if(root != null){return contains(value, root, false);}return false;}/** * 递归判断节点存在性 * @param value 节点值 * @param node 树根结点 * @param clueFlag 节点是否线索 * @return */private boolean contains(T value, ClueNode<T> node, boolean clueFlag){if(clueFlag){return false;}int result = value.compareTo(node.getValue());if(result < 0){return contains(value, node.getLeft(), node.isLeftClue());}else if(result > 0){return contains(value, node.getRight(), node.isRightClue());}else{return true;}}/** * 递归插入方法 * @param value 插入值 * @param node 树根结点 * @param pre 左线索 * @param next 右线索 * @param clueFlag 节点是否为线索 * @return 树根结点 */private ClueNode<T> insert(T value, ClueNode<T> node, ClueNode<T> pre, ClueNode<T> next, boolean clueFlag){//1.若为线索节点,则创建新节点,线索由参数传入if(clueFlag){ClueNode<T> newNode = new ClueNode<T>(value);newNode.setLeft(pre);newNode.setRight(next);newNode.setLeftClue(true);newNode.setRightClue(true);return newNode;}int result = value.compareTo(node.getValue());//2.若小于根节点,往左子树插入if(result < 0){ClueNode<T> left = insert(value, node.getLeft(), node.getLeft(), node, node.isLeftClue());node.setLeft(left);node.setLeftClue(false);}//3.若大于根节点,往右子树插入else if(result > 0){ClueNode<T> right = insert(value, node.getRight(), node, node.getRight(), node.isRightClue());node.setRight(right);node.setRightClue(false);}return node;}/** * 从树根结点开始插入 * @param value */public void insert(T value){if(root == null){root = insert(value, root, null, null, true);}else{root = insert(value, root, null, null, false);}}/** * 递归方法实现删除功能 * @param value 节点值 * @param node 树根结点 * @param clueFlag 判断节点是否为线索 * @param childFlag 判断节点类型,假为左节点,真为右节点 * @return 树根结点 */private ClueNode<T> remove(T value, ClueNode<T> node, boolean clueFlag, boolean childFlag){//1.若为线索节点,直接返回线索节点if(clueFlag){return node;}int result = value.compareTo(node.getValue());//2.若与根节点相等,开始进行删除操作if(result == 0){//2.1若子节点均为线索,根据该节点的节点类型,返回不同的线索节点if(node.isLeftClue() && node.isRightClue()){if(childFlag){node = node.getRight();}else{node = node.getLeft();}}//2.2若子节点都不为线索else if(!node.isLeftClue() && !node.isRightClue()){//2.2.1缓存右节点ClueNode<T> rightTemp = node.getRight();//2.2.2取得右子树最小节点并设值ClueNode<T> min = findMin(rightTemp, false);node.setValue(min.getValue());//2.2.3从右子树删除最小节点并连接右子树ClueNode<T> temp = remove(min.getValue(), rightTemp, false, true); node.setRight(temp);//2.2.4若右节点的子节点均为线索,则更改节点右线索标志if(rightTemp != null && rightTemp.isLeftClue() && rightTemp.isRightClue() && rightTemp != temp){node.setRightClue(true);}}//2.3若其中一个节点为线索else{//2.3.1若左边为线索if(node.isLeftClue()){//2.3.2修改关联节点的线索ClueNode<T> min = findMin(node.getRight(), false);min.setLeft(node.getLeft());node = node.getRight();}//2.3.3若右边为线索else{//2.3.4修改关联节点的线索ClueNode<T> max = findMax(node.getLeft(), false);max.setRight(node.getRight());node = node.getLeft();}}}//3.若小于根节点,则从左子树删除else if(result < 0){ClueNode<T> leftTemp = node.getLeft();ClueNode<T> left = remove(value, leftTemp, node.isLeftClue(), false);node.setLeft(left);if(leftTemp != null && leftTemp.isLeftClue() && leftTemp.isRightClue() && leftTemp != left){node.setLeftClue(true);}}//4.若大于根节点,则从右子树删除else{ClueNode<T> rightTemp = node.getRight();ClueNode<T> right = remove(value, rightTemp, node.isRightClue(), true);node.setRight(right);if(rightTemp != null && rightTemp.isLeftClue() && rightTemp.isRightClue() && rightTemp != right){node.setRightClue(true);}}return node;}/** * 从根节点开始删除 * @param value */public void remove(T value){if(root != null){root = remove(value, root, false, false);}}/** * 递归寻找最小节点 * @param node 树根结点 * @return 最小节点 */private ClueNode<T> findMin(ClueNode<T> node, boolean clueFlag){if(clueFlag){return null;}if(!node.isLeftClue()){return findMin(node.getLeft(), false);}else{return node;}}/** * 递归寻找最大节点 * @param node 树根结点 * @return 最大节点 */private ClueNode<T> findMax(ClueNode<T> node, boolean clueFlag){if(clueFlag){return null;}if(!node.isRightClue()){return findMax(node.getRight(), false);}else{return node;}}}

线索树的优点在于利用空闲的n+1个空指针来存储前驱和后继节点,使其可以非递归有顺序地打印树,对于n很大时,可以有效节省栈空间,节省内存空间。

原创粉丝点击