Java中基于ArrayList的二叉树实现

时间:2013-04-01 21:12:53

标签: java oop recursion arraylist tree

我有3种方法可以递归实现。是的,这是为了学校,所以请,没有简单的&简单的答案,我会感谢描述性的答案,所以我可以学习!我是树结构的新手。

3种方法如下......

public class Zombies{
   public static int countPeople(Person p){...}
   // counts all the people in the tree structure 
   // starting with Person p. 

   public static int countZombies(Person p){...}
   // counts all the people in the tree structure
   // starting with Person p that are zombies

   public static void draw(Person p){...}
   // draws a diagram of the people in tree structure
   // starting with Person p.
   // each person will be denoted by a P and 
   // person that is a zombie will be denoted by a Z
   //
   // The diagram should illustrate the family tree
   // structure.  Each person will be drawn with 3 minus  
   // signs '-' for each level below p.

我已经开始了我的Person课程,我有几个问题。

1)我和我的班级人员在正确的轨道上

2)方法描述中提到的树结构是二叉树吗?

3)我缺少能够实现这些方法的东西(如果有什么东西,或者这个树结构需要构建块)

以下是我的Person类。

public class Person{

    public int     id;     // some identification number unique to the person
    public boolean zombie; // true if the person is a zombie
    public char    state;  // p means human, z means zombie

    public ArrayList<Person> friends;  // list of friends

    public Person(int id, char state, boolean zombie){
        this.id = id;
        this.state = state;
        this.zombie = zombie;
    }

    public boolean isZombie() {
        if (state == 'p'){
            return zombie=false;
        }
        else if (state == 'z'){
            return zombie=true;
        }
        return zombie;  
    }
}

树的类型输出如下..

P          (this is Person q)
---P       (this is a friend of q, say q1)
------P    (this is a friend of q1)
------Z    (this is another friend of q1, who is a zombie)
---Z       (this is a friend of q, say q2, who is a zombie)
------Z    (this is a friend of q1, who is also a zombie)
------P    (this is a friend of q1, who is not a zombie)

提前感谢您的耐心和帮助/输入!

4 个答案:

答案 0 :(得分:1)

希望这能让您对基于数组的二叉树的实现有所了解。

取自另一篇文章:

当您将二叉树写为数组时,您正在构建通常称为堆的数据。堆很好地记录在案,本文将为您提供有关如何实现它们的大量详细信息:

http://en.wikipedia.org/wiki/Binary_heap

链接到原文:

ArrayList Based Binary Tree - Java

编辑:

你正在做的是创建一个“Person”类的二叉树。每个“父母”人都有“朋友”,这将是“人”的孩子。如果“朋友”的数量限制为2,则这是二叉树格式。

树只是用于保存数据的组织结构......在您的情况下,不同的人。与您无关的二进制堆的部分是堆根据节点值进行组织。你不必担心这个。

所以你的班级Zombie可以接受任何人物和他们所有相关的“朋友”,并确定有多少人或僵尸等。

一个人的每个实例都会有一个朋友树,你可以从那个人那里访问。

使结构成为树的原因是从父级到子级的链接。所以person1有2个朋友,friend1和friend2。然后,您访问friend1,然后检查他是否有任何朋友。如果是这样,你检查朋友朋友等等。这是树可以帮助您导航信息的非常通用的解释。

基本上,如果树中的任何人有超过2个朋友,则它不再是二叉树。

看看这个:

http://en.wikibooks.org/wiki/A-level_Computing/AQA/Problem_Solving,_Programming,_Operating_Systems,_Databases_and_Networking/Programming_Concepts/Tree_traversal_algorithms_for_a_binary_tree

这是遍历树的示例。您可以在遍历时使值增加,以便为树中的僵尸或普通人提供数量。

如果这个解释看起来很分散,我很抱歉,但我很难理解你要做的事情和组织。

EDIT2:

好的,你可以从Zombie类中调用静态函数。你需要递归检查这个人和他所有的朋友。

如果您希望这是一个二叉树实现,每个人可以拥有不超过2个朋友。

如果不需要二叉树,那么每个人的朋友数组的大小没有限制。

基本上你需要做的是让Zombie类中的函数遍历所有人(朋友,朋友的朋友等),检查他们是否是僵尸。当您发现它们是否存在时,请打印以控制结果。继续前进。

请查看我上面发布的关于迭代树的链接,并将其应用于每个人的朋友的arraylist。递归迭代有不同的方法...所以选择一种样式(看起来你需要按顺序遍历)并以这种方式实现检查/打印功能。

这是一个主角,让我知道你是否再次陷入困境。理解树木所涉及的抽象可能很棘手。

答案 1 :(得分:1)

1)也许不是你想要的,但我会摆脱Person.state。有两个单独的字段,用于确定一个人是否是一个僵尸是混乱和容易出错。 zombietruestatep时,这意味着什么?

2)Miorel的评论有一些很好的见解。从你给我们的是什么树应该代表什么,为什么它必须是一棵树,或者它如何被填充,这不是很清楚。

3)你需要某种World对象。 Zombies可能是个不错的选择。在某个地方,显然,你需要一棵所有人的树。至少,你需要一些人的集合。该集合需要声明,实例化和填充。您可能希望它成为Zombies类的成员。绝对不是Person类的成员,你将拥有很多。

答案 2 :(得分:0)

Q1)我和我的班级人员走在正确的轨道上了吗?

从我的观点来看,我必须说不。

它出了什么问题?

你有冗余的逻辑。字段zombiestate指的是人类潜能的相同状态。

此时我们必须决定什么是僵尸,什么是人。行为,行为方式相同吗?根据我的观察,他们有一些共同的特征,但也有非常独特的表达元素。为了证明这一点,让我们想象一下我们站在人类面前,向他询问时间。他很可能会给我们一些逻辑答案。在完成问题之前,来自另一只手的僵尸肯定会尝试吃掉我们的大脑。

这就是为什么我会使用inherit mechanism而不是引入状态(btw应该是枚举)。

public class Person {

  private final int id;

  public Person(int id) {
   this.id = id;

  }

  public int hashCode() {
     return id;
  }

  public boolean equals(Object object) {

    if(object instance of Person) {
       return this.id == ((Person) object).id;
    }

    return false;
  }
}

public class Zombie : Person {

   public Zombie(int id) {
      super(id);
   }
)

如何证明朋友是人还是僵尸?

为此,您使用了方法isZombie。正如我们现在有两个具有此方法的类是不合理的。由于班级Zombie代表僵尸和Human。因此,在代码中使用类似if(human.isZombie())的内容,看起来很奇怪。

这就是OOP的力量所在。在检测到对象是这种类型或其他类型时,我们不会插入。我们想要的是呈现在控制台上(对于这种情况),通知用户该对象是人或僵尸的有效字符。

为了能够做到这一点,我们必须添加一个方法来类Human和[覆盖]它在类Zombie中。此方法将负责返回有效的char。

public class Person {

  //...   

  public char howDoOtherSeeMe() {

    return 'P';

  } 
}

public class Zombie : Person {

   //...

   @override
   public char howDoOtherSeeMe() {

    return 'Z';

  } 
}

Q2)方法描述中提到的树结构是二叉树吗?

A2。不是。定义中的二叉树只能有两个节点,并且不能有循环。在Person类中耦合结构也可以使类快速增长而无需控制。

答案 3 :(得分:0)

  1. 是的,我认为你走在了正确的轨道上。但是,正如其他人指出的那样,同时拥有char stateboolean zombie是多余的。就个人而言,在这种情况下,我认为继承是一种重大的矫枉过正 - 也许是可以理解的,在这种情况下,你可能以后想要拥有可能是“僵尸”或“吸血鬼”甚至是“狼人”的“人”。 “但是,我认为在这种情况下能够简单地说if (p.isZombie()) { ... }就足够了,但我会留下它,因为这是一个古老的设计论证 - 我属于”组合结束-inheritance“camp(http://en.wikipedia.org/wiki/Composition_over_inheritance

  2. 这确实是一个树结构,但是,我高度怀疑它是一个二叉树 - 基于规范,但是没有理由它不能< / em>是。对我来说,这似乎是一个N-Ary树。其中,如果您之前没有触及这些树,它们只是一个通用的树结构,其中每个节点可以有任意数量的子节点。此链接提供了更好的解释:http://www.brpreiss.com/books/opus5/html/page257.html(稍后会详细介绍)

  3. 你没有遗漏任何实现这些方法的东西(我可以说,这取决于你的教授 - 他们如何标记这个?运行他们自己的测试代码?看看你的代码?或者您是否提供演示其工作原理的客户端代码(主要方法)?如果他们正在运行测试代码,您必须确保您的Person API与其规范兼容。)

  4. 这里要理解的重要一点是,您创建的数据结构和 它代表一个N-Ary树。 Person类表示树中的单个节点(任何节点,可以是root,无关紧要),ArrayList<Person>存储属于该节点的每个子节点(或朋友)。它本质上是一个“链接结构”。考虑一下:

    class Node {
        public ArrayList<Node> children = new ArrayList<Node>();
    }
    

    这个班有0个或更多孩子(存储在children中),每个孩子都是Node(其中有0个或更多孩子)。

    因此,我可以轻松地将一些Node作为根Node,然后以这种方式构建树:

    Node root = new Node();
    root.children.add(new Node());
    root.children.add(new Node());
    root.children.get(0).children.add(new Node());
    root.children.get(0).children.add(new Node());
    

    从本质上讲,这将创建一个可能表示为这样的树:

        root
         /\
        /  \
       0    1
      / \
     /   \
    0     1
    

    现在,也许您可​​能会注意到我之前说过的原因“没有理由无法成为[二叉树]”从技术上讲,二叉树是N-Ary树,其中N = 2。

    另一个重要的事情(关于N-Ary树的前一个链接提到它)是每个节点可以被认为是它自己的N-Ary树。因此,例如,当您对方法说draw(Person p)时,p将始终是某些N-Ary树的根 - 无论它实际上是整个树的根还是只是树的一些子树的根。

    希望这有帮助!我知道你刚才发布了这个问题,所以我希望你能成功地完成这个问题,或者我不会太迟。如果没有,也许它会帮助别人:/

    此外,在解决这些问题(算法和数据结构)时要记住的重要事项是尽量不要被无关的细节所困扰,例如(在这种情况下),它们是否是不重要的“有些朋友可能是僵尸的人”,等等。这不是我们正在寻找的抽象!我们只想在树中代表这种关系!当然,这对于现实世界的问题将变得更加困难,因为我们并不总是被赋予最佳的数据结构,并且我们通常需要利用不同类型的数据结构来创建一些任务。

    始终尝试隔离问题的根源,然后从那里开始。通常你会发现很多问题只是添加细节/数据的另一个简单问题;或者甚至只是另一个问题的轻微变化。

    祝你好运。