学习数据结构和算法的日常Demo
二叉树遍历存在的问题
线索二叉树基本介绍
中序线索二叉树思路分析
代码实现
public class TreeNode {
private int value;
private TreeNode left;
private TreeNode right;
// 如果leftType为0,表示指向左子树,如果为1表示指向前驱节点(rightType同)
private int leftType;
private int rightType;
public TreeNode(int value) {
this.value = value;
}
@Override
public String toString() {
return "TreeNode{" +
"value=" + value +
'}';
}
public int getValue() {
return value;
}
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 void setValue(int value) {
this.value = value;
}
public TreeNode getLeft() {
return left;
}
public void setLeft(TreeNode left) {
this.left = left;
}
public TreeNode getRight() {
return right;
}
public void setRight(TreeNode right) {
this.right = right;
}
// 前序遍历
public void preOrder() {
// 输出父节点
System.out.print(this.value + " ");
// 递归左子树
if (this.left != null) {
this.left.preOrder();
}
// 递归右子树
if (this.right != null) {
this.right.preOrder();
}
}
// 中序遍历
public void infixOrder() {
// 递归左子树
if (this.left != null) {
this.left.infixOrder();
}
// 输出父节点
System.out.print(this.value + " ");
// 递归右子树
if (this.right != null) {
this.right.infixOrder();
}
}
// 后序遍历
public void postOrder() {
// 递归左子树
if (this.left != null) {
this.left.postOrder();
}
// 递归右子树
if (this.right != null) {
this.right.postOrder();
}
// 输出父节点
System.out.print(this.value + " ");
}
}
public class ThreadedBinaryTree {
private TreeNode root;
private TreeNode pre = null; // 线索化的前驱节点
public TreeNode getRoot() {
return root;
}
public void setRoot(TreeNode root) {
this.root = root;
}
// 对二叉树中序线索化
// node即为当前需要线索化的节点
public void threadedNodes(TreeNode node) {
if (node == null) {
return;
}
// 1.线索化左子树
threadedNodes(node.getLeft());
// 2.线索化当前节点
// 处理当前节点的前驱节点
if (node.getLeft() == null) {
// 让当前节点的左指针指向前驱节点
node.setLeft(pre);
// 修改当前左指针的指向类型
node.setLeftType(1);
}
// 处理后继节点
if (pre != null && pre.getRight() == null) {
// 前驱节点的右指针指向当前节点
pre.setRight(node);
// 修改前驱节点的右指针类型
pre.setRightType(1);
}
// 每处理一个节点,让当前节点是下一个节点的前驱节点
pre = node;
// 3.线索化右子树
threadedNodes(node.getRight());
}
// 遍历中序线索化二叉树
public void threadedList(){
// 定义一个变量,存储当前遍历到的节点
TreeNode node = root;
while(node!=null){
// 循环找到leftType == 1的节点
// 当leftType == 1,说明该节点是线索化处理后的
while (node.getLeftType() == 0){
node = node.getLeft();
}
// 打印当前节点
System.out.print(node.getValue()+" ");
// 如果当前节点的右节点指向后继节点,就一直输出
while (node.getRightType() == 1){
// 获取到当前节点的后继节点
node = node.getRight();
System.out.print(node.getValue()+" ");
}
// 替换这个遍历的节点
node = node.getRight();
}
}
// 前序遍历
public void preOrder() {
if (root != null) {
root.preOrder();
} else {
System.out.println("二叉树为空!");
}
}
public void infixOrder() {
if (root != null) {
root.infixOrder();
} else {
System.out.println("二叉树为空!");
}
}
public void postOrder() {
if (root != null) {
root.postOrder();
} else {
System.out.println("二叉树为空!");
}
}
}
// 测试类
public class ThreadedBinaryTreeDemo {
public static void main(String args[]) {
ThreadedBinaryTree tree = new ThreadedBinaryTree();
TreeNode root = new TreeNode(1);
TreeNode node1 = new TreeNode(3);
TreeNode node2 = new TreeNode(6);
TreeNode node3 = new TreeNode(8);
TreeNode node4 = new TreeNode(10);
TreeNode node5 = new TreeNode(14);
// 构建树
root.setLeft(node1);
root.setRight(node2);
node1.setLeft(node3);
node1.setRight(node4);
node2.setLeft(node5);
// 创建根节点
tree.setRoot(root);
/*
1
3 6
8 10 14
*/
tree.infixOrder();
System.out.println("中序遍历(线索化前)");
// 线索化二叉树
System.out.println("中序线索化:");
tree.threadedNodes(root);
// 测试,10号节点
System.out.println("10的前驱节点:" + node4.getLeft());
System.out.println("10的后继节点:" + node4.getRight());
// 当线索化二叉树后,不能使用原先的遍历方式
tree.threadedList();
System.out.println("中序遍历(线索化后)");
}
线索化二叉树关键点
// 代码片段
// 如果leftType为0,表示指向左子树,如果为1表示指向前驱节点
private int leftType;
// 如果rightType为0,表示指向右子树,如果为1表示指向前后继节点
private int rightType;
// 每处理一个节点,让当前节点是下一个节点的前驱节点
pre = node;
递归过程中,不断处理前驱节点和后继节点的指向