二叉树很明显就只有两个分叉,及左子节点和右子节点,这里主要是说明二叉树的遍历,查找节点和删除节点,线索化这几种。
遍历分为前序遍历,中序遍历,后序遍历这三种,前,中,后是相对中间节点来说的,及前序比那里是先中间节点,在左边节点,最后右边节点。
下面是前序遍历代码:
public void preOrder(){
System.out.println(this);
if(this.left!=null) {
this.left.preOrder();
}
if(this.right!=null) {
this.right.preOrder();
}
}
这是节点的前序遍历,在二叉树里面遍历还需要判断给的节点是不是空:
public void preOrder() {
if(this.root!=null) {
this.root.preOrder(); //调用上面的preOrder方法。
}else {
System.out.println("二叉树为空");
}
}
中序和后序遍历和上面差不多,就是输出顺序不一样,可以自行参照对比。
查找节点:也分为前序遍历查找。中序遍历查找,后序遍历查找。
前序遍历查找思路:就是按照中间节点,左子树,右子树的顺序遍历找到相同节点就赋值,然后退出,没找到就返回一个空节点。
代码如下:也分为节点的遍历和二叉树的遍历,二叉树的遍历要判断是否为空
//前序查找
public HeroNode preOrderSearch(int no) {
if(this.no==no) {
return this;
}
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 preOrderSearch(int no) {
if(root!=null) {
return root.preOrderSearch(no); //调用上面的preOrderSearch方法。
}else {
return null;
}
}
删除节点:二叉树删除节点和平衡二叉树删除节点不同:二叉树删除节点就直接将要删除的节点置为空,不管是叶子节点还是带子节点的父节点,都置空即可,但是平衡二叉树删除的节点要是带子节点的父节点删的时候要进行调整、
代码:分为节点的和二叉树的删除节点,二叉树的删除节点要判断这个树的根节点是否为空,要是空就说明没有,直接退出即可。
//删除节点
public void delNode(int no) {
if(this.left!=null&&this.no==no) {
this.left=null;
return;
}
if(this.right!=null && this.no==no) {
this.right=null;
return;
}
if(this.left!=null) {
this.left.delNode(no);
}
if(this.right!=null) {
this.right.delNode(no);
}
}
public void delNode(int no) {
if(root!=null) {
if(root.getNo()==no) {
root=null;
}else {
root.delNode(no); //调用上面代码
}
}else {
System.out.println("树空");
}
}
二叉树线索化:何为线索化,就是给二叉树的每一个没有左子节点和右子节点的节点添加了这个节点的前驱和后继节点。因为如果有左子节点和右子节点,哪肯定指向的是左子节点和右子节点,不会有前驱和后继了,也就是给叶子节点和只有一个左子节点或右子节点的父节点添加前驱和后继。
那要是这样后面遍历就会出现问题:会出现循环,因为当你遍历到叶子节点,叶子节点有可能指向之前出现过的节点,所以遍历的时候就要添加一个属性,判断属性得知这个节点的左子节点和右子节点指向的是左子节点和右子节点还是前驱和后继节点。
代码:不理解的可以画图看一下。
public void threadNodes(HeroNode node) {
if(node==null) {
return;
}
threadNodes(node.getLeft());
threadNodes(node.getRight());
if(node.getLeft()==null) { //得到这个节点的左子节点。
node.setLeft(pre);
node.setLeftType(1);
}
if(pre!=null&&pre.getRight()==null) { //得到这个节点的前驱节点的右子节点。
//因为如果这个节点的左子节点是前驱节点了,哪前驱节点的右子节点就是这个节点了。
//而且如果这个节点的左边没有连线,哪这个节点的前驱也就没有连线。
pre.setRight(node);
pre.setRightType(1);
}
}