二叉树

简介: 二叉树

二叉树是一种常见的树状数据结构,它由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。在 Java 中,可以使用类来表示二叉树。

首先,我们需要定义一个表示二叉树节点的类,可以包含一个值和左右子节点的引用。例如:

class TreeNode {
   
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode(int val) {
   
        this.val = val;
    }
}

然后,我们可以创建二叉树并操作节点。

// 创建一个二叉树
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);

// 遍历二叉树
// 1. 前序遍历(根-左-右)
System.out.print("Preorder traversal: ");
preorderTraversal(root);
System.out.println();

// 2. 中序遍历(左-根-右)
System.out.print("Inorder traversal: ");
inorderTraversal(root);
System.out.println();

// 3. 后序遍历(左-右-根)
System.out.print("Postorder traversal: ");
postorderTraversal(root);
System.out.println();

在上述代码中,我们创建了一个简单的二叉树,并对其进行了三种常见的遍历操作:前序遍历、中序遍历和后序遍历。这些遍历方式可以按照不同顺序访问二叉树的节点。

以下是遍历二叉树的示例实现:

// 前序遍历
public static void preorderTraversal(TreeNode node) {
   
    if (node == null) {
   
        return;
    }
    System.out.print(node.val + " ");
    preorderTraversal(node.left);
    preorderTraversal(node.right);
}

// 中序遍历
public static void inorderTraversal(TreeNode node) {
   
    if (node == null) {
   
        return;
    }
    inorderTraversal(node.left);
    System.out.print(node.val + " ");
    inorderTraversal(node.right);
}

// 后序遍历
public static void postorderTraversal(TreeNode node) {
   
    if (node == null) {
   
        return;
    }
    postorderTraversal(node.left);
    postorderTraversal(node.right);
    System.out.print(node.val + " ");
}

通过调用以上的遍历方法,我们可以输出二叉树的节点值。

好的,我们来详细介绍如何在二叉树中查找节点、插入节点和删除节点。这些操作对于二叉搜索树(Binary Search Tree, BST)尤为重要,因为 BST 的特性使得这些操作更高效。

查找节点

在二叉搜索树中,查找节点是相对简单的。我们根据当前节点的值与目标值的大小关系来决定向左子树还是右子树递归查找。

public TreeNode search(TreeNode root, int key) {
   
    if (root == null || root.val == key) {
   
        return root;
    }
    if (key < root.val) {
   
        return search(root.left, key);
    } else {
   
        return search(root.right, key);
    }
}

插入节点

在二叉搜索树中插入节点,需要找到合适的位置插入新节点。新节点应该插入到叶节点的位置。

public TreeNode insert(TreeNode root, int key) {
   
    if (root == null) {
   
        return new TreeNode(key);
    }
    if (key < root.val) {
   
        root.left = insert(root.left, key);
    } else {
   
        root.right = insert(root.right, key);
    }
    return root;
}

删除节点

删除节点是最复杂的操作,因为需要考虑三种情况:

  1. 节点没有子节点(直接删除)。
  2. 节点有一个子节点(将子节点移到该节点的位置)。
  3. 节点有两个子节点(需要找到中序后继或者中序前驱节点来替代该节点)。
public TreeNode delete(TreeNode root, int key) {
   
    if (root == null) {
   
        return null;
    }
    if (key < root.val) {
   
        root.left = delete(root.left, key);
    } else if (key > root.val) {
   
        root.right = delete(root.right, key);
    } else {
   
        // 找到要删除的节点
        if (root.left == null) {
   
            return root.right;
        } else if (root.right == null) {
   
            return root.left;
        }
        // 节点有两个子节点,找到右子树中的最小值节点(中序后继)
        TreeNode minNode = findMin(root.right);
        root.val = minNode.val;
        root.right = delete(root.right, minNode.val);
    }
    return root;
}

private TreeNode findMin(TreeNode node) {
   
    while (node.left != null) {
   
        node = node.left;
    }
    return node;
}

在这个删除节点的方法中,findMin 方法用于找到右子树中的最小值节点,即中序后继节点。在删除节点时,如果要删除的节点有两个子节点,就用中序后继节点的值替换该节点的值,然后在右子树中删除中序后继节点。

示例代码

public class BinaryTreeOperations {
   

    public static void main(String[] args) {
   
        TreeNode root = new TreeNode(50);
        root = insert(root, 30);
        root = insert(root, 20);
        root = insert(root, 40);
        root = insert(root, 70);
        root = insert(root, 60);
        root = insert(root, 80);

        System.out.print("Inorder traversal: ");
        inorderTraversal(root);
        System.out.println();

        System.out.println("Search for 40: " + (search(root, 40) != null ? "Found" : "Not Found"));

        System.out.println("Delete 20");
        root = delete(root, 20);
        System.out.print("Inorder traversal: ");
        inorderTraversal(root);
        System.out.println();

        System.out.println("Delete 30");
        root = delete(root, 30);
        System.out.print("Inorder traversal: ");
        inorderTraversal(root);
        System.out.println();

        System.out.println("Delete 50");
        root = delete(root, 50);
        System.out.print("Inorder traversal: ");
        inorderTraversal(root);
        System.out.println();
    }

    public static TreeNode search(TreeNode root, int key) {
   
        // ... (search method as defined above)
    }

    public static TreeNode insert(TreeNode root, int key) {
   
        // ... (insert method as defined above)
    }

    public static TreeNode delete(TreeNode root, int key) {
   
        // ... (delete method as defined above)
    }

    private static TreeNode findMin(TreeNode node) {
   
        // ... (findMin method as defined above)
    }

    public static void inorderTraversal(TreeNode node) {
   
        if (node == null) {
   
            return;
        }
        inorderTraversal(node.left);
        System.out.print(node.val + " ");
        inorderTraversal(node.right);
    }
}

class TreeNode {
   
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
   
        this.val = val;
    }
}
目录
相关文章
|
9月前
|
机器学习/深度学习 存储 算法
深入理解【二叉树】
深入理解【二叉树】
55 0
|
9月前
|
C语言
【二叉树】的实现
【二叉树】的实现
23 0
|
2月前
|
存储
二叉树详解
二叉树详解
28 2
|
11月前
二叉树的讲解
1.若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1) 个结点. 2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是 2^h-1. 3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为02 ,则有n0 =n2 +1 4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h= . (ps: 是log以2为底,n+1为对数) 5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的结点有:
二叉树的讲解
|
2月前
|
算法 网络协议 NoSQL
认识二叉树(详细介绍)
认识二叉树(详细介绍)
|
11月前
|
存储
|
2月前
|
存储 数据库管理
【二叉树】
【二叉树】
37 0
|
2月前
|
存储 Java C++
二叉树的实现(上)
二叉树的实现
48 0
|
8月前
24 二叉树
24 二叉树
34 0
|
11月前
|
存储
二叉树_详解
二叉树的详解