1.自我介绍🎶🎶🎶
- 1.线索化叉树(Threaded Binary Tree)是一种二叉树,其节点除了保存左右子节点的指针外,还可以保存指向前驱和后继节点的指针。
- 2.n个结点的二叉链表中含有n+1 【公式2n-(n-1)-n+1】个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")。
- 3.线索化叉树可以分为前序线索化二叉树、中序线索化二叉树和后序线索化二叉树三种。
2.应用案例🎶🎶🎶
中序遍历得到的结果:{8,3,10,1,14,6}
3.代码实现🎶🎶🎶
创建节点🤞🤞
/**
* 创建HeroNode节点
*/
class HeroNode {
private int no;
private String name;
private HeroNode left;//左节点 默认null
private HeroNode right;//右节点 默认null
private int leftTree; //等于0,指向左子树,等于1表示指向前驱节点
private int rightTree;//等于0,指向右子树,等于1表示指向后驱节点
public HeroNode(int no, String name) {
this.no = no;
this.name = name;
}
public int getLeftTree() {
return leftTree;
}
public void setLeftTree(int leftTree) {
this.leftTree = leftTree;
}
public int getRightTree() {
return rightTree;
}
public void setRightTree(int rightTree) {
this.rightTree = rightTree;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getLeft() {
return left;
}
public void setLeft(HeroNode left) {
this.left = left;
}
public HeroNode getRight() {
return right;
}
public void setRight(HeroNode right) {
this.right = right;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
/**
* 前序遍历
*/
public void preOrder() {
System.out.println(this);//先输出根节点
//向左子节点递归
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.println(this);
//递归右子节点遍历
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.println(this);
}
/**
* 前序查找
*/
public HeroNode preOrderSearch(int no) {
//判断当前节点是否相等
if (this.no == no) {
return this;
}
//定义变量,接收递归返回值
HeroNode tempNode = null;
//判断左子节点是否为空,向左子节点递归
if (this.left != null) {
tempNode = this.left.preOrderSearch(no);
}
//说明左递归找到
if (tempNode != null) {
return tempNode;
}
//左递归未找到,判断右子节点是否为空,并向右递归
if (this.right != null) {
tempNode = this.right.preOrderSearch(no);
}
return tempNode;
}
/**
* 中序查找
*/
public HeroNode infixOrderSearch(int no) {
HeroNode tempNode = null;
//判断当前节点的左子节点是否为空,并递归
if (this.left != null) {
tempNode = this.left.infixOrderSearch(no);
}
//判断是否找到
if (tempNode != null) {
return tempNode;
}
//未找到,判断当前节点是否相等
if (this.no == no) {
return this;
}
//不等,判断右子节点是否为空,向有递归
if (this.right != null) {
tempNode = this.right.infixOrderSearch(no);
}
return tempNode;
}
/**
* 后序查找
*/
public HeroNode postOrderSearch(int no) {
HeroNode tempNode = null;
//判断当前节点的左子节点
if (this.left != null) {
tempNode = this.left.postOrderSearch(no);
}
//判断是否找到
if (tempNode != null) {
return tempNode;
}
//未找到,判断右子节点是否为空,并递归
if (this.right != null) {
tempNode = this.right.postOrderSearch(no);
}
//判断有递归是否找到
if (tempNode != null) {
return tempNode;
}
//左右均未找到,比较当前节点
if (this.no == no) {
return this;
}
return tempNode;
}
/**
* 递归删除节点
*/
public void deleteNode(int no) {
//当前节点的左子节点不为空,并且是要删除的节点,则置为空
if (this.left != null && this.left.no == no) {
this.left = null;
return;
}
//当前节点的右子节点不为空,并且是要删除的节点,则置为空
if (this.right != null && this.right.no == no) {
this.right = null;
return;
}
//向左子树递归
if (this.left != null) {
this.left.deleteNode(no);
}
//向右子树递归
if (this.right != null) {
this.right.deleteNode(no);
}
}
}
创建二叉树实现线索化 🤞🤞
/**
* 线索化二叉树
*/
class ThrTree {
private HeroNode root;
//总是保留前一个结点
private HeroNode pre = null;
public void setRoot(HeroNode root) {
this.root = root;
}
//中序线索化二叉树
//node:需要线索化的节点
public void threadNodes(HeroNode node) {
if (node == null) {
return;
}
//1.先线索化左子树
threadNodes(node.getLeft());
//2.线索化当前节点
//2.1先处理当前节点的前驱
if (node.getLeft() == null) {
//当前节点的左指针指向前驱节点
node.setLeft(pre);
//修改当前节点的做指针类型
node.setLeftTree(1);
}
//2.2处理当前节点的后继节点
if (pre != null && pre.getRight() == null) {
pre.setRight(node);
pre.setRightTree(1);
}
//每处理一个节点后,让当前节点是下一个节点的前驱节点
pre = node;
//3.线索化右子树
threadNodes(node.getRight());
}
//删除指定节点
public void deleteNode(int no) {
if (this.root != null) {
//如果只有一个root节点,判断root是否是要删除的
if (root.getNo() == no) {
root = null;
return;
} else {
root.deleteNode(no);
}
} else {
System.out.println("空树无法删除");
}
}
//前序查找
public HeroNode preOrderSearch(int no) {
if (this.root != null) {
return this.root.preOrderSearch(no);
} else {
return null;
}
}
//中序查找
public HeroNode infixOrderSearch(int no) {
if (this.root != null) {
return this.root.infixOrderSearch(no);
} else {
return null;
}
}
//后序查找
public HeroNode postOrderSearch(int no) {
if (this.root != null) {
return this.root.postOrderSearch(no);
} else {
return null;
}
}
//前序遍历
public void preOrder() {
if (this.root != null) {
this.root.preOrder();
} else {
System.out.println("当前二叉树为空无法遍历");
}
}
//中序遍历
public void infixOrder() {
if (this.root != null) {
this.root.infixOrder();
} else {
System.out.println("当前二叉树为空无法遍历");
}
}
//后序遍历
public void postOrder() {
if (this.root != null) {
this.root.postOrder();
} else {
System.out.println("当前二叉树为空无法遍历");
}
}
}
遍历线索二叉树🤞🤞
//前序遍历线索化二叉树的方法
public void threadPreList() {
//1.定义变量临时存储,当前遍历的节点,从root开始
HeroNode node = root;
while (node != null) {
//打印
System.out.println(node);
//直到找到线索化节点
while (node.getLeftTree() == 0) {
node = node.getLeft();
System.out.println(node);
}
//如果当前节点的右指针指向后继节点,就一直输出
while (node.getRightTree() == 1) {
node = node.getRight();
}
//替换遍历的节点
node = node.getRight();
}
}
//中序历线索化二叉树的方法
public void threadMidList() {
//1.定义变量临时存储,当前遍历的节点,从root开始
HeroNode node = root;
while (node != null) {
//直到找到线索化节点
while (node.getLeftTree() == 0) {
node = node.getLeft();
}
//打印
System.out.println(node);
//如果当前节点的右指针指向后继节点,就一直输出
while (node.getRightTree() == 1) {
node = node.getRight();
System.out.println(node);
}
//替换遍历的节点
node = node.getRight();
}
}