线索化二叉树
简介
在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化。
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();