关于#数据结构#的问题,如何解决?(语言-java)

用java语言。该问题是关于树的存储和操作实现。
使用孩⼦兄弟表⽰法作为树的存储结构,输入树中的顶点值及对应的关系创建树后,求树中结点的个数、求树的深度、求结点的children个数、实现树的先根、后根和层次遍历。

1、求树中结点的个数:
可以使用递归来求树中结点的个数。具体来说,可以递归遍历整棵树,对于每一个遍历到的结点,都将结果加1:

public int getNodeCount(CSBTreeNode root) {
    if (root == null) {
        return 0;
    }
    int count = 1;
    CSBTreeNode child = root.firstChild;
    while (child != null) {
        count += getNodeCount(child);
        child = child.nextSibling;
    }
    return count;
}

2、
求树的深度可以使用递归来实现。具体来说,对于一棵树的根结点,可以递归地求出它的每一个子结点的深度,然后取最大值加1作为当前结点的深度:

public int getDepth(CSBTreeNode root) {
    if (root == null) {
        return 0;
    }
    int depth = 1;
    CSBTreeNode child = root.firstChild;
    while (child != null) {
        depth = Math.max(depth, getDepth(child) + 1);
        child = child.nextSibling;
    }
    return depth;
}

3、
求结点的children个数:
可以使用递归来求结点的children个数。具体来说,可以递归遍历结点的每一个子结点,对于每一个遍历到的子结点,都将结果加1:

public int getChildCount(CSBTreeNode node) {
    if (node == null || node.firstChild == null) {
        return 0;
    }
    int count = 1;
    CSBTreeNode child = node.firstChild.nextSibling;
    while (child != null) {
        count++;
        child = child.nextSibling;
    }
    return count;
}

4、
实现树的先根遍历:
先根遍历是指先遍历根结点,然后递归遍历每一个子结点。可以使用递归来实现先根遍历:

public void preOrderTraversal(CSBTreeNode root) {
    if (root == null) {
        return;
    }
    System.out.println(root.val);
    CSBTreeNode child = root.firstChild;
    while (child != null) {
        preOrderTraversal(child);
        child = child.nextSibling;
    }
}

5、
实现树的后根遍历:
后根遍历是指先递归遍历每一个子结点,然后遍历根结点。可以使用递归来实现后根遍历:

public void postOrderTraversal(CSBTreeNode root) {
    if (root == null) {
        return;
    }
    CSBTreeNode child = root.firstChild;
    while (child != null) {
        postOrderTraversal(child);
        child = child.nextSibling;
    }
    System.out.println(root.val);
}

6、
实现树的层次遍历:
层次遍历是指按照树的层次依次遍历每一个结点。可以使用队列来实现层次遍历。首先将根结点入队,然后只要队列不为空,就依次取出队列中的结点,并将它的子结点入队:

public void levelOrderTraversal(CSBTreeNode root) {
    if (root == null) {
        return;
    }
    Queue<CSBTreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        CSBTreeNode node = queue.poll();
        System.out.println(node.val);
        CSBTreeNode child = node.firstChild;
        while (child != null) {
            queue.offer(child);
            child = child.nextSibling;
        }
    }
}

仅供参考,望采纳,谢谢。

我写了一段使用孩子兄弟表示法存储树并实现上述操作的 Java 代码,你试试看:

class Node {
    int val;
    Node firstChild;
    Node nextSibling;

    public Node(int val) {
        this.val = val;
        firstChild = null;
        nextSibling = null;
    }
}

class Tree {
    Node root;

    public Tree(Node root) {
        this.root = root;
    }

    // 计算树中结点的个数
    public int countNodes() {
        return countNodes(root);
    }

    private int countNodes(Node node) {
        if (node == null)
            return 0;
        int count = 1;
        Node child = node.firstChild;
        while (child != null) {
            count += countNodes(child);
            child = child.nextSibling;
        }
        return count;
    }

    // 计算树的深度
    public int getDepth() {
        return getDepth(root);
    }

    private int getDepth(Node node) {
        if (node == null)
            return 0;
        int depth = 0;
        Node child = node.firstChild;
        while (child != null) {
            depth = Math.max(depth, getDepth(child));
            child = child.nextSibling;
        }
        return depth + 1;
    }

    // 计算结点的 children 个数
    public int countChildren(Node node) {
        int count = 0;
        Node child = node.firstChild;
        while (child != null) {
            count++;
            child = child.nextSibling;
        }
        return count;
    }

    // 实现树的先根遍历
    public void preOrderTraversal() {
        preOrderTraversal(root);
    }

    private void preOrderTraversal(Node node) {
        if (node == null)
            return;
        System.out.print(node.val + " ");
        Node child = node.firstChild;
        while (child != null) {
            preOrderTraversal(child);
            child = child.nextSibling;
        }
    }

    // 实现树的后根遍历
    public void postOrderTraversal() {
        postOrderTraversal(root);
    }

    private void postOrderTraversal(Node node) {
        if (node == null)
            return;
        Node child = node.firstChild;
        while (child != null) {
            postOrderTraversal(child);
            child = child.nextSibling;
        }
        System.out.print(node.val + " ");
    }

    // 实现树的层次遍历
public void levelOrderTraversal() {
Queue<Node> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
Node node = queue.poll();
System.out.print(node.val + " ");
Node child = node.firstChild;
while (child != null) {
queue.offer(child);
child = child.nextSibling;
}
}
}
}

public class Main {
public static void main(String[] args) {
// 创建树
Node a = new Node('A');
Node b = new Node('B');
Node c = new Node('C');
Node d = new Node('D');
Node e = new Node('E');
Node f = new Node('F');
Node g = new Node('G');
a.firstChild = b;
b.nextSibling = c;
b.firstChild = d;
d.nextSibling = e;
c.firstChild = f;
f.nextSibling = g;
Tree tree = new Tree(a);

    // 测试
    System.out.println("结点个数:" + tree.countNodes());
    System.out.println("树的深度:" + tree.getDepth());
System.out.println("D 结点的 children 个数:" + tree.countChildren(d));
System.out.print("先根遍历:");
tree.preOrderTraversal();
System.out.println();
System.out.print("后根遍历:");
tree.postOrderTraversal();
System.out.println();
System.out.print("层次遍历:");
tree.levelOrderTraversal();
}


计算树中结点的个数
首先定义一个计数器count,初始值为0。然后遍历树中所有的结点,每遍历到一个结点,就将count加1。最终得到的count即为树中结点的个数。

计算树的深度
首先定义一个计数器depth,初始值为0。然后遍历树中所有的结点,每遍历到一个结点,就将该结点的深度与depth进行比较,取较大值并赋值给depth。最终得到的depth即为树的深度。

计算结点的children个数
首先定义一个计数器children,初始值为0。然后遍历树中所有的结点,每遍历到一个结点,就将该结点的children个数加到children上。最终得到的children即为树中所有结点的children个数之和。

实现树的先根遍历
先根遍历需要使用栈进行实现。首先将根结点压入栈中,然后取出栈顶结点并访问。接着将该结点的所有子结点从左到右压入栈中,再取出栈顶结点并访问,直到栈为空。

实现树的后根遍历
后根遍历需要使用栈进行实现。首先将根结点压入栈中,然后取出栈顶结点的所有子结点从左到右压入栈中,直到栈为空。每次从栈中取出结点时,都将该结点的值记录到结果数组中,最后将结果数组倒序输出即为后根遍历的结果。

实现树的层次遍历
层次遍历需要使用队列进行实现。首先将根结点入队,然后每次从队列中取出一个结点并访问。接着将该结点的所有子结点从左到右依次入队,直到队列为空。

vqilai01@163.com
继续

所有子结点从左到右压入栈中,直到栈为空。每次从栈中取出结点时,都将该结点的值记录到结果数组中,最后将结果数组倒序输出即为后根遍历的结果。

实现树的层次遍历
层次遍历需要使用队列进行实现。首先将根结点入队,然后每次从队列中取出一个结点并访问。接着将该结点的所有子结点从左到右依次入队,直到队列为空。

下面是一个例子,展示了如何使用孩子兄弟表示法来实现树的存储和操作:

class TreeNode {
    int val;
    TreeNode parent;
    TreeNode firstChild;
    TreeNode nextSibling;

    public TreeNode(int val) {
        this.val = val;
        this.parent = null;
        this.firstChild = null;
        this.nextSibling = null;
    }
}

class Tree {
    TreeNode root;

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

    // 返回树中节点的个数
    public int getNodeCount() {
        return getNodeCount(root);
    }

    private int getNodeCount(TreeNode node) {
        if (node == null) {
            return 0;
        }
        int count = 1;
        TreeNode child = node.firstChild;
        while (child != null) {
            count += getNodeCount(child);
            child = child.nextSibling;
        }
        return count;
    }

    // 返回树的深度
    public int getDepth() {
        return getDepth(root);
    }

    private int getDepth(TreeNode node) {
        if (node == null) {
            return 0;
        }
        int depth = 0;
        TreeNode child = node.firstChild;
        while (child != null) {
            depth = Math.max(depth, getDepth(child));
            child = child.nextSibling;
        }
        return depth + 1;
    }

    // 返回结点的 children 个数
    public int getChildCount(TreeNode node) {
        if (node == null || node.firstChild == null) {
            return 0;
        }
        int count = 1;
        TreeNode child = node.firstChild.nextSibling;
        while (child != null) {
            count++;
            child = child.nextSibling;
        }
        return count;
    }

   // 先根遍历
public void preOrder(TreeNode node) {
if (node == null) {
return;
}
System.out.println(node.val);
TreeNode child = node.firstChild;
while (child != null) {
preOrder(child);
child = child.nextSibling;
}
}
// 后根遍历
public void postOrder(TreeNode node) {
    if (node == null) {
        return;
    }
    TreeNode child = node.firstChild;
    while (child != null) {
        postOrder(child);
        child = child.nextSibling;
    }
    System.out.println(node.val);
}

// 层次遍历
public void levelOrder() {
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        System.out.println(node.val);
        TreeNode child = node.firstChild;
        while (child != null) {
            queue.offer(child);
            child = child.nextSibling;
        }
    }
}
}

为了使用孩子兄弟表示法来存储树,您需要定义一个结构体或类来表示每个结点。该结构体应该包含以下几个字段:

  • 一个存储结点值的字段
  • 一个指向该结点的第一个孩子的指针
  • 一个指向该结点的兄弟的指针

下面是一个示例实现:

public class TreeNode {
  int value;
  TreeNode firstChild;
  TreeNode nextSibling;

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

下面是如何实现上述操作的一些提示:

  • 求树中结点的个数:您可以使用递归来遍历树中的所有结点,并统计结点的数量。

  • 求树的深度:您可以递归地遍历树的所有子树,并求出每个子树的深度。然后,取所有子树的最大深度并将其加 1(用于计算当前结点的深度)。

  • 求结点的 children 个数:您可以使用递归来遍历该结点的所有孩子,并统计孩子的数量。

  • 实现树的先根、后根和层次遍历:您可以使用递归来实现先根遍历和后根遍历。对于层次遍历,您可以使用队列来存储每层的结点,然后依次遍历每层的结点。

下面是一个示例实现,该实现使用孩子兄弟表示法存储树,并实现了计算树中结点的个数、求树的深度、求结点的 children 个数、实现树的先根、后根和层次遍历的功能。

import java.util.LinkedList;
import java.util.Queue;

public class Tree {
    private TreeNode root;

    public Tree(int value) {
        root = new TreeNode(value);
    }

    // 计算树中结点的个数
    public int countNodes() {
        return countNodes(root);
    }

    private int countNodes(TreeNode node) {
        if (node == null) {
            return 0;
        }
        int count = 1;
        for (TreeNode child = node.firstChild; child != null; child = child.nextSibling) {
            count += countNodes(child);
        }
        return count;
    }

    // 求树的深度
    public int getDepth() {
        return getDepth(root);
    }

    private int getDepth(TreeNode node) {
        if (node == null) {
            return 0;
        }
        int maxDepth = 0;
        for (TreeNode child = node.firstChild; child != null; child = child.nextSibling) {
            int depth = getDepth(child);
            if (depth > maxDepth) {
                maxDepth = depth;
            }
        }
        return maxDepth + 1;
    }

    // 求结点的 children 个数
    public int countChildren(int value) {
        TreeNode node = findNode(value, root);
        if (node == null) {
            return 0;
        }
        int count = 0;
        for (TreeNode child = node.firstChild; child != null; child = child.nextSibling) {
            count++;
        }
        return count;
    }

    // 实现树的先根遍历
    public void preOrderTraversal() {
        preOrderTraversal(root);
    }

    private void preOrderTraversal(TreeNode node) {
        if (node == null) {
            return;
        }
        System.out.print(node.value + " ");
        for (TreeNode child = node.firstChild; child != null; child = child.nextSibling) {
            preOrderTraversal(child);
        }
    }

    // 实现树的后根遍历
    public void postOrderTraversal() {
        postOrderTraversal(root);
    }

    private void postOrderTraversal(TreeNode node) {
        if (node == null) {
            return;
        }
        for (TreeNode child = node.firstChild; child != null; child = child.nextSibling) {
            postOrderTraversal(child);
        }
        System.out.print(node.value + " ");
    }

    // 实现树的层次遍历
    public void levelOrderTraversal() {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            System.out.print(node.value + " ");
            for (TreeNode child = node.firstChild; child != null; child = child.nextSibling) {
                queue.add(child);
            }
        }
    }

    private TreeNode findNode(int value, TreeNode node) {
        if (node == null || node.value == value) {
            return node;
        }
        for (TreeNode child = node.firstChild; child != null; child = child.nextSibling) {
            TreeNode found = findNode(value, child);
            if (found != null) {
                return found;
            }
        }
        return null;
    }
}

可以使用以下步骤:

定义一个类来表示树中的节点,该类应包含节点的值、父节点的引用、左儿子的引用和右哥哥的引用。这样就可以使用孩子兄弟表示法来存储树。

实现一个方法,该方法接受节点的值和父节点的引用,并创建一个新节点。

实现一个方法,该方法实现一个方法,该方法可以计算树中节点的个数。可以使用递归的方法来实现,先求出当前节点的子树中节点的个数,然后加上1(当前节点本身)即为树中节点的总数。

实现一个方法,该方法可以计算树的深度。可以使用递归的方法来实现,对于当前节点的每个子节点,递归调用该方法求出它们的子树的深度,然后取最大值加1即为当前节点的子树的深度。

实现一个方法,该方法可以计算节点的子节点个数。可以使用递归的方法来实现,对于当前节点的每个子节点,递归调用该方法求出它们的子节点个数,然后累加起来即为当前节点的子节点个数。

实现树的先根遍历,可以使用递归的方法,先访问当前节点,然后依次访问它的左儿子和右儿子。

实现树的后根遍历,可以使用递归的方法,先依次访问当前先依次访问当前节点的左儿子和右儿子,然后访问当前节点。

实现树的层次遍历,可以使用队列实现树的层次遍历,可以使用队列来实现。首先将根节点入队,然后进行如下操作:从队头取出一个节点,访问该节点,然后将它的左儿子和右儿子依次入队。重复这个过程,直到队列为空。

参考下我的写的:如果对你有所帮助,还请采纳。

//创建HeroNode结点
@Data
class HeroNode{
    private int no;
    private String name;
    private HeroNode left;//默认为null
    private HeroNode right;//默认为null
 
    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "HeroNode [no=" + no + ", name=" + name + "]";
    }
 
    //前序遍历
    public void preOrder(){
        System.out.println(this);//先输出父结点(谁调用这个方法,谁就是this)
        //递归向左子树前序遍历
        if(this.left!=null){
            this.left.preOrder();
        }
        //递归向右子树前序遍历
        if(this.right!=null){
            this.right.preOrder();
        }
    }
    
    //中序遍历
    public void infixOrder(){
        //递归向左子树中序遍历
        if(this.left!=null){
            this.left.infixOrder();
        }
        //输出父结点
        System.out.println(this);
        //递归向右子树中序遍历
        if(this.right!=null){
            this.right.infixOrder();
        }
    }
    
    //后序遍历
    public void postOrder(){
        //递归向左子树后序遍历
        if(this.left!=null){
            this.left.postOrder();
        }
        //递归向右子树后序遍历
        if(this.right!=null){
            this.right.postOrder();
        }
        //输出父结点
        System.out.println(this);
    }
}

写个main函数测试:

public static void main(String[] args) {
      //先需要创建一颗二叉树
      BinaryTree binaryTree=new BinaryTree();
      //创建需要的结点
        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,"武松");
        HeroNode node6=new HeroNode(6,"鲁智深");
        HeroNode node7=new HeroNode(7,"杨志");
 
        //说明,我们先手动创建该二叉树,后面我们学习递归的方式创建而常数
        root.setLeft(node2);
        root.setRight(node3);
        node2.setLeft(node4);
        node2.setRight(node5);
        node3.setLeft(node6);
        node3.setRight(node7);
 
        binaryTree.setRoot(root);
 
        //测试:
        System.out.println("前序遍历");//1,2,4,5,3,6,7
        binaryTree.preOrder();
 
        System.out.println("中序遍历");//4,2,5,1,6,3,7
        binaryTree.infixOrder();
        System.out.println("后序遍历");//4,5,2,6,7,3,1
        binaryTree.postOrder();
    }


参考该实例【java实现二叉树的(查找),(树的深度),(叶的个数),(结点个数)】,链接:https://blog.csdn.net/asfsaf21/article/details/112545816