简介
在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化。
n个结点的二叉链表中含有n+1 【公式 2n-(n-1)=n+1】 个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")
这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种
一个结点的前一个结点,称为前驱结点,一个结点的后一个结点,称为后继结点.
代码
结点对象
class Node2 { int value; private int leftType; private int rightType; public Node2 parent; public Node2 getParent() { return parent; } public void setParent(Node2 parent) { this.parent = parent; } 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; } public Node2(int value) { this.value = value; } private Node2 left; private Node2 right; public int getValue() { return value; } public void setValue(int value) { this.value = value; } public Node2 getLeft() { return left; } public void setLeft(Node2 left) { this.left = left; } public Node2 getRight() { return right; } public void setRight(Node2 right) { this.right = right; } @Override public String toString() { return "Node2{" + "value=" + value + '}'; } /** * 如果添加的结点比父结点小,就添加到父结点的左节点,反之添加到父结点的右结点(二叉排序树) * @param node 添加的结点对象 */ public void add(Node2 node) { if (node == null) { return; } if (this.value > node.value) { if (this.left == null) { this.left = node; } else { this.left.add(node); } } else { if (this.right == null) { this.right = node; } else { this.right.add(node); } } } }
树
class ThreadedBinaryTree { private Node2 root; private Node2 pre = null; public Node2 getRoot() { return root; } /** * 如果添加的结点比父结点小,就添加到父结点的左节点,反之添加到父结点的右结点(二叉排序树) * @param node 添加的结点对象 */ public void add(Node2 node) { if (root == null) { root = node; } else { root.add(node); } } //中序线索化 public void threadedNodes(Node2 node) { if (node == null) { return; } threadedNodes(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; threadedNodes(node.getRight()); } //中线索化二叉树遍历 public void threadedList() { Node2 node = root; 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(); } } //前序线索化 public void preorder(Node2 node) { if (node == null) { return; } if (node.getLeft() == null) { node.setLeft(pre); node.setLeftType(1); } if (pre != null && pre.getRight() == null) { pre.setRight(node); pre.setRightType(1); } pre = node; if (node.getLeftType() == 0) { preorder(node.getLeft()); } if (node.getRightType() == 0) { preorder(node.getRight()); } } //遍历前序线索化二叉树 public void preorderList() { Node2 node = root; while (node != null) { while (node.getLeftType() == 0) { System.out.println(node); node = node.getLeft(); } System.out.println(node); while (node.getRightType() == 1) { node = node.getRight(); System.out.println(node); } node = node.getRight(); } } /** * 注意,后序遍历要设置每个结点的父结点!!! * @param node 开始的结点 */ //后序线索化二叉树 public void postorder(Node2 node) { if (node == null) { return; } if (node.getLeftType() == 0) { postorder(node.getLeft()); } if (node.getRightType() == 0) { postorder(node.getRight()); } if (node.getLeft() == null) { node.setLeft(pre); node.setLeftType(1); } if (pre != null && pre.getRight() == null) { pre.setRight(node); pre.setRightType(1); } pre = node; } //后序线索化二叉树遍历 public void postorderList() { Node2 node = root; while ( node != null && node.getLeftType() == 0 ) { node = node.getLeft(); } while ( node != null ) { //右节点是线索 if (node.getRightType() == 1) { System.out.print(node + ", "); pre = node; node = node.getRight(); } else { //如果上个处理的节点是当前节点的右节点 if (node.getRight() == pre) { System.out.print(node + ", "); if (node == root) { return; } pre = node; node = node.getParent(); } else { //如果从左节点的进入则找到有子树的最左节点 node = node.getRight(); while ( node != null && node.getLeftType() == 0 ) { node = node.getLeft(); } } } } } }
测试
ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree(); int[] arr = {1,7,2,5,9,6}; for (int i : arr) { threadedBinaryTree.add(new Node2(i)); } threadedBinaryTree.threadedNodes(threadedBinaryTree.getRoot()); threadedBinaryTree.threadedList();