目录
[1. 前中后序遍历](#1. 前中后序遍历)
[3 二叉树节点删除操作:](#3 二叉树节点删除操作:)
二叉树的遍历
1. 前中后序遍历
学习二叉树结构,最简单的方式就是遍历。
所谓 遍历 (Traversal) 是指沿着某条搜索路线,依次对树中每个结 点均做一次且仅做一次访问 。 访
问结点所做的操作依赖于具体的应用问题
遍历是二叉树上最重要的操作之一,是二叉树上进行其它运算之基础。
在遍历二叉树时,如果没有进行某种约定,每个人都按照自己的方式遍历,得出的结果就比较乱, 如 果按照某种规则进行约定,则每个人对于同一棵树的遍历结果肯定是相同的 。
如果 N 代表根节点, L 代表根节点的左子树,R 代表根节点的右子树,则根据遍历根节点的先后次序有以下遍历方式:
NLR :前序遍历 (Preorder Traversal )------ 访问根结点 ---> 根的左子树 ---> 根的右子树。
LNR :中序遍历 (Inorder Traversal)------ 根的左子树 ---> 根节点 ---> 根的右子树。
LRN :后序遍历 (Postorder Traversal------ 根的左子树 ---> 根的右子树 ---> 根节点。
java
public class BinaryTree{
public static class BTNode{
BTNode left;
BTNode right;
int value;
BTNode(int value){
this.value = value;
}
}
private BTNode root;
public void createBinaryTree(){
BTNode node1 = new BTNode(1);
BTNode node2 = new BTNode(2);
BTNode node3 = new BTNode(3);
BTNode node4 = new BTNode(4);
BTNode node5 = new BTNode(5);
BTNode node6 = new BTNode(6);
root = node1;
node1.left = node2;
node2.left = node3;
node1.right = node4;
node4.left = node5;
node4.right = node6;
}
}
二叉树的前中后序遍历:
通过上面的简单介绍,我们可以开始正式学习接下来的操作了
二叉树的前序遍历(根节点最先遍历):
基本思路:
若二叉树为空,什么都不做,否则:
i、先访问根结点;
ii、再前序遍历左子树;
iii、最后前序遍历右子树;
动画展示
代码实现:
java
//前序遍历
public static void preOrder(KunBinaryTree root){
if(root == null){
return ;
}
System.out.print(root.no+" "+root.name+" ");//先访问根
preOrder(root.left);//接着左右子树
preOrder(root.right);
}
首先,我们从根节点出发,也就是,按照先根节点后左右子树的过程进行依次遍历,这里相当于先打印根节点所对应的数据域中的信息后,在接着递归调用左子树,直到为空,回溯后递归调用右子树,直到为空。该树的左子树(总的)调用完后, 开始调用右子树,来到②过程,按照(根-----》左子树---》右子树)的规则继续递归。直到左右子树都为空,返回,也就是③,④过程。
输出结果为:123456
中序遍历
基本思路:
若二叉树为空,什么也不做,否则:
i、后序遍历左子树
ii、访问根结点
iii、后序遍历右子树
代码实现:
java
//后续遍历
public static void postOrder(KunBinaryTree root){
if(root == null){
return ;
}
postOrder(root.left);
System.out.print(root.no +" "+root.name+" ");
postOrder(root.right);
}
中序遍历结果: 3 2 1 5 4 6
二叉树的后续遍历:
基本思路:
若二叉树为空,什么也不做,否则:
i、后序遍历左子树
ii、后序遍历右子树
iii、访问根结点
代码实现:
java
//后续遍历
public static void postOrder(KunBinaryTree root){
if(root == null){
return ;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.no +" "+root.name+" ");
}
输出结果:
**后序遍历结果:**3 2 5 6 4 1
小结:
比较各个遍历的过程
前序遍历:根结点 ---> 左子树 ---> 右子树
中序遍历:左子树---> 根结点 ---> 右子树
后序遍历:左子树 ---> 右子树 ---> 根结点
前中后其实说的就是根节点遍历的顺序
2.二叉树的前中后续查找:
有了前中后续遍历的实现,我们接着就能实现查找过程,这是基于遍历来实现的
2.1二叉树的前序查找:
基本思路:
1.先判断当前节点的no(序号)是否等于要查找的
2.如果是相等的,则返回当前节点
3.如果不等,则判断当前节点的左右子节点是否为空,如果不为空,则递归前序查找
4.如果左递归前序查找找到节点,则返回,否则继续判断当前节点的左右子节点是否为空,如果不为空,则继续右递归前序查找
代码实现:
java
// 前序查找
public BTNode preOrderSearch(BTNode node, int value) {
if (node == null) {
return null; // 如果节点为空,返回 null
}
// 如果找到节点,返回该节点
if (node.value == value) {
return node;
}
// 在左子树中查找
BTNode foundNode = preOrderSearch(node.left, value);
if (foundNode != null) {
return foundNode; // 如果在左子树找到,直接返回
}
// 在右子树中查找
return preOrderSearch(node.right, value);
}
2.2二叉树的中序查找:
基本思路:
1.判断当前节点的左右子节点是否为空,如果不为空,则递归中序查找
2.如果找到,则返回,若果没有找到,就和当前节点比较,如果是则返回当前节点,否则继续进行右递归的中序查找
3.右递归中序查找,找到就返回,否则返回null
cs
// 中序查找
public BTNode preOrderSearch(BTNode node, int value) {
if (node == null) {
return null; // 如果节点为空,返回 null
}
// 在左子树中查找
BTNode foundNode = preOrderSearch(node.left, value);
if (foundNode != null) {
return foundNode; // 如果在左子树找到,直接返回
}
// 如果找到节点,返回该节点
if (node.value == value) {
return node;
}
// 在右子树中查找
return preOrderSearch(node.right, value);
}
2.2二叉树的后续查找:
基本思路:
1.判断当前节点的左子节点是否为空,如果不为空,则递归后序查找
2.如果找到,就返回,如果没有找到,就判断当前节点的有子节点是否为空,如果不为空,则右递归进行后序查找,如果找到,就返回
3.接着和当前节点进行比较,找到则返回,否则返回null
代码实现:
java
// 前序查找
public BTNode preOrderSearch(BTNode node, int value) {
if (node == null) {
return null; // 如果节点为空,返回 null
}
// 在左子树中查找
BTNode foundNode = preOrderSearch(node.left, value);
if (foundNode != null) {
return foundNode; // 如果在左子树找到,直接返回
}
// 在右子树中查找
return preOrderSearch(node.right, value);
}
// 如果找到节点,返回该节点
if (node.value == value) {
return node;
}
}
3 二叉树节点删除操作:
完成删除结点的操作
规定:
1)如果删除的节点是叶子节点 ,则删除该节点
2)如果删除的节点是非叶子节点 ,则删除该子树
思路
首先先处理:
考虑如果树是空树root,如果只有一个root结点,则等价将二叉树置空
步骤:
1.因为我们的二叉树是单向的,所以我们是判断当前结点的子结点是来需要删除而不能去判断当前这个结点是不是需要删除结点.
2.如果当前结点的左子结点不为空,并且左子结点就是要删除结点,就将this.left并且就返回(结束递归删除)
3.如果当前结点的右子结点不为空,并且右子结点就是要删除结点,就将this.righ null;并且就返回(结束递归删除)
4.如果第2和第3步没有删除结点,那么我们就需要向左子树进行递归删除
- 如果第4步也没有删除结点,则应当向右子树进行递归删除.
java
//删除节点
public static void delTreeNode(KunBinaryTree root,int no){
if(root.no == no){
root = null;
}else{
if(root.left != null && root.left.no == no){
root.left = null;
return ;
}
if(root.right != null && root.right.no == no){
root.right = null;
return ;
}
if(root.left != null){
delTreeNode(root.left,no);
}
if(root.right != null){
delTreeNode(root.right,no);
}
}
}
当我们删除4这个子节点时,后面的节点也一并删除了:
下面主要分析前序递归遍历,中序与后序图解类似,同学们可自己动手绘制。
最后,完整代码:
java
public class Main {
public static void main(String[] args) {
BinaryTree b = new BinaryTree();
b.createBinaryTree();
System.out.println("前序遍历:");
b.preOrderTraversal(b.getRoot());
System.out.println("\n中序遍历:");
b.inOrderTraversal(b.getRoot());
System.out.println("\n后序遍历:");
b.postOrderTraversal(b.getRoot());
BinaryTree.BTNode foundNode = b.preOrderSearch(b.getRoot(),5);
if (foundNode != null) {
System.out.println("\n找到节点: " + foundNode.value);
} else {
System.out.println("\n未找到节点值: " + 5);
}
System.out.println("删除前");
System.out.println("前序遍历:");
b.preOrderTraversal(b.getRoot());
System.out.println("删除后");
b.delTreeNode(b.getRoot(),4);
System.out.println("前序遍历:");
b.preOrderTraversal(b.getRoot());
}
}
java
public class BinaryTree {
public static class BTNode {
BTNode left;
BTNode right;
int value;
BTNode(int value) {
this.value = value;
}
}
private BTNode root;
public void createBinaryTree() {
BTNode node1 = new BTNode(1);
BTNode node2 = new BTNode(2);
BTNode node3 = new BTNode(3);
BTNode node4 = new BTNode(4);
BTNode node5 = new BTNode(5);
BTNode node6 = new BTNode(6);
root = node1;
node1.left = node2;
node2.left = node3;
node1.right = node4;
node4.left = node5;
node4.right = node6;
}
// 前序遍历
public void preOrderTraversal(BTNode node) {
if (node == null) return;
System.out.print(node.value + " ");
preOrderTraversal(node.left);
preOrderTraversal(node.right);
}
// 中序遍历
public void inOrderTraversal(BTNode node) {
if (node == null) return;
inOrderTraversal(node.left);
System.out.print(node.value + " ");
inOrderTraversal(node.right);
}
// 后序遍历
public void postOrderTraversal(BTNode node) {
if (node == null) return;
postOrderTraversal(node.left);
postOrderTraversal(node.right);
System.out.print(node.value + " ");
}
public BTNode getRoot() {
return root;
}
// 前序查找
public BTNode preOrderSearch(BTNode node, int value) {
if (node == null) {
return null; // 如果节点为空,返回 null
}
// 如果找到节点,返回该节点
if (node.value == value) {
return node;
}
// 在左子树中查找
BTNode foundNode = preOrderSearch(node.left, value);
if (foundNode != null) {
return foundNode; // 如果在左子树找到,直接返回
}
// 在右子树中查找
return preOrderSearch(node.right, value);
}
//删除节点
public static void delTreeNode(BTNode root,int value){
if(root.value == value){
root = null;
}else{
if(root.left != null && root.left.value == value){
root.left = null;
return ;
}
if(root.right != null && root.right.value == value){
root.right = null;
return ;
}
if(root.left != null){
delTreeNode(root.left,value);
}
if(root.right != null){
delTreeNode(root.right,value);
}
}
}
}
到这里,竹竹零就要和大家说再见了🍕🍕🍕
如果您觉得有失偏颇请您在评论区指正,如果您觉得不错的话留个好评再走吧!!
您的鼓励就是对我最大的支持! ! !