星空网 > 软件开发 > Java

线索二叉树

1. 基本概念

      在链式存储中,发现二叉链表中存在大量的空指针,如果利用这些空指针指向其直接前驱或后继的指针,则可以更方便地运用某些二叉树操作算法。二叉树的线索化,是为了加快查找结点前驱和后继的速度。

      在有N个结点的二叉树中,存在N+1个空指针。每个叶结点有2个空指针,度为1的结点有1个空指针,总的空指针为2N0+N1,又有N0=N2+1,所以总的空指针为N0+N1+N2+1=N+1。

      二叉树线索化规则:若无左子树,令lchild指向其前驱结点;若无右子树,令rchild指向其后继结点。如图,增加两个标志域,用来表明当前指针指向左右结点还是前驱后继结点。

 线索二叉树

其中标志位含义为:

 线索二叉树

线索二叉树的结点:

private class Node{  int data;  Node lchild, rchild;  int ltag = 0, rtag = 0;}

      以这种结点构成的二叉链表作为二叉树的存储结构,叫做线索链表,其中指向前驱和后继的指针,叫做线索,加上线索的二叉树叫做线索二叉树,对二叉树以某种次序遍历使其变为线索二叉树的过程叫做线索化

2. 二叉树的构造及线索化

      构造:直接使用完全二叉树序列递归创建二叉树,不存在的使用0,这里不再赘述。直接给出代码。

public class ThreadTree {    private Integer[] nodes; // 存储完全二叉树序列  private int n; // 树结点数  Node root; // 根结点  Node pre; // 前一个访问的结点  private class Node{    int data;    Node lchild, rchild;    int ltag = 0, rtag = 0;  }    public ThreadTree(){    System.out.println("输入一个完全二叉树序列,不存在的结点用0代替,使用逗号隔开:");//    String[] ins = StdIn.readString().split(",");    String[] ins = "1,2,3,0,4,0,5".split(",");    nodes = new Integer[ins.length];    for (int i = 0; i < ins.length; i++) {      nodes[i] = Integer.valueOf(ins[i]);    }    n = ins.length;    root = build(1);    TreeUtil.print(depth(root), n, nodes);  }    /**   * 递归创建一棵二叉树   * <p>   * 使用完全二叉树序列   */  public Node build(int index){    if(index > n) {      return null;    }    if(nodes[index-1]==0){      return null;    }    Node node = new Node();    node.data = nodes[index-1];    node.lchild = build(2 * index);    node.rchild = build(2 * index + 1);    return node;  }}

      线索化一个二叉树其实就是遍历一次二叉树,遍历过程中,检查当前结点左右指针是否为空,若为空,将它们改为指向前驱或后继结点。

      以中序遍历为例,那么结点的前驱和后继的结点就是二叉树中序遍历序列中的前后结点

算法描述:node指向当前结点,pre指向前一个访问的结点

(1)若node的左孩子为空,则修改左指针指向pre,置ltag为1

(2)若pre不为空,且不存在右孩子,则修改右指针指向node,置rtag为1

(3)使pre指向刚刚访问过的结点node,即pre = node

public void inThreaded(){  inThreaded(root);  pre.rchild = null; // 单独处理下最后一个结点  pre.rtag = 1;}/** * 中序线索化一个二叉树 */public void inThreaded(Node node){  if (node != null) {    inThreaded(node.lchild); // 线索化左子树,找到左侧一个没有左孩子的结点    if(node.lchild == null){ // 左孩子为空      node.lchild = pre; // 修改指向其前驱结点      node.ltag = 1; // 修改标志位    }    if(pre != null && pre.rchild == null){ // 如果前一个访问的结点不为空,且没有右孩子      pre.rchild = node; // 修改指向其后继结点      pre.rtag = 1; // 修改标志位    }    pre = node;    inThreaded(node.rchild); // 线索化右子树  }}

3. 线索化的遍历

     中序线索化二叉树主要目的就是加快访问前驱和后继的速度,这种遍历就不需要借助栈,因为结点中隐含了前驱和后继结点的信息。不含头结点的线索二叉树遍历算法如下:

(1)首先找到中序线索二叉树中的第一个结点,左侧没有左孩子的结点,不一定是叶结点,根据ltag标志为判断

(2)找结点的后继结点,根据rtag判断

/** * 中序线索二叉树遍历,非递归 * @param node */public void inOrder(Node node){  Node tmp = firstNode(node);  while(tmp != null){    System.out.print(tmp.data+" ");    tmp = nextNode(tmp);  }}/** * 求第一个结点 * @param node * @return */public Node firstNode(Node node){  while(node.ltag == 0){ // 最左下结点,不一定是叶子结点    node = node.lchild;  }  return node;}/** * 求后继结点 * @param node * @return */public Node nextNode(Node node){  if(node.rtag == 0){ // 存在右孩子    return firstNode(node.rchild); // 以此结点为根找最左下结点  }  return node.rchild; // rtag = 1 直接返回后继}/** * 倒序非递归遍历 * @param node */public void inOrderO(Node node){  Node tmp = lastNode(node);  while(tmp != null){    System.out.print(tmp.data+" ");    tmp = preNode(tmp);  }}/** * 求最后一个结点 * @return */public Node lastNode(Node node){  while(node.rtag == 0){    node = node.rchild;  }  return node;}/** * 求前驱结点 * @return */public Node preNode(Node node){  if(node.ltag == 0){    return lastNode(node.lchild);  }  return node.lchild;}

4. 测试

public static void main(String[] args) {  ThreadTree tree = new ThreadTree();  System.out.print("二叉树的结点总数:" + tree.nodes(tree.root));  System.out.print("\n中序遍历递归:");  tree.inOrderRecur(tree.root);  tree.inThreaded();  System.out.print("\n线索化...\n中序线索化二叉树遍历非递归:");  tree.inOrder(tree.root);  System.out.print("\n非递归遍历(倒序):");  tree.inOrderO(tree.root);}

4.1 输出结果

线索二叉树

 




原标题:线索二叉树

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

中国到印尼物流专线:https://www.goluckyvip.com/tag/98707.html
印尼到中国物流专线:https://www.goluckyvip.com/tag/98708.html
海南到驻马店物流:https://www.goluckyvip.com/tag/98709.html
法国封城:https://www.goluckyvip.com/tag/9871.html
驻马店到海南物流:https://www.goluckyvip.com/tag/98710.html
南湾物流:https://www.goluckyvip.com/tag/98711.html
长治婚庆女司仪和主持人:https://www.vstour.cn/a/366176.html
北京丰台区水上乐园哪家好玩?:https://www.vstour.cn/a/366177.html
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流