我有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)
提前感谢您的耐心和帮助/输入!
答案 0 :(得分:1)
希望这能让您对基于数组的二叉树的实现有所了解。
取自另一篇文章:
当您将二叉树写为数组时,您正在构建通常称为堆的数据。堆很好地记录在案,本文将为您提供有关如何实现它们的大量详细信息:
http://en.wikipedia.org/wiki/Binary_heap
链接到原文:
ArrayList Based Binary Tree - Java
编辑:
你正在做的是创建一个“Person”类的二叉树。每个“父母”人都有“朋友”,这将是“人”的孩子。如果“朋友”的数量限制为2,则这是二叉树格式。
树只是用于保存数据的组织结构......在您的情况下,不同的人。与您无关的二进制堆的部分是堆根据节点值进行组织。你不必担心这个。
所以你的班级Zombie可以接受任何人物和他们所有相关的“朋友”,并确定有多少人或僵尸等。
一个人的每个实例都会有一个朋友树,你可以从那个人那里访问。
使结构成为树的原因是从父级到子级的链接。所以person1有2个朋友,friend1和friend2。然后,您访问friend1,然后检查他是否有任何朋友。如果是这样,你检查朋友朋友等等。这是树可以帮助您导航信息的非常通用的解释。
基本上,如果树中的任何人有超过2个朋友,则它不再是二叉树。
看看这个:
这是遍历树的示例。您可以在遍历时使值增加,以便为树中的僵尸或普通人提供数量。
如果这个解释看起来很分散,我很抱歉,但我很难理解你要做的事情和组织。
EDIT2:
好的,你可以从Zombie类中调用静态函数。你需要递归检查这个人和他所有的朋友。
如果您希望这是一个二叉树实现,每个人可以拥有不超过2个朋友。
如果不需要二叉树,那么每个人的朋友数组的大小没有限制。
基本上你需要做的是让Zombie类中的函数遍历所有人(朋友,朋友的朋友等),检查他们是否是僵尸。当您发现它们是否存在时,请打印以控制结果。继续前进。
请查看我上面发布的关于迭代树的链接,并将其应用于每个人的朋友的arraylist。递归迭代有不同的方法...所以选择一种样式(看起来你需要按顺序遍历)并以这种方式实现检查/打印功能。
这是一个主角,让我知道你是否再次陷入困境。理解树木所涉及的抽象可能很棘手。
答案 1 :(得分:1)
1)也许不是你想要的,但我会摆脱Person.state
。有两个单独的字段,用于确定一个人是否是一个僵尸是混乱和容易出错。 zombie
为true
且state
为p
时,这意味着什么?
2)Miorel的评论有一些很好的见解。从你给我们的是什么树应该代表什么,为什么它必须是一棵树,或者它如何被填充,这不是很清楚。
3)你需要某种World对象。 Zombies
可能是个不错的选择。在某个地方,显然,你需要一棵所有人的树。至少,你需要一些人的集合。该集合需要声明,实例化和填充。您可能希望它成为Zombies
类的成员。绝对不是Person
类的成员,你将拥有很多。
答案 2 :(得分:0)
Q1)我和我的班级人员走在正确的轨道上了吗?
从我的观点来看,我必须说不。
它出了什么问题?
你有冗余的逻辑。字段zombie
和state
指的是人类潜能的相同状态。
此时我们必须决定什么是僵尸,什么是人。行为,行为方式相同吗?根据我的观察,他们有一些共同的特征,但也有非常独特的表达元素。为了证明这一点,让我们想象一下我们站在人类面前,向他询问时间。他很可能会给我们一些逻辑答案。在完成问题之前,来自另一只手的僵尸肯定会尝试吃掉我们的大脑。
这就是为什么我会使用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)
是的,我认为你走在了正确的轨道上。但是,正如其他人指出的那样,同时拥有char state
和boolean zombie
是多余的。就个人而言,在这种情况下,我认为继承是一种重大的矫枉过正 - 也许是可以理解的,在这种情况下,你可能以后想要拥有可能是“僵尸”或“吸血鬼”甚至是“狼人”的“人”。 “但是,我认为在这种情况下能够简单地说if (p.isZombie()) { ... }
就足够了,但我会留下它,因为这是一个古老的设计论证 - 我属于”组合结束-inheritance“camp(http://en.wikipedia.org/wiki/Composition_over_inheritance)
这确实是一个树结构,但是,我高度怀疑它是一个二叉树 - 基于规范,但是没有理由它不能< / em>是。对我来说,这似乎是一个N-Ary树。其中,如果您之前没有触及这些树,它们只是一个通用的树结构,其中每个节点可以有任意数量的子节点。此链接提供了更好的解释:http://www.brpreiss.com/books/opus5/html/page257.html(稍后会详细介绍)
你没有遗漏任何实现这些方法的东西(我可以说,这取决于你的教授 - 他们如何标记这个?运行他们自己的测试代码?看看你的代码?或者您是否提供演示其工作原理的客户端代码(主要方法)?如果他们正在运行测试代码,您必须确保您的Person API与其规范兼容。)
这里要理解的重要一点是,您创建的数据结构和 它代表一个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树的根 - 无论它实际上是整个树的根还是只是树的一些子树的根。
希望这有帮助!我知道你刚才发布了这个问题,所以我希望你能成功地完成这个问题,或者我不会太迟。如果没有,也许它会帮助别人:/
此外,在解决这些问题(算法和数据结构)时要记住的重要事项是尽量不要被无关的细节所困扰,例如(在这种情况下),它们是否是不重要的“有些朋友可能是僵尸的人”,等等。这不是我们正在寻找的抽象!我们只想在树中代表这种关系!当然,这对于现实世界的问题将变得更加困难,因为我们并不总是被赋予最佳的数据结构,并且我们通常需要利用不同类型的数据结构来创建一些任务。
始终尝试隔离问题的根源,然后从那里开始。通常你会发现很多问题只是添加细节/数据的另一个简单问题;或者甚至只是另一个问题的轻微变化。
祝你好运。