线索二叉树和普通二叉树有所不同,线索二叉树的左孩子和右孩子位置都是满的,需要根据ltag和rtag来进行遍历。
首先,线索二叉树的数据结构为
public class ThreadBinaryTreeNode { private int data; //数据域,可自定义引用类型,整型等 private ThreadBinaryTreeNode lchild; //存放左孩子或者前驱 private ThreadBinaryTreeNode rchild; //存放右孩子或者后继 private int ltag; //为1代表存放的是前驱 为0代表存放的是左孩子 private int rtag; //为1 代表存放的是后继 为0代表存放的是右孩子 public int getData() { return data; } public void setData(int data) { this.data = data; } public ThreadBinaryTreeNode getLchild() { return lchild; } public void setLchild(ThreadBinaryTreeNode lchild) { this.lchild = lchild; } public ThreadBinaryTreeNode getRchild() { return rchild; } public void setRchild(ThreadBinaryTreeNode rchild) { this.rchild = rchild; } public int getLtag() { return ltag; } public void setLtag(int ltag) { this.ltag = ltag; } public int getRtag() { return rtag; } public void setRtag(int rtag) { this.rtag = rtag; } }
然后先创建一个普通二叉树,然后对该二叉树进行线索化。所谓线索化就是将树中的空指针域(左孩子为空或右孩子为空)存放前驱或者后继的过程
public class App { public static ThreadBinaryTreeNode pre = null; //声明一个全局结点,便于线索化 public static final int THREAD = 1; //代表线索结点 public static final int LINK =0; //代表孩子结点 public static void main(String[] args){ ThreadBinaryTreeNode list = createTree(); threadTree(list); traverseBinaryTreeNode(list); } /** * 该二叉树是没有设头结点的 * 1 * 2 3 * 4 * 创建二叉树 * @return */ private static ThreadBinaryTreeNode createTree(){ ThreadBinaryTreeNode node1 = new ThreadBinaryTreeNode(); node1.setData(1); ThreadBinaryTreeNode node2 = new ThreadBinaryTreeNode(); node2.setData(2); ThreadBinaryTreeNode node3 = new ThreadBinaryTreeNode(); node3.setData(3); ThreadBinaryTreeNode node4 = new ThreadBinaryTreeNode(); node4.setData(4); node1.setLchild(node2); node1.setRchild(node3); node2.setRchild(node4); return node1; } /** * 前序遍历线索二叉树 * @param list */ private static void traverseBinaryTreeNode(ThreadBinaryTreeNode list){ if(list == null){ return; }else{ System.out.println(list.getData()+" ltag: " + list.getLtag() + " rtag: " + list.getRtag()); if(list.getLtag() == LINK) //相对于不同二叉树而言 这步是必要的 因为线索二叉树 左孩子肯定不为空 // 我们要遍历的是左孩子 即ltag为0 traverseBinaryTreeNode(list.getLchild()); if(list.getRtag() == LINK) //相对于不同二叉树而言 这步是必要的 因为线索二叉树 右孩子肯定不为空 //我们要遍历的是右孩子 即rtag为0 traverseBinaryTreeNode(list.getRchild()); } } /** * 该方法主要讨论的是 该结点的左孩子 和 上一个结点的右孩子 * 因为该为二叉树没有头结点 所以 pre初始化为空 * @param list */ //中序对二叉树进行线索化 private static void threadTree(ThreadBinaryTreeNode list){ if(list != null){ threadTree(list.getLchild()); if(list.getLchild() == null){ //之所以不讨论当左孩子不为空 是因为 ltag默认为0 list.setLtag(THREAD); list.setLchild(pre); } if(pre != null && pre.getRchild() == null){ //之所以不套路右孩子不为空 是因为rtag默认为0 pre.setRtag(THREAD); pre.setRchild(list); } pre = list; threadTree(list.getRchild()); } } }
结果:
1 ltag: 0 rtag: 0
2 ltag: 1 rtag: 0
4 ltag: 1 rtag: 1
3 ltag: 1 rtag: 0