1. 二叉树的概念
** 二叉树的递归遍历**
-
前序遍历:先输出父节点,再遍历左子树和右子树
(1)先输出当前节点,初始的时候是root节点
(2)如果当前左子树不为空,则递归继续前序遍历
(3)如果当前右子树不为空,则递归继续前序遍历
结果:1->2->3->5->4 -
中序遍历:先遍历左子树,再输出父节点,最后遍历右子树
(1)如果当前左子树不为空,则递归继续中序遍历
(2)输出当前节点
(3)如果当前右子树不为空,则递归继续中序遍历
结果:2->1->5->3->4 -
后序遍历:先遍历左子树,再遍历右子树,最后输出父节点
(1)如果当前左子树不为空,则递归继续后序遍历
(2)如果当前右子树不为空,则递归继续中序遍历
(3)输出当前节点
结果:2->5->4->3->1 -
源代码:
package Tree;
import java.util.Arrays;
public class BinarlyTree {
public static void main(String[] args) {
//创建二叉树,并加入节点
BinTree bt = new BinTree();
HeroNode ND1 = new HeroNode(1,"宋江");
HeroNode ND2 = new HeroNode(2,"吴用");
HeroNode ND3 = new HeroNode(3,"卢俊义");
HeroNode ND4 = new HeroNode(4,"林冲");
HeroNode ND5 = new HeroNode(5,"关胜");
bt.setRoot(ND1);
ND1.setLeft(ND2);
ND1.setRight(ND3);
ND3.setLeft(ND5);
ND3.setRight(ND4);
//前序遍历测试1-》2-》3—》4
System.out.println("前序遍历结果:");
bt.PretOrder();
//中序遍历测试2-》1-》3—》4
System.out.println("中序遍历结果:");
bt.MidtOrder();
//后序遍历测试2-》4-》3—》1
System.out.println("后序遍历结果:");
bt.LasttOrder();
}
}
//创建树,定义跟节点及遍历方法
class BinTree{
private HeroNode root;
public void setRoot(HeroNode root) {
this.root = root;
}
//树的前序遍历,先输出root节点,然后是左子树,最后是右子树
public void PretOrder() {
if(this.root!=null) {
this.root.PreOrder();
}else {
System.out.println("二叉树为空");
}
}
//树的中序遍历,先输出左子树,然后是root节点,最后是右子树
public void MidtOrder() {
if(this.root!=null) {
this.root.MidOrder();
}else {
System.out.println("二叉树为空");
}
}
//树的后序遍历,先输出左子树,然后是右子树,最后是root节点,
public void LasttOrder() {
if(this.root!=null) {
this.root.LastOrder();
}else {
System.out.println("二叉树为空");
}
}
}
//创建树节点
class HeroNode {
public int id;
public String name;
HeroNode left; //默认为空
HeroNode right;
public HeroNode(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 [id=" + id + ", name=" + name + "]";
}
//树的前序遍历,先输出root节点,然后是左子树,最后是右子树
public void PreOrder() {
System.out.println(this); //谁调用就指向谁
if(this.left!=null) {
this.left.PreOrder();
}
if(this.right!=null) {
this.right.PreOrder();
}
}
//树的中序遍历,先输出左子树,然后是root节点,最后是右子树
public void MidOrder() {
if(this.left!=null) {
this.left.MidOrder();
}
System.out.println(this); //谁调用就指向谁
if(this.right!=null) {
this.right.MidOrder();
}
}
//树的后序遍历,先输出左子树,然后是右子树,最后是root节点,
public void LastOrder() {
if(this.left!=null) {
this.left.LastOrder();
}
if(this.right!=null) {
this.right.LastOrder();
}
System.out.println(this); //谁调用就指向谁
}
}
- 测试结果:
二叉树节点的查找
//树节点的前序查找
public HeroNode PretSearch(int id) {
//首先判断当前节点是不是匹配
if(root != null) {
return root.PreSearch(id);
}else {
return null;
}
}
//树节点的中序查找
public HeroNode MidtSearch(int id) {
//首先判断当前节点是不是合适
if(root != null) {
return root.MidSearch(id);
}else {
return null;
}
}
//树节点的后序查找
public HeroNode LattSearch(int id) {
//首先判断当前节点是不是合适
if(root != null) {
return root.LatSearch(id);
}else {
return null;
}
}
//树的节点查找,根据编号大小分别进行前序、中序、后序查找
//前序查找
public HeroNode PreSearch(int id) {
//首先判断当前节点是不是合适
if(this.id == id) {
return this;
}
//如果没有找到,则向左子树进行查找
HeroNode temp = null; //方便结果的返回
//先判断左子树为不为空
if(this.left!=null) {
//不为空的话则递归前序遍历查找,
temp = this.left.PreSearch(id);
}
//判断在左子树是否找到,找到返回结束遍历
if(temp!=null) {
return temp;
}
//如果左子树中没有找到,则遍历右子树
if(this.right!=null) {
//不为空的话则递归前序遍历查找,
temp = this.right.PreSearch(id);
}
//无论找到与否,返回当前temp才知道,
return temp;
}
//中序查找节点
public HeroNode MidSearch(int id) {
HeroNode temp = null; //方便结果的返回
//首先遍历当前节点的左子树节点
//先判断左子树为不为空
if(this.left!=null) {
//有元素的话则递归中序遍历查找,
temp = this.left.MidSearch(id);
}
//判断在左子树是否找到,找到返回结束遍历
if(temp!=null) {
return temp;
}
//其次查找当前节点是否匹配
if(this.id == id) {
return this;
}
//如果没有找到,则遍历右子树
if(this.right!=null) {
//不为空的话则递归前序遍历查找,
temp = this.right.MidSearch(id);
}
//无论找到与否,返回当前temp才知道,
return temp;
}
//后序查找节点
public HeroNode LatSearch(int id) {
HeroNode temp = null; //方便结果的返回
//首先遍历当前节点的左子树节点
//先判断左子树为不为空
if(this.left!=null) {
//有元素的话则递归中序遍历查找,
temp = this.left.LatSearch(id);
}
//判断在左子树是否找到,找到返回结束遍历
if(temp!=null) {
return temp;
}
//如果左子树没有找到,则遍历右子树
if(this.right!=null) {
//不为空的话则递归前序遍历查找,
temp = this.right.LatSearch(id);
}
//判断在右子树是否找到,找到返回结束遍历
if(temp!=null) {
return temp;
}
//最后在当前节点进行查找
if(this.id==id) {
return this;
}
return temp; //未找到就返回空
}
二叉树节点的删除
代码:
//节点的删除
public void DeleteNode(int id) {
//首先是判断树为不为空
if(root!=null) {
//判断当前root节点符不符合
if(root.getId()==id) {
root = null;
}else {
root.Delete(id);
}
}else {
System.out.println("此树为空");
}
}
//在node中的delete方法
//按编号删除节点,每次需要遍历到该节点的子节点才能删除操作
public void Delete(int id) {
//首先是判断树为不为空,其次判断当前root节点符不符合,在Tree删除中完成
//1.判断左子树符不符合要删除的节点
if(this.left!=null && this.left.id==id) {
this.left = null;
return;
}
//2.判断右子树符不符合要删除的节点
if(this.right!=null &&this.right.id==id) {
this.right = null;
return;
}
//均未找到,则继续遍历递归删除
//3.左子树递归删除
if(this.left!=null) {
this.left.Delete(id);
}
//4.右子树递归删除
if(this.right!=null) {
this.right.Delete(id);
}
}
顺序存储二叉树
- 在堆排序中会用到顺序存储二叉树
- 代码:数组 arr = {1,2,3,4,5,6,7},前序遍历则为{1,2,4,5,3,6,7}
package Tree;
//顺序存储二叉树,用数组方式实现
public class ArrayTree {
static int[]arr = {1,2,3,4,5,6,7};
public static void main(String[] args) {
PreOreder(0);
}
public static void PreOreder(int index) {
if( arr==null||arr.length==0) {
System.out.println("数组为空");
}
System.out.print(arr[index]+" ");//打印当前节点
//遍历父节点的左边子树节点,其数组下标关系为2*n+1
if(index*2+1<arr.length) {
PreOreder(index*2+1);
}
//遍历父节点的右边子树节点,其数组下标关系为2*n+2
if(index*2+2<arr.length) {
PreOreder(index*2+2);
}
}
}
- 测试结果:
线索化二叉树