public class test {
public static void main(String[] args) {
Node root = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
Tree tree = new Tree();
tree.root = root;
root.setLeft(node2);
root.setRight(node3);
node2.setLeft(node4);
node2.setRight(node5);
node3.setLeft(node6);
tree.indixThread(root);
tree.throughIndixThread(root);
}
}
class Tree{
// 自己的线索二叉树
public Node root;
public Node pre = null;
public Tree(){
}
// 可以进行中序线索化和不使用递归的中序遍历
public void indixThread(Node node){
if(node==null){
return ;
// 退出
}
// 左中右
indixThread(node.getLeft());
// 来中 前 后
if(node.getLeft()==null){
node.setLeft(pre);
node.setLefttype(1);
}
if(pre!=null&&pre.getRight()==null){
pre.setRight(node);
pre.setRighttype(1);
}
// 更新
pre = node;
// 后
indixThread(node.getRight());
}
// 进行线索二叉树的中序遍历
public void throughIndixThread(Node node){
while(node!=null){
while(node.getLefttype()==0){
node = node.getLeft();
}
System.out.println(node);
while(node.getRighttype()==1){
node = node.getRight();
System.out.println(node);
}
node = node.getRight();
}
}
}
class Node{
// 节点类 需要val left right leftType rightType
int val;
Node left;
Node right;
@Override
public String toString() {
return "Node{" +
"val=" + val +
'}';
}
int lefttype;
int righttype;
public Node(int val) {
this.val = val;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public int getLefttype() {
return lefttype;
}
public void setLefttype(int lefttype) {
this.lefttype = lefttype;
}
public int getRighttype() {
return righttype;
}
public void setRighttype(int righttype) {
this.righttype = righttype;
}
}
线索二叉树是用二叉树中多余的 n+1 个指针来构建当前节点的前序和后继的过程 下面我来解释一下如何从普通的二叉树构建成线索二叉树以及不使用递归来进行线索二叉树的中序遍历
public void indixThread(Node node){
if(node==null){
return ;
// 退出
}
// 左中右
indixThread(node.getLeft());
// 来中 前 后
if(node.getLeft()==null){
node.setLeft(pre);
node.setLefttype(1);
}
if(pre!=null&&pre.getRight()==null){
pre.setRight(node);
pre.setRighttype(1);
}
// 更新
pre = node;
// 后
indixThread(node.getRight());
}
我们的tree类定义了一个pre 这个就是当前节点按照遍历的顺序的前一个节点 当我们遍历到第一个元素的时候 它是没有前一个节点的 因为它是遍历的第一个 所以它的前一个节点就是null
我们初始化pre的时候就为null
我们有了node 当前节点和 pre上一个节点 就可以判断能不能搭桥
// 由于是中序遍历 我们需要先左 再中右
indixThread(node.left);
if(node.left==null) 当前节点没有左指针 就利用这个节点指向前一个节点
node.setLeft(pre)
在判断前一个节点
if(pre!=null&&pre.right==null){
pre.setRight(node)
}
这时 我们正式完成了指针的利用 需要进入到下一个节点 所以就需要更新pre的值
pre = node;
最后 进入到右子树进行遍历
indixThread(node.right);
public void throughIndixThread(Node node){
while(node!=null){
while(node.getLefttype()==0){
node = node.getLeft();
}
System.out.println(node);
while(node.getRighttype()==1){
node = node.getRight();
System.out.println(node);
}
node = node.getRight();
}
}
进行线索二叉树的无递归遍历
我们首先要找到第一个元素 由于是中序遍历 所以它的特点是在左子树第一个leftType为1的地方
因为我们设置它的前序是null
使用while来寻找 直到找到 打印出这个节点
当right的type为1时 right就是下一个节点 我们可以直接打印
while(node.getRightType()==1){
node = node.right();
sout(node);
}
当出循环的时候 就来到了中间的节点 因为它本来就有右子树 所以righttype为0
我们需要进入右子树再进行中序遍历的逻辑 所以
node = node.getRight(); 此时停手 进入下一轮循环
相当于进入右子树后在根据中序遍历的逻辑进行判断.