思路都写在注释里了
package com.www.demo20;
//二叉树结点
public class BinaryTreeNode {
private int data;
private BinaryTreeNode left;
private BinaryTreeNode right;
//true代表是线索
private boolean isLeftisClue;
private boolean isRightisClue;
public BinaryTreeNode(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public BinaryTreeNode getLeft() {
return left;
}
public void setLeft(BinaryTreeNode left) {
this.left = left;
}
public BinaryTreeNode getRight() {
return right;
}
public void setRight(BinaryTreeNode right) {
this.right = right;
}
public boolean isLeftisClue() {
return isLeftisClue;
}
public void setLeftisClue(boolean leftisClue) {
isLeftisClue = leftisClue;
}
public boolean isRightisClue() {
return isRightisClue;
}
public void setRightisClue(boolean rightisClue) {
isRightisClue = rightisClue;
}
@Override
public String toString() {
return "BinaryTreeNode{" +
"data=" + data +
'}';
}
}
package com.www.demo20;
//二叉树构建、线索化、遍历等
public class BinaryTree {
private BinaryTreeNode root = null, pre = null;
private int[] arr;
//创建类的对象时完成二叉树创建和线索化
public BinaryTree(int[] arr) {
this.arr = arr;
build();
clueTree();
}
//创建类的时候就构建,选择是按照顺序存储,也可以手动,也可以按照data值构建
private void build(){
if (arr == null || arr.length == 0){
System.out.println("无法构建二叉树");
return;
}
root = new BinaryTreeNode(arr[0]);
build(root,0);
}
private void build(BinaryTreeNode node,int index){
//给左节点赋值
if ((2*index + 1) < arr.length){
//代表认可此处结点的左节点可以被赋值
node.setLeft(new BinaryTreeNode(arr[2*index+1]));
build(node.getLeft(),2*index + 1);
}
//给右节点赋值
if ((2*index + 2) < arr.length){
//代表认可此处结点的右节点可以被赋值
node.setRight(new BinaryTreeNode(arr[2*index+2]));
build(node.getRight(),2*index + 2);
}
}
//中序线索化
private void clueTree(){
if (root == null){
System.out.println("无数据");
}
clueTree(root);
}
//中序线索化思路:1、给定一个二叉树,找到最左边所在的小树,处理左边,右边,回到小树的父树(父树是老父树的子树),最终回到根节点;
// 2、此树要处理的第一个节点node,把节点的前驱节点设置为处理此树之前的结点pre;
// 3、对于上一个处理的节点pre,如果非空并且右节点为空,那么pre的后继节点就是此时处理的节点;
// 4、将pre设置为此时处理的节点node,node的后继节点等下一次处理设置(到下一次时,node就相当于23中pre);
// 5、如果此节点有右节点,那么就去处理右边的节点,此时右边的节点就相当于一棵小树,再次重复1234;
private void clueTree(BinaryTreeNode node){//传进来的node是子树的中结点,左中右,要先找左节点
//1
if (node.getLeft() != null){//找到此子树要处理的第一个
clueTree(node.getLeft());
}
//2
if (node.getLeft() == null){//把此子树第一个要处理的结点,最左边的左指针指向前驱结点pre
node.setLeft(pre);
node.setLeftisClue(true);
}
//3
if (pre != null && pre.getRight() == null){//上一个处理的节点如果没有右节点,那么它的后继节点就是此刻处理的节点
// (意味着此刻处理的结点等到下一个处理节点时再设置)
pre.setRight(node);
pre.setRightisClue(true);
}
//4
pre = node;
//5
if (node.getRight() != null){
clueTree(node.getRight());//右节点不是空,则此右节点可以看成root等价,然后同样先处理左边
}
}
//中序遍历
public void inorderTraversal(){
if (root == null){
System.out.println("无数据");
return;
}
inorderTraversal(root);
}
private void inorderTraversal(BinaryTreeNode temp){
while (!temp.isLeftisClue()){//有左节点
temp = temp.getLeft();
}//从树的第一个节点开始
do {
System.out.println(temp.getData());
if (temp.isRightisClue()){//没有右节点,指针就移向后继节点
temp = temp.getRight();
}else{//没有后继节点有两种情况:1、有右节点;2、最后一个节点
temp = temp.getRight();//移向右节点
while (temp != null && !temp.isLeftisClue()){//如果不为空,右节点相当于一棵小树,再按照左边第一个开始遍历,如果为空,遍历结束
temp = temp.getLeft();
}
}
}while (temp != null);
}
}
package com.www.demo20;
public class Test {
public static void main(String[] args) {
int[] arr = new int[]{1,5,6,2,3,4,8,9};
BinaryTree binaryTree = new BinaryTree(arr);
binaryTree.inorderTraversal();
}
}