线索二叉树的建立及其遍历访问操作
2017-04-16 17:04
459 查看
线索二叉树(中序),建立、访问
对于线索二叉树有先序、中序、后序三种,但是只有中序线索二叉树才能获得任意节点的前驱和后继节点(实际上二叉树任意节点的访问均是访问的某一棵树的根节点),那么只有中序遍历生成的中序线索二叉树是先访问左子树,根节点,右子树,而先序线索二叉树,是先访问根节点,所以只能从先序线索二叉树中得到节点的后继结点,同理只能从后序线索二叉树得到节点的前驱结点(最后访问根节点)。
对于线索二叉树有先序、中序、后序三种,但是只有中序线索二叉树才能获得任意节点的前驱和后继节点(实际上二叉树任意节点的访问均是访问的某一棵树的根节点),那么只有中序遍历生成的中序线索二叉树是先访问左子树,根节点,右子树,而先序线索二叉树,是先访问根节点,所以只能从先序线索二叉树中得到节点的后继结点,同理只能从后序线索二叉树得到节点的前驱结点(最后访问根节点)。
package ccnu.offer.tree; public class Demo03 { static ThreadNode pre = null; public static void main(String[] args) { ThreadNode root = createBiTreeByPreIn(new int[]{1, 2, 4, 3, 5}, new int[]{2, 4, 1, 5, 3}, 0, 0, 5); ThreadNode inRoot = createInThreadBiTree(root); inOrder(inRoot); System.out.println(); inOrderByReverse(inRoot); } public static ThreadNode createBiTreeByPreIn(int[] pre, int[] in, int preBegin, int inBegin, int len){ if(pre == null || in == null || pre.length != in.length || pre.length == 0 || in.length == 0){ return null; } if(len <= 0){ return null; } ThreadNode root = new ThreadNode(pre[preBegin]); int rootIndex; for(rootIndex = 0; in[rootIndex] != pre[preBegin]; rootIndex++); root.lchild = createBiTreeByPreIn(pre, in, preBegin + 1, inBegin, rootIndex - inBegin); root.rchild = createBiTreeByPreIn(pre, in, preBegin + (rootIndex - inBegin) + 1, rootIndex + 1, len - (rootIndex - inBegin) - 1); return root; } public static ThreadNode createInThreadBiTree(ThreadNode root){ // ThreadNode pre = null; if(root != null){ inThreadBiTree(root); pre.rtag = 1; // pre指向中序遍历的最后一个节点 pre.rchild = null; // 没有后继节点 } return root; } public static void inThreadBiTree(ThreadNode root){ if(root != null){ inThreadBiTree(root.lchild); // 第一步:线索化当前root的左子树 // 第二步:访问当前root节点,如果当前root节点的左孩子为空,那么root的lchild就应该指向其中序序列前驱结点,同时如果root的前一个访问节点(中序序列)pre的rchild为空,那么pre的rchild就应该指向当前root if(root.lchild == null){ root.ltag = 1; // root的lchild指向root的中序遍历前驱结点 root.lchild = pre; // 当前节点的中序遍历前驱结点为中序遍历中的上一个访问的节点 } if(pre != null && pre.rchild == null){ // pre != null 因为第一个访问节点没有前驱 pre.rtag = 1; // 中序遍历上一个访问的节点pre指向其中序遍历的后继节点,即当前节点root pre.rchild = root; } pre = root; // 将刚才访问的节点保存,注意访问最后一个节点时,pre会指向它 inThreadBiTree(root.rchild); // 第三步:线索化当前root的右子树 } } public static void inOrder(ThreadNode root){ // 中序线索二叉树中序遍历 if(root == null){ return; } ThreadNode firstNode = firstNode(root); ThreadNode p = firstNode; while(p != null){ System.out.print(p.data + " "); p = nextNode(p); } } public static void inOrderByReverse(ThreadNode root){ if(root == null){ return; } ThreadNode lastNode = lastNode(root); ThreadNode p = lastNode; while(p != null){ System.out.print(p.data + " "); p = previousNode(p); } } public static ThreadNode firstNode(ThreadNode root){ // 得到中序遍历序列(以root作为根节点的树)的第一个节点--->没有左孩子的root子树就是中序序列的第一个节点 if(root == null){ return null; } while(root.ltag == 0){ // 存在左孩子 root = root.lchild; } return root; } public static ThreadNode lastNode(ThreadNode root){ // 得到中序遍历序列(以root作为根节点的树)的最后一个节点--->没有右孩子的root子树就是中序序列的最后一个节点 if(root == null){ return null; } while(root.rtag == 0){ // root.rtag == 0不等价于root.rchild != null(不一定存在右孩子),因为rchild可能指向其后继节点 root = root.rchild; } return root; // } public static ThreadNode previousNode(ThreadNode p){ if(p == null){ return null; } if(p.ltag == 0){ // p存在左孩子 return lastNode(p.lchild); }else{ // 没有左孩子 return p.lchild; // lchild直接指向其前驱结点 } } public static ThreadNode nextNode(ThreadNode p){ // 得到p节点的中序遍历序列的后继节点 if(p == null){ return null; } if(p.rtag == 0){ // 存在右孩子,那么找到p的后继节点等价于找到p.rchild的中序遍历的第一个节点 return firstNode(p.rchild); }else{ // 木有右孩子,那么p节点的rchild直接就指向其后继节点 return p.rchild; } } private static class ThreadNode{ private int data; private int ltag = 0; // 默认lchild指向左孩子 private int rtag = 0; // 默认rchild指向右孩子 private ThreadNode lchild = null; private ThreadNode rchild = null; public ThreadNode(int data){ this.data = data; } } }
相关文章推荐
- 数据结构类型定义及基本操作汇总(二)-- 二叉树及其遍历
- javascript操作dom 建立 增加 删除 克隆 访问节点
- C++ 单链表的建立,插入数值,删除数值,排序,遍历,和分割操作
- 算法导论中十二章C++实现二叉查找树建立,插入,删除,遍历操作
- CImage访问像素及其像素操作总结
- 建立JSP操作以提高数据库访问的效率
- 二叉树基本操作的递归实现(二叉树建立,先序,中序,后序,深度的递归遍历。广度优先,高度优先的非递归遍历)
- 线索二叉树的建立和遍历
- 建立中序线索二叉树并遍历
- 基于邻接表的图的基本操作(建立,遍历)
- 线索二叉树及其遍历(前根,后根和中序)
- 如何建立JSP操作用以提高数据库访问效率
- javascript操作dom 建立 增加 删除 克隆 访问节点
- 二叉树建立与遍历递归操作c++实现
- struts2操作json成字符串格式错误被转义及其前台访问json对象的方法
- Abstract Class的建立类及其成员及方法的调用关系访问等的实例演示
- 数据库访问及其基本操作(sql server和添加删除查找替换)
- Properties的用法及其操作属性文件(遍历Key)
- [数据结构] 二叉树的建立及其基本操作
- 图的BFS遍历中标记已访问的节点操作影响效率