线索二叉树是利用叶子结点的左右子树结点指向自己的前驱后继
利用浪费的空间让树更加效率
先创建二叉树结点:
public class node { private int no; private String name; private node Left; private node Right; /** * NoLeft和NoRight表示一个结点的左右节点是否有结点 * 如果有则表示1 没有则为0 */ private int NoLeft; private int NoRight; public node(int no, String name) { this.no = no; this.name = name; } /** * 删除结点 * @param no */ public void DelNode(int no){ /* 判断左子树是否为空,并且左子树的No是否等于要删除的no如果相等则把左子树置为空 删掉左子树。 如果不相等那就在下面递归 */ if(this.Left!=null&&this.Left.getNo()==no){ this.Left=null; return; } /* 判断右子树和左子树同理 */ if(this.Right!=null&&this.Right.getNo()==no){ this.Right=null; return; } /* 判断子树是否为空 继续递归下 直到直到叶子结点 */ if(this.Left!=null){ this.Left.DelNode(no); } if(this.Right!=null){ this.Right.DelNode(no); } } /** * 中序遍历 */ public void MidSelect(){ /* 判断结点子树是否为空 同时也是递归的终止条件 */ if(this.Left!=null) this.Left.MidSelect();//向左递归 System.out.println(this);//输出此结点的数据 if(this.Right!=null) this.Right.MidSelect();//向右递归 } /** * 根据编号中序查找 */ public node MidFound(int no){ /* 设计辅助结点,用来接收返回值 也是用来返回的值 */ node temp=null; /* 如果左子树有结点则递归左子树接收返回值 */ if(this.Left!=null){ temp=this.Left.MidFound(no); } /* 用来递归左子树的结点 如果没找到则temp为null */ if(temp!=null) return temp; /* 判断该结点是否为要查找的值结点 */ if(this.getNo()==no){ return this; } if(this.Right!=null){ temp=this.Right.MidFound(no); } /* 用来递归右子树的结点 如果没找到则temp为null */ return temp; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public node getLeft() { return Left; } public void setLeft(node left) { Left = left; } public node getRight() { return Right; } public void setRight(node right) { Right = right; } public int getNoLeft() { return NoLeft; } public void setNoLeft(int noLeft) { NoLeft = noLeft; } public int getNoRight() { return NoRight; } public void setNoRight(int noRight) { NoRight = noRight; } @Override public String toString() { return "node{" + "no=" + no + ", name='" + name + '\'' + '}'; } }
创建一个线索二叉树的建立:
public class BinaryTree { /** * root为根结点 */ private node root; /** * pre是用来指向前驱的结点的继辅助指针 */ private node pre; public void setRoot(node root) { this.root = root; } /** * 普通二叉树转线索二叉树 */ /** * 重载方法 方便试用 */ public void ClueNode(){ this.ClueNode(this.root); } public void ClueNode(node n){ if(n==null) return; /* 中序转化 先线索化左子树一直递归到左子树 */ ClueNode(n.getLeft()); //找到叶子结点没有前驱后继都是Null /* 找到叶子结点后他的前驱肯定是空的 那么pre也是null直接赋值 并且设置为有结点状态 中序遍历的最左边的叶子前驱是没有东西的 其他结点同理 */ if(n.getLeft()==null){ n.setLeft(pre); n.setNoLeft(1); } //如果该结点pre不为空那说明该结点的前驱有了 //那就可以赋值后继 /** * 那就可以吧此结点设置为pre来当下个结点的前驱也就是此结点的后继 * 如果pre不为空那表示已经有结点了 * 那就把pre设置为此结点来表示下个结点的前驱 * 有点类似于链表的辅助temp遍历链表 */ if(pre!=null&&pre.getRight()==null){ pre.setRight(n); pre.setNoRight(1); } //迭代处理下一个结点 pre=n; /* 左子树处理完然后继续递归右子树 */ ClueNode(n.getRight()); } /** * 遍历线索化二叉树 */ public void ClueList(){ //创建临时结点用来迭代每个结点 node temp = this.root; while(temp!=null){ //中序查询先从左子树查 //循环从根结点出发根结点的NoLeft是等于0的 //而最左子树的结点的NoLeft是等于1的 //也就是说到最左子树的时候停下并且打印 while(temp.getNoLeft()==0){ temp=temp.getLeft(); } System.out.println(temp); //现在temp是等于最左边的子树然后寻找后继就可以了 //叶子结点的NoRight如果等于1那就表示有后继 //如果一个结点拥有左右子树的话那这个结点的前驱后继是等于0的 //也就是从这个等于0的结点进行 /* //继续循环找 temp=temp.getRight(); */ while(temp.getNoRight()==1){ temp=temp.getRight(); System.out.println(temp); } //继续循环找 temp=temp.getRight(); } } }