四、顺序存储二叉树

代码实现
package Tree.BinaryTree;
//顺序存储二叉树
public class ArrBinaryTree {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7};
ArrTree tree = new ArrTree(arr);
tree.preOrder();
System.out.println();
tree.infixOrder();
System.out.println();
tree.postOrder();
System.out.println();
}
}
//编写一个ArrBinaryTree,实现顺序存储二叉树遍历
class ArrTree {
private int[] arr;
public ArrTree(int[] arr) {
this.arr = arr;
}
//重载后外部无需再输入参数下标
public void preOrder() {
this.preOrder(0);
}
public void infixOrder() {
this.infixOrder(0);
}
public void postOrder() {
this.postOrder(0);
}
//前序遍历
public void preOrder(int index) {//数组下标
if (arr == null || arr.length == 0) {
System.out.println("数组为空,无法遍历");
return;
}
System.out.print(arr[index] + " ");
//向左遍历递归
if (index * 2 + 1 < arr.length) {
preOrder(index * 2 + 1);
}
if (index * 2 + 2 < arr.length) {
preOrder(index * 2 + 2);
}
}
//中序遍历
public void infixOrder(int index) {//数组下标
if (arr == null || arr.length == 0) {
System.out.println("数组为空,无法遍历");
return;
}
if (index * 2 + 1 < arr.length) {
infixOrder(index * 2 + 1);
}
System.out.print(arr[index] + " ");
if (index * 2 + 2 < arr.length) {
infixOrder(index * 2 + 2);
}
}
//后序遍历
public void postOrder(int index) {//数组下标
if (arr == null || arr.length == 0) {
System.out.println("数组为空,无法遍历");
return;
}
if (index * 2 + 1 < arr.length) {
postOrder(index * 2 + 1);
}
if (index * 2 + 2 < arr.length) {
postOrder(index * 2 + 2);
}
System.out.print(arr[index] + " ");
}
}
五、线索化二叉树

注:
1、n个节点共有2n个指针,除去根节点的其他n-1个节点,会占用对应父节点的一个指针,因此,空指针的数量等于二者相减
2、节点=》该节点

数组中打头的没有前驱节点,末尾的没有后继节点
说明中的情况要在代码中体现
六、遍历线索化二叉树
思路分析
1、先取到要遍历的第一个节点(第一个lefttType=1但left=0的节点)
2、如果后驱节点一直存在,就一直输出,直到遇到right域指向的是右子树的节点时(即rightType=0时),将当前临时节点node替换为此节点
3、继续通过新的node节点执行上述的操作,直到right指向为空
解释:因为实现线索化二叉树中是通过下个节点的pre来设置后驱节点,而最后一个节点无下个节点,不会被设置后驱,rightTpye=0所以走外层while:通过右子树是否为空这个条件,作为判断是否实现全部二叉树的线索化遍历的依据
重要提示:在中序线索化中,是在回溯的过程中进行节点的pre域进行操作,因此递归不需要对pre指向的是前驱节点还是左子树进行判断;而在前序线索化中,是先进行了节点操作后进行递归,因此在递归时有必要判断,即递归的条件是leftType=0
代码实现
package Tree.ThreadedBinaryTree;
public class ThreadedBinaryTree {
public static void main(String[] args) {
HeroNode root = new HeroNode(1, "1");
HeroNode n2 = new HeroNode(3, "3");
HeroNode n3 = new HeroNode(6, "6");
HeroNode n4 = new HeroNode(8, "8");
HeroNode n5 = new HeroNode(10, "10");
HeroNode n6 = new HeroNode(14, "14");
root.left = n2;
root.right = n3;
n2.left = n4;
n2.right = n5;
n3.left = n6;
ThreadTree tree = new ThreadTree();
tree.setRoot(root);
// tree.threadedInfixNodes();
//找一个点做验证,10的前后是否是3和1
// System.out.println(n6.left);
// System.out.println(n6.right);
// tree.threadedInfixList();
System.out.println("===============");
// tree.threadedPreNodes();
// System.out.println(n4.left);
// System.out.println(n4.right);
// tree.threadedPreList();
tree.threadedPostNodes();
// System.out.println(n4.left);
// System.out.println(n4.right);
tree.threadedPostList();
}
}
//定义一个树
class ThreadTree {
private HeroNode root;
//为了实现线索化,需要创建一个指向当前节点的前驱节点的指针
//在递归仅限线索化时,pre始终保留前一个结点
private HeroNode pre = null;
public void setRoot(HeroNode root) {
this.root = root;
}
//重载
public void threadedInfixNodes() {
this.threadedInfixNodes(root);
}
public void threadedPreNodes() {
this.threadedPreNodes(root);
}
public void threadedPostNodes() {
this.threadedPostNodes(root);
}
//二叉树前序线索化
public void threadedPreNodes(HeroNode node) {
if (node == null) {
return;
}
//左指针为空时,指向前驱节点
if (node.left == null) {
node.left = pre;
node.leftType = 1;
}
//后继节点是在下一次处理的(在下一个节点中,用pre表示上一个节点然后进行设置)
//最后一个节点没有下一个节点,自然也就没有了后继节点
if (pre != null && pre.right == null) {
pre.right = node;
pre.rightType = 1;
}
pre = node;
//处理左子树
if (node.leftType == 0) {
threadedPreNodes(node.left);
}
//处理右子树
if (node.rightType == 0) {
threadedPreNodes(node.right);
}
}
//二叉树中序线索化
public void threadedInfixNodes(HeroNode node) {//需要线索化的节点
if (node == null) {
return;
}
;
//先线索化左子树、再当前节点、再右子树
threadedInfixNodes(node.left);
//线索化当前节点
if (node.left == null) {//前驱节点使用pre
node.left = pre;
node.leftType = 1;
}
//后继节点是在下一次处理的(在下一个节点中,用pre表示上一个节点然后进行设置)
//最后一个节点没有下一个节点,自然也就没有了后继节点
if (pre != null && pre.right == null) {
pre.right = node;
pre.rightType = 1;
}
pre = node;
threadedInfixNodes(node.right);
}
//二叉树后序线索化
public void threadedPostNodes(HeroNode node) {
if (node == null) {
return;
}
//处理左子树
if (node.leftType == 0) {
threadedPostNodes(node.left);
}
//处理右子树
if (node.rightType == 0) {
threadedPostNodes(node.right);
}
//左指针为空时,指向前驱节点
if (node.left == null) {
node.left = pre;
node.leftType = 1;
}
//后继节点是在下一次处理的(在下一个节点中,用pre表示上一个节点然后进行设置)
//最后一个节点没有下一个节点,自然也就没有了后继节点
if (pre != null && pre.right == null) {
pre.right = node;
pre.rightType = 1;
}
pre = node;
}
//线索化前序遍历
public void threadedPreList() {
HeroNode node = root;
while (node != null) {
//循环的找到leftType=1的节点
while (node.leftType == 0) {//第一个leftType=1的节点就是首节点
System.out.println(node);
node = node.left;
}
//打印当前这个节点
System.out.println(node);
node = node.right;
}
}
//线索化中序遍历
public void threadedInfixList() {
//定义一个临时变量,存储当前遍历的节点,从root开始
HeroNode node = root;
while (node != null) {
//循环的找到leftType=1的节点
while (node.leftType == 0) {//第一个leftType=1的节点就是首节点
node = node.left;
}
//打印当前这个节点
System.out.println(node);
//如果当前节点的右指针指向的是后继节点,就一直输出
while (node.rightType == 1) {
node = node.right;
System.out.println(node);
}
//while结束时,说明遇到了右指针指向的是右子树的节点,
// 此时把这个节点替换为node,重复进行新一轮的while操作
node = node.right;
}
}
//线索化后序遍历
public void threadedPostList() {
//定义一个临时变量,存储当前遍历的节点,从root开始
HeroNode node = root;
//找后序遍历开始的节点
HeroNode pre = null;
while (node != null && node.leftType == 0) {
node = node.left;
}
while (node!=null){
if (node.rightType==1){
System.out.println(node);
pre=node;
node=node.right;
} else {
//如果上个处理的节点是当前节点的右节点
if (node.right==pre){
System.out.println(node);
if (node==root){
return;
}
pre = node;
node=node.parent;
} else {//如果是从左节点进入则找到有子树的最左节点
node=node.right;
while (node!=null&&node.leftType==0){
node=node.left;
}
}
}
}
}
//前序遍历
public void preOrder() {
if (root != null) {
this.root.preOrder();
} else {
System.out.println("当前二叉树为空,无法遍历");
}
}
//中序遍历
public void infixOrder() {
if (root != null) {
this.root.infixOrder();
} else {
System.out.println("当前二叉树为空,无法遍历");
}
}
//后序遍历
public void postOrder() {
if (root != null) {
this.root.postOrder();
} else {
System.out.println("当前二叉树为空,无法遍历");
}
}
//前序查找
public HeroNode preOrderSearch(int no) {
if (root != null) {
HeroNode res = this.root.preOrderSearch(no);
if (res.no == no) {
return res;
}
return null;
} else {
return null;
}
}
//中序查找
public HeroNode infixOrderSearch(int no) {
if (root != null) {
HeroNode res = this.root.infixOrderSearch(no);
if (res.no == no) {
return res;
}
return null;
} else {
return null;
}
}
//后序查找
public HeroNode postOrderSearch(int no) {
if (root != null) {
HeroNode res = this.root.postOrderSearch(no);
if (res.no == no) {
return res;
}
return null;
} else {
return null;
}
}
//删除
public void del(int no) {
if (root != null) {
if (root.no == no) {
root = null;
} else {
this.root.del(no);
}
} else {
System.out.println("二叉树为空,无法继续删除");
}
}
}
//先创建HeroNode节点
class HeroNode {
public int no;
public String name;
public HeroNode left;
public HeroNode right;
public int leftType;//等于0代表是左子树,等于1代表是前驱节点
public int rightType;
public HeroNode parent;
public HeroNode() {
}
public HeroNode(int no, String name) {
this.no = no;
this.name = name;
}
@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;
} else {
HeroNode resNode = null;
if (this.left != null) {//递归前序查找
resNode = this.left.preOrderSearch(no);
}
if (resNode != null) {//说明左子树找到
return resNode;
}
if (this.right != null) {
resNode = this.right.preOrderSearch(no);
}
return resNode;//为空说明都没找到,不为空说明在右子树找到,最后的判断放在上层做
}
}
//中序查找
public HeroNode infixOrderSearch(int no) {
HeroNode resNode = null;
if (this.left != null) {//递归前序查找
resNode = this.left.infixOrderSearch(no);
}
if (resNode != null) {//说明左子树找到
return resNode;
}
if (this.no == no) {
return this;
}
if (this.right != null) {
resNode = this.right.infixOrderSearch(no);
}
return resNode;
}
//后序查找
public HeroNode postOrderSearch(int no) {
HeroNode resNode = null;
if (this.left != null) {
resNode = this.left.postOrderSearch(no);
}
if (resNode != null) {
return resNode;
}
if (this.right != null) {
resNode = this.right.postOrderSearch(no);
}
if (resNode != null) {
return resNode;
}
return this;
}
//删除
public void del(int no) {
if (this.left != null && this.left.no == no) {
if (this.left.left != null) {
this.left = this.left.left;
} else if (this.left.right != null) {
this.left = this.left.right;
} else {
this.left = null;
}
return;
}
if (this.right != null && this.right.no == no) {
if (this.right.left != null) {
this.right = this.right.left;
} else if (this.right.right != null) {
this.right = this.right.right;
} else {
this.right = null;
}
return;
}
if (this.left != null) {
this.left.del(no);
}
if (this.right != null) {
this.right.del(no);
}
}
}