1. 遍历方式
a. 先序遍历
- 步骤 // 先访问根结点
- 访问根结点
- 先序访问左子树
- 先序访问右子树
- 举例
b. 中序遍历
- 步骤 // 中间访问根结点
- 中序遍历左子树
- 访问根结点
- 中序遍历右子树
- 举例
c. 后序遍历
- 步骤 // 最后访问根结点
- 后序遍历左子树
- 后序遍历右子树
- 访问根结点
- 举例
2. 查找结点
3. 删除结点
- 如果删除的结点是叶子结点,则删除该结点
- 如果删除的结点是非叶子结点,则删除该子树
∵二叉树是单向的 ∴ 判断的应当是当前结点的子结点是否为待删结点,而不应该直接找待删结点。
- 待删结点编号恰为 root 结点的编号,则置空二叉树
- 如果当前结点的 左子结点不为空&&左子结点的编号为待删结点编号,直接将 this.left 置空,并将 待删结点 返回;
- 如果当前结点的 右子结点不为空&&右子结点的编号为待删结点编号,直接将 this.right 置空,并将 待删结点 返回;
- 如果 step2 和 step3 没有删除结点,就向左子树递归删除 // 若找到了就直接返回,以免再去右边做无用功;
- 如果 step4 还没把结点删除,就再向右子树递归删除
4. 代码实现
public class BinaryTreeDemo {
public static void main(String[] args) {
BiTree biTree = new BiTree();
HeroNode root = new HeroNode(1, "宋江");
HeroNode node2 = new HeroNode(2, "吴用");
HeroNode node3 = new HeroNode(3, "卢俊义");
HeroNode node4 = new HeroNode(4, "林冲");
HeroNode node5 = new HeroNode(5, "关胜");
root.left = node2;
root.right = node3;
node3.right = node4;
node3.left = node5;
biTree.root = root;
/*
System.out.println("前序遍历:");
biTree.preOrderBiTree(); // 1, 2, 3, 5, 4
System.out.println("--------------");
System.out.println("中序遍历:");
biTree.midOrderBiTree(); // 2, 1, 5, 3, 4
System.out.println("--------------");
System.out.println("后序遍历:");
biTree.postOrderBiTree(); // 2, 5, 4, 3, 1
System.out.println("--------------");
System.out.println("前序查找:");
HeroNode node = biTree.preOrderSearch(5); // 4次
System.out.println(node!=null ? node : "没找到");
System.out.println("--------------");
System.out.println("中序查找:");
node = biTree.midOrderSearch(5); // 3次
System.out.println(node!=null ? node : "没找到");
System.out.println("--------------");
System.out.println("后序查找:");
node = biTree.postOrderSearch(5); // 2次
System.out.println(node!=null ? node : "没找到");
System.out.println("--------------");
*/
System.out.println("删除结点5:" + biTree.deleteNode(5));
}
}
class BiTree {
public HeroNode root;
// 前序遍历
public void preOrderBiTree() {
if (root != null) root.preOrderBiTree();
else System.out.println("二叉树为空, 无法前序遍历");
}
// 中序遍历
public void midOrderBiTree() {
if (root != null) root.midOrderBiTree();
else System.out.println("二叉树为空, 无法中序遍历");
}
// 后序遍历
public void postOrderBiTree() {
if (root != null) root.postOrderBiTree();
else System.out.println("二叉树为空, 无法后序遍历");
}
// 前序查找
public HeroNode preOrderSearch(int no) {
if (root != null) return root.preOrderSearch(no);
else return null;
}
// 中序查找
public HeroNode midOrderSearch(int no) {
if (root != null) return root.midOrderSearch(no);
else return null;
}
// 后序查找
public HeroNode postOrderSearch(int no) {
if (root != null) return root.postOrderSearch(no);
else return null;
}
// 删除结点
public HeroNode deleteNode(int no) {
HeroNode delNode = null;
if (root != null) {
if (root.no == no) {
delNode = root;
root = null;
return delNode;
} else {
return root.deleteNode(no);
}
} else throw new RuntimeException("二叉树为空");
}
}
class HeroNode {
public int no;
public String name;
public HeroNode left;
public HeroNode right;
public HeroNode(int no, String name) {
this.no = no;
this.name = name;
}
// 前序遍历
public void preOrderBiTree() {
System.out.println(this);
// 递归 前序遍历左子树
if(this.left != null)
this.left.preOrderBiTree();
// 递归 前序遍历右子树
if(this.right != null)
this.right.preOrderBiTree();
}
// 中序遍历
public void midOrderBiTree() {
// 递归 中序遍历左子树
if(this.left != null)
this.left.midOrderBiTree();
System.out.println(this);
// 递归 中序遍历右子树
if(this.right != null)
this.right.midOrderBiTree();
}
// 后序遍历
public void postOrderBiTree() {
// 递归 后序遍历左子树
if(this.left != null)
this.left.postOrderBiTree();
// 递归 后序遍历右子树
if(this.right != null)
this.right.postOrderBiTree();
System.out.println(this);
}
/**
* 前序查找
* @param no 结点编号
* @return 找到则返回该结点, 否则返回null
*/
public HeroNode preOrderSearch(int no) {
HeroNode node = null;
// 1. 比较当前结点是不是
// System.out.printf("[前序] %d → ", this.no);
if(this.no == no) return this;
// 2. 对左子树递归前序查找
if(this.left != null)
node = this.left.preOrderSearch(no);
// 在左边找到, 就没必要再去递归找右边了
if(node != null) return node;
// 3. 对右子树递归前序查找
if(this.right != null)
node = this.right.preOrderSearch(no);
return node;
}
/**
* 中序查找
* @param no 结点编号
* @return 找到则返回该结点, 否则返回null
*/
public HeroNode midOrderSearch(int no) {
HeroNode node = null;
// 1. 对左子树递归中序查找
if(this.left != null)
node = this.left.midOrderSearch(no);
if(node != null)
return node;
// 2. 判断
// System.out.printf("[中序] %d → ", this.no);
if(this.no == no)
return this;
// 3. 对右子树递归中序查找
if(this.right != null)
node = this.right.midOrderSearch(no);
return node;
}
/**
* 后序查找
* @param no 结点编号
* @return 找到则返回该结点, 否则返回null
*/
public HeroNode postOrderSearch(int no) {
HeroNode node = null;
// 1. 对左子树递归后序查找
if (this.left != null)
node = this.left.postOrderSearch(no);
if (node != null)
return node;
// 2. 对右子树递归后序查找
if (this.right != null)
node = this.right.postOrderSearch(no);
if (node != null)
return node;
// 3. 判断
// System.out.printf("[后序] %d → ", this.no);
if (this.no == no)
return this;
return node;
}
/**
* 删除结点
* @param no 待删结点编号
* @return 返回以no为编号的结点; 如果没找到返回null
*/
public HeroNode deleteNode(int no) {
HeroNode delNode = null;
if (this.left != null && this.left.no == no) {
delNode = this.left;
this.left = null;
return delNode;
}
if (this.right != null && this.right.no == no) {
delNode = this.right;
this.right = null;
return delNode;
}
if (this.left != null) {
delNode = this.left.deleteNode(no);
if (delNode != null) return delNode;
}
if (this.right != null)
delNode = this.right.deleteNode(no);
return delNode;
}
@Override
public String toString() {
return "[no=" + no + ", name=" + name + "]";
}
}