N元树数据结构

一元树数据结构

N元树是一棵树,它使我们可以拥有n一个特定节点的子节点数目,因此命名为N-ary,这使其比非常常见的二叉树(使我们最多具有两个特定子节点的树)更为复杂。节点。

N元树的图形表示如下所示:

 

在上面显示的N元树中,我们可以注意到总共有11个节点有些节点有3个子节点,有些只有一个。在二叉树的情况下,存储这些子节点更为容易,因为我们可以将两个节点(即左右)分配给一个特定的节点以标记其子节点,但这并不是那么简单。为了存储任何树节点的子节点,我们使用了另一种数据结构,主要是C ++中的vector和Java中的LinkedList。

N元树的实现

处理非线性数据结构时,我们要做的第一件事就是为它们创建自己的结构(Java中的构造函数)。就像在二叉树的情况下一样,我们使用一个类,TreeNode并且在该类内部,我们创建了构造函数并具有了类级变量。

考虑下面的代码片段:

public static class TreeNode{
        int val;
        List<TreeNode> children = new LinkedList<>();

        TreeNode(int data){
            val = data;
        }

        TreeNode(int data,List<TreeNode> child){
            val = data;
            children = child;
        }
}

在上面的代码片段中,我们有一个名为的类,该类TreeNode又包含两个具有相同名称的构造函数,但实际上它们是重载的(相同的方法名称,但参数不同)。我们还有两个标识符,其中之一是val,用于存储任何特定节点的值,然后,我们具有一个List,用于存储树的任何节点的子节点。

上面的代码段包含了我们树的基本结构,现在只剩下一个树了,随后我们将看到如何使用级别顺序遍历来打印树。为了构建一棵树,我们将利用我们在上面的类中定义的构造函数。

考虑下面的代码片段:

public static void main(String[] args) {
        // creating an exact replica of the above pictorial N-ary Tree
        TreeNode root = new TreeNode(1);
        root.children.add(new TreeNode(2));
        root.children.add(new TreeNode(3));
        root.children.add(new TreeNode(4));
        root.children.get(0).children.add(new TreeNode(5));
        root.children.get(0).children.add(new TreeNode(6));
        root.children.get(0).children.add(new TreeNode(7));
        root.children.get(1).children.add(new TreeNode(8));
        root.children.get(2).children.add(new TreeNode(9));
        root.children.get(2).children.add(new TreeNode(10));
        root.children.get(2).children.add(new TreeNode(11));
        printNAryTree(root);
}

首先,我们创建了N元树根节点,然后必须为该根节点分配一些子节点,方法是使用dot(.)运算符并访问该根节点的children属性,然后然后使用List接口提供的add方法将不同的子级添加到根节点。一旦添加了根节点的所有子节点,就该添加每个新级别节点的子节点了,我们首先通过使用list接口提供的get方法访问该节点,然后添加相应的子节点来进行此操作节点到该节点。

最后,我们打印此N元树,我们通过调用printNAryTree方法来做到这一点。

现在,由于打印一棵树并不像遍历一组项目那样简单,因此我们可以使用不同的技术(精确地计算算法)。这些主要是:

  • 有序遍历

     

  • 预购遍历

  • 后订单遍历

  • 级别顺序遍历

在本教程中,我们将使用“级别顺序遍历”方法,因为它很容易理解,前提是您之前已经了解了它如何在二叉树上工作。

级别顺序遍历(打印N元树)

对任何树的“级别顺序”遍历都考虑到这样一个事实,我们要先在根级别上打印节点,然后再转到下一个级别,并继续重复此过程,直到我们到达最后一个级别为止。我们利用队列数据结构来存储特定级别的节点。

考虑下面显示的简单N元树:

 

以上树的“级别顺序遍历”如下所示:

1
2 3 4 5

考虑下面的代码片段:

private static void printNAryTree(TreeNode root){
        if(root == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            int len = queue.size();
            for(int i=0;i<len;i++) { // so that we can reach each level
                TreeNode node = queue.poll();
                System.out.print(node.val + " ");
                for (TreeNode item : node.children) { // for-Each loop to iterate over all childrens
                    queue.offer(item);
                }
            }
            System.out.println();
        }
}

整个代码如下所示:

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

public class NAryTree {
    public static class TreeNode{
        int val;
        List<TreeNode> children = new LinkedList<>();

        TreeNode(int data){
            val = data;
        }

        TreeNode(int data,List<TreeNode> child){
            val = data;
            children = child;
        }
    }

    private static void printNAryTree(TreeNode root){
        if(root == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            int len = queue.size();
            for(int i=0;i<len;i++) {
                TreeNode node = queue.poll();
                assert node != null;
                System.out.print(node.val + " ");
                for (TreeNode item : node.children) {
                    queue.offer(item);
                }
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.children.add(new TreeNode(2));
        root.children.add(new TreeNode(3));
        root.children.add(new TreeNode(4));
        root.children.get(0).children.add(new TreeNode(5));
        root.children.get(0).children.add(new TreeNode(6));
        root.children.get(0).children.add(new TreeNode(7));
        root.children.get(1).children.add(new TreeNode(8));
        root.children.get(2).children.add(new TreeNode(9));
        root.children.get(2).children.add(new TreeNode(10));
        root.children.get(2).children.add(new TreeNode(11));
        printNAryTree(root);
    }
}

上面代码的输出是:

1 2 3 4 5 6 7 8 9 10 11

 

我们可以将此输出与开始时使用的N元树的图形表示形式进行比较,每个级别节点包含相同的值。

一元树的类型

以下是N元树的类型:

1.完整的N元树

完整N元树是一个N元树,它允许每个节点具有0个或N个子节点。

考虑以下所示的完整N元树的图形表示形式:

 

请注意,以上N元的所有节点都具有4个子节点或0个子节点,因此满足该属性。

2.完整的N元树

完整的N元树是一棵N元树,其中除最后一级节点外,该树的每一级上的节点都应完整(应该有N个子节点),如果最后一级节点不完整,则这些节点必须“尽可能左”。

考虑以下所示的完整N元树的图形表示形式:

 

3.完美的N元树

理想的N元树是完整的N元树,但是叶节点的级别必须相同。

考虑以下所示的理想N元树的图形表示形式:

 

结论

  • 我们了解了什么是N元树。
  • 我们还学习了如何在Java中实现N元树(通过级别顺序遍历)。
  • 然后,我们了解了总共有不同类型的N元树。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值