二叉树的三种遍历方法,添加节点,删除节点

1、一个最基本的二叉树节点,由指向左子节点,指向右子节点,根节点构成

package 二叉树;
//对节点类进行定义
public class TNode {
//设置属性,数据
private int data;
//设置属性,左子节点
private TNode left;
//设置属性,右子节点
private TNode right;

//重写无参构造方法
public TNode() {

}
//重写带数据的构造方法
public TNode(int data) {
this.data = data;
}
//重写带三个参数的构造方法
public TNode(int data, TNode left, TNode right) {
this.data = data;
this.left = left;
this.right = right;
}


//数据的获取方法
public int getData() {
return data;
}
//数据的设置方法
public void setData(int data) {
this.data = data;
}
//左子节点的获取方法
public TNode getLeft() {
return left;
}
//左子节点的设置方法
public void setLeft(TNode left) {
this.left = left;
}
//右子节点的获取方法
public TNode getRight() {
return right;
}
//右子节点的设置方法
public void setRight(TNode right) {
this.right = right;
}
}

2、遍历树的方法 先序、后序、中序
/**
* FTravel(tnode)方法是进行先序遍历
* @param tnode 传入一个父节点
*/
public void FTravel(TNode tnode){
//tnode为传入的父节点
//System.out.println(tnode.getData()+" "+tnode.getLeft().getData()+" "+tnode.getRight().getData());
//父节点的左子节点或右子节点都可能为空,导致上面的输出语句出现空指针

//先获取输出根节点的数据
System.out.print(tnode.getData()+"\t");
if(null!=tnode.getLeft()){
//左子节点不为空
if(null!=tnode.getLeft().getLeft()||null!=tnode.getLeft().getRight()){
//如果左子节点还有非空子节点,递归调用本方法
FTravel(tnode.getLeft());
}else{
//反之,该左子节点是叶子节点
System.out.print(tnode.getLeft().getData()+"\t");
}
}
if(null!=tnode.getRight()){
//右子节点不为空
if(null!=tnode.getRight().getLeft()||null!=tnode.getRight().getRight()){
//如果左子节点还有非空子节点,递归调用本方法
FTravel(tnode.getRight());
}else{
//反之,该右子节点是叶子节点
System.out.print(tnode.getRight().getData()+"\t");
}
}
}
/**
* LTravel(tnode)方法是进行后序遍历
* @param tnode 传入一个父节点
*/
public void LTravel(TNode tnode) {
// 先从给定父节点的左子树开始遍历
if (null != tnode.getLeft()) {
// 左子节点不为空
if (null != tnode.getLeft().getLeft()
|| null != tnode.getLeft().getRight()) {
// 如果左子节点还有非空子节点,递归调用本方法
LTravel(tnode.getLeft());
} else {
// 反之,该左子节点是叶子节点
System.out.print(tnode.getLeft().getData() + "\t");
}
}
// 后从给定父节点的右子树开始遍历
if (null != tnode.getRight()) {
// 右子节点不为空
if (null != tnode.getRight().getLeft()
|| null != tnode.getRight().getRight()) {
// 如果右子节点还有非空子节点,递归调用本方法
LTravel(tnode.getRight());
} else {
// 反之,该右子节点是叶子节点
System.out.print(tnode.getRight().getData() + "\t");
}
}
// 再获取输出根节点的数据
System.out.print(tnode.getData() + "\t");
}
/**
* MTravel(tnode)方法是进行中序遍历
* @param tnode 传入一个父节点
*/
public void MTravel(TNode tnode){
//先从给定父节点的左子树开始遍历
if(null!=tnode.getLeft()){
//左子节点不为空
if(null!=tnode.getLeft().getLeft()||null!=tnode.getLeft().getRight()){
//如果左子节点还有非空子节点,递归调用本方法
MTravel(tnode.getLeft());
}else{
//反之,该左子节点是叶子节点
System.out.print(tnode.getLeft().getData()+"\t");
}
}
//后获取输出根节点的数据
System.out.print(tnode.getData() + "\t");
//再从给定父节点的右子树开始遍历
if (null != tnode.getRight()) {
// 右子节点不为空
if (null != tnode.getRight().getLeft()
|| null != tnode.getRight().getRight()) {
// 如果右子节点还有非空子节点,递归调用本方法
MTravel(tnode.getRight());
} else {
// 反之,该右子节点是叶子节点
System.out.print(tnode.getRight().getData() + "\t");
}
}
}

3、节点的添加

/**
* 添加节点的方法
*
* @param node
*/
public void add(TNode tnode) {
// 判断root是否为null
if (null == root) {
root = tnode;
}else{
//在以root为根节点的树上遍历,寻找存放tnode 的位置
queryNode(root,tnode);
}
}

/**
* 查找节点的方法
* @param node1根节点
* @param node2要被添加的节点
* @return 返回要添加节点的位置
*/
private void queryNode(TNode tnode1,TNode tnode2){
if(tnode2.getData()>tnode1.getData()){
//要添加的节点的数据比该节点大,添加到该节点的右子树上
if(null==tnode1.getRight()){
//如果该节点的右子节点地址为空,则把要添加的节点添加到该节点的右子节点上
tnode1.setRight(tnode2);
}else {
//反之,则把要添加的节点添加到该节点的右子节点为根节点的树上
queryNode(tnode1.getRight(),tnode2);
}
}else {
//反之,将要添加的节点添加到该节点的左子树上
if(null==tnode1.getLeft()){
//如果该节点的左子节点地址为空,则把要添加的节点添加到该节点的左子节点上
tnode1.setLeft(tnode2);
}else{
//反之,则把要添加的节点添加到该节点的左子节点为根节点的树上
queryNode(tnode1.getLeft(),tnode2);
}
}
}

4、节点的删除

//如果删除成功,返回true,否则返回false
public boolean remove(TNode tnode) {
//调用统计节点的方法,统计删除节点前的节点个数
int count1=count(this.root);
//调用删除节点的方法,删除结点tnode
remove1(this.root,tnode);
//调用统计节点的方法,统计删除节点后的节点个数
int count2=count(this.root);
if(count1>count2)
//如果前后节点数不一样,返回true
return true;
else
//否则删除失败,返回false
return false;
}
/**
* 接下来定义先序遍历,删除某一节点的方法
* 先找到该节点所在,
* 如果该节点只有一个子节点,则将该子节点替换成该子节点的子节点
* 如果该节点没有子节点,则只要将该节点的父节点指向该节点的地址改成空
* 如果该节点有两个子节点,则将该子节点替换成该子节点的左子节点
* parm@tnode 传入的当前的父节点
* parm@tnode2 传入的要删除的结点
*/
public void remove1(TNode tnode, TNode tnode2) {
// 先获取输出父节点的数据
// System.out.print(tnode.getData()+"\t");

// 如果根节点是要删除的节点,
if (tnode.getData() == tnode2.getData()&&tnode==root) {
if(null==tnode.getLeft()){
if(null==tnode.getRight()){
//如果根节点的左子节点和右子节点都为空
root=null;
}else{
//根节点的左子节点为空,右子节点非空
root=root.getRight();
}
}else if(null==tnode.getRight()){
//根节点的右子节点为空,左子节点非空
root=root.getLeft();
}else {
//根节点的左子节点和右子节点都非空
TNode temp=root.getLeft();
//用temp存储根节点的左子节点
//调用remove1方法,传入根节点和字符串Left
remove2(root,"Left");
//将temp的左子节点指向根节点的左子节点
temp.setLeft(root.getLeft());
//将temp的右子节点指向根节点的右子节点
temp.setRight(root.getRight());
//用temp代替根节点
root=temp;

}
}
if (null != tnode.getLeft()) {
// 左子节点不为空
if (null != tnode.getLeft().getLeft()
|| null != tnode.getLeft().getRight()) {
// 如果左子节点还有非空子节点,
if(tnode.getLeft().getData()==tnode2.getData()){
remove2(tnode,"Left");
}
//递归调用本方法
remove1(tnode.getLeft(),tnode2);
} else {
// 反之,该左子节点是叶子节点
// System.out.print(tnode.getLeft().getData()+" ");
if (tnode2.getData() == tnode.getLeft().getData()) {
// 如果该叶子节点的数据与要删除的节点数据一致,就把该叶子节点的父节点的左子节点赋为空
tnode.setLeft(null);
}
}
}
if (null != tnode.getRight()) {
// 右子节点不为空
if (null != tnode.getRight().getLeft()
|| null != tnode.getRight().getRight()) {
// 如果左子节点还有非空子节点,
if(tnode.getRight().getData()==tnode2.getData()){
remove2(tnode,"Right");
}
//递归调用本方法
remove1(tnode.getRight(),tnode2);
} else {
// 反之,该右子节点是叶子节点
// System.out.print(tnode.getRight().getData()+" ");
if (tnode2.getData() == tnode.getRight().getData()) {
// 如果该叶子节点的数据与要删除的节点数据一致,就把该叶子节点的父节点的左子节点赋为空
tnode.setRight(null);
}
}
}
}

/**
*
* @param tnode 表示要删除节点的父节点
* @param str 要删除的节点是父节点的左子节点Left,或者是父节点的右子节点Right
*/
public void remove2(TNode tnode,String str){
if(str.equals("Left")){
//tnode的左子节点要被删除
if(null==tnode.getLeft().getLeft()){
//被删节点的左子节点为空,则右子节点非空
tnode.setLeft(tnode.getLeft().getRight());
}else if(null==tnode.getLeft().getRight()){
//被删节点的右子节点为空,则左子节点非空
tnode.setLeft(tnode.getLeft().getLeft());
}else {
//被删节点的左子节点和右子节点都不为空
//把被删节点的左子节点存起来
TNode temp= tnode.getLeft().getLeft();
//递归调用本方法,删除被删节点的左子节点
remove2(tnode.getLeft(),"Left");
//设置被删节点的左子节点为temp的左子节点
temp.setLeft(tnode.getLeft().getLeft());
//设置被删节点的右子节点为temp的右子节点
temp.setRight(tnode.getLeft().getRight());
//设置被删节点的父节点的左子节点为temp
tnode.setLeft(temp);
}
}else if(str.equals("Right")){
//tnode的右子节点要被删除
if(null==tnode.getRight().getLeft()){
//被删节点的左子节点为空,则右子节点非空
tnode.setLeft(tnode.getLeft().getRight());
}else if(null==tnode.getRight().getRight()){
//被删节点的右子节点为空,则左子节点非空
tnode.setLeft(tnode.getLeft().getLeft());
}else{
//被删节点的左子节点和右子节点都不为空
//把被删节点的左子节点存起来
TNode temp= tnode.getRight().getLeft();
//递归调用本方法,删除被删节点的左子节点
remove2(tnode.getRight(),"Left");
//设置被删节点的左子节点为temp的左子节点
temp.setLeft(tnode.getRight().getLeft());
//设置被删节点的右子节点为temp的右子节点
temp.setRight(tnode.getRight().getRight());
//设置被删节点的父节点的右子节点为temp
tnode.setRight(temp);
}
}
}

/**
*
* @param tnode为传入的父节点
* @return 从该父节点往下的所有结点个数,包括父节点
*/
public int count(TNode tnode) {
// tnode为传入的父节点
int t = 1;
// // 先获取输出根节点的数据
// System.out.print(tnode.getData() + "\t");
if (null != tnode.getLeft()) {
// 左子节点不为空
if (null != tnode.getLeft().getLeft()
|| null != tnode.getLeft().getRight()) {
// 如果左子节点还有非空子节点,递归调用本方法
t=t+count(tnode.getLeft());
} else {
// 反之,该左子节点是叶子节点
// System.out.print(tnode.getLeft().getData() + "\t");
}
t=t+1;
}
if (null != tnode.getRight()) {
// 右子节点不为空
if (null != tnode.getRight().getLeft()
|| null != tnode.getRight().getRight()) {
// 如果左子节点还有非空子节点,递归调用本方法
t=t+count(tnode.getRight());
} else {
// 反之,该右子节点是叶子节点
// System.out.print(tnode.getRight().getData() + "\t");
}
t=t+1;
}
return t;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值