Java 递归-如果节点的字符串为“0”,则删除节点;“莱昂纳多”;
我有一个节点树Java 递归-如果节点的字符串为“0”,则删除节点;“莱昂纳多”;,java,algorithm,recursion,graph-algorithm,breadth-first-search,Java,Algorithm,Recursion,Graph Algorithm,Breadth First Search,我有一个节点树 class Node { String mName; List<Node> children = new ArrayList<>(); Node(String name) { mName = name; } } 结果应该是: Jessy / | \ Rafael David J
class Node {
String mName;
List<Node> children = new ArrayList<>();
Node(String name) {
mName = name;
}
}
结果应该是:
Jessy
/ | \
Rafael David John Denis Phillipe
|
Keren
(关于莱昂纳多、丹尼斯、菲利普和莱昂纳多的子树结果的解释:杰西的第三个儿子是莱昂纳多,因此莱昂纳多被移除,他的儿子(丹尼斯和莱昂纳多)成为杰西的儿子。但是,另一个莱昂纳多被移除,菲利普代替他而来。)
孩子们的顺序无关紧要(也就是说,拉斐尔和大卫可以跟在菲利普后面)
假设“Leonardo”在根中时无法获得初始树
我已经试过了,但不幸的是它不起作用
for (int i = 0; i < root.children.size(); ++i) {
removeLeonardo(root, root.children.get(i));
}
public void removeLeonardo(Node curr, Node child) {
if (child == null || child.children.isEmpty() == true) {
return;
}
if (child.mName.equals("Leonardo") == true) {
// add all Leonardo's children to current father
for (int i = 0; i < child.children.size(); ++i) {
curr.children.add(child.children.get(i));
// apply the func for the current father with each of Leonardo's children
removeLeonardo(curr, child.children.get(i));
}
// remove "Leonardo" from the current father
curr.children.remove(child);
}
else { // no "Leonardo" found, so apply the func for each child and this child's children
for (int i = 0; i < child.children.size(); ++i) {
removeLeonardo(child, child.children.get(i));
}
}
}
for(int i=0;i
但是Java不能通过引用工作。你能帮我解决这个问题吗?我相信这应该行得通 如果您担心效率,那么从ArrayList内部删除并插入ArrayList并不是最好的选择。LinkedList会更好,但这样你就不想通过子对象的索引来访问它们了。您可能会改用ListIterator,并使用add和remove方法
public static void main(String[] args)
{
Node root = new Node("Jessy");
root.children.addAll(Arrays.asList(new Node[]{new Node("Leonardo"), new Node("John"), new Node("Leonardo")}));
root.children.get(0).children.addAll(Arrays.asList(new Node[]{new Node("Rafael"), new Node("David")}));
root.children.get(1).children.addAll(Arrays.asList(new Node[]{new Node("Leonardo"), new Node("Keren")}));
root.children.get(2).children.addAll(Arrays.asList(new Node[]{new Node("Denis"), new Node("Leonardo")}));
root.children.get(2).children.get(1).children.add(new Node("Phillipe"));
print(root, "");
pruneByName(root, "Leonardo");
print(root, "");
}
static void pruneByName(Node node, String name)
{
assert !node.mName.equals(name);
for(int i=0; i<node.children.size(); )
{
Node child = node.children.get(i);
if(child.mName.equals(name))
{
node.children.remove(i);
node.children.addAll(i, child.children);
}
else
{
pruneByName(child, name);
i += 1;
}
}
}
static void print(Node node, String ind)
{
System.out.println(ind + node.mName);
for(Node child : node.children)
{
print(child, ind + " ");
}
}
我相信这应该行得通 如果您担心效率,那么从ArrayList内部删除并插入ArrayList并不是最好的选择。LinkedList会更好,但这样你就不想通过子对象的索引来访问它们了。您可能会改用ListIterator,并使用add和remove方法
public static void main(String[] args)
{
Node root = new Node("Jessy");
root.children.addAll(Arrays.asList(new Node[]{new Node("Leonardo"), new Node("John"), new Node("Leonardo")}));
root.children.get(0).children.addAll(Arrays.asList(new Node[]{new Node("Rafael"), new Node("David")}));
root.children.get(1).children.addAll(Arrays.asList(new Node[]{new Node("Leonardo"), new Node("Keren")}));
root.children.get(2).children.addAll(Arrays.asList(new Node[]{new Node("Denis"), new Node("Leonardo")}));
root.children.get(2).children.get(1).children.add(new Node("Phillipe"));
print(root, "");
pruneByName(root, "Leonardo");
print(root, "");
}
static void pruneByName(Node node, String name)
{
assert !node.mName.equals(name);
for(int i=0; i<node.children.size(); )
{
Node child = node.children.get(i);
if(child.mName.equals(name))
{
node.children.remove(i);
node.children.addAll(i, child.children);
}
else
{
pruneByName(child, name);
i += 1;
}
}
}
static void print(Node node, String ind)
{
System.out.println(ind + node.mName);
for(Node child : node.children)
{
print(child, ind + " ");
}
}
在初始循环中跳过子John。这是怎么做的 杰西的孩子莱昂纳多、约翰等在数组列表的索引0、1等处。
for
循环从索引0开始,处理第一个莱昂纳多和那个莱昂纳多
被移除。在除掉莱昂纳多的过程中,指数1的约翰,
将移动到索引0。for循环然后移动到索引1,跳过John和
不带走约翰的孩子,莱昂纳多
下面是使用ListIterator
解决问题的代码。用这个
代码您可以使用任何类型的列表,包括LinkedList
,以及ArrayList
public static void removeLeonardo2(Node node) {
if (node == null || node.children.isEmpty()) {
return;
}
for(ListIterator<Node> it = node.children.listIterator(); it.hasNext();) {
Node n;
n = it.next();
if(n.mName.equals("Leonardo")) {
removeLeonardo2(n);
it.remove();
for(Node childNode: n.children) {
it.add(childNode);;
}
}else {
removeLeonardo2(n);
}
}
}
public static void removeLeonardo2(节点){
if(node==null | | node.children.isEmpty()){
回来
}
for(ListIterator it=node.children.ListIterator();it.hasNext();){
节点n;
n=it.next();
如果(n.mName.等于(“莱昂纳多”)){
去除氧自由基(n);
it.remove();
用于(节点子节点:n个子节点){
添加(childNode);;
}
}否则{
去除氧自由基(n);
}
}
}
在初始循环中跳过子John。这是怎么做的
杰西的孩子莱昂纳多、约翰等在数组列表的索引0、1等处。
for
循环从索引0开始,处理第一个莱昂纳多和那个莱昂纳多
被移除。在除掉莱昂纳多的过程中,指数1的约翰,
将移动到索引0。for循环然后移动到索引1,跳过John和
不带走约翰的孩子,莱昂纳多
下面是使用ListIterator
解决问题的代码。用这个
代码您可以使用任何类型的列表,包括LinkedList
,以及ArrayList
public static void removeLeonardo2(Node node) {
if (node == null || node.children.isEmpty()) {
return;
}
for(ListIterator<Node> it = node.children.listIterator(); it.hasNext();) {
Node n;
n = it.next();
if(n.mName.equals("Leonardo")) {
removeLeonardo2(n);
it.remove();
for(Node childNode: n.children) {
it.add(childNode);;
}
}else {
removeLeonardo2(n);
}
}
}
public static void removeLeonardo2(节点){
if(node==null | | node.children.isEmpty()){
回来
}
for(ListIterator it=node.children.ListIterator();it.hasNext();){
节点n;
n=it.next();
如果(n.mName.等于(“莱昂纳多”)){
去除氧自由基(n);
it.remove();
用于(节点子节点:n个子节点){
添加(childNode);;
}
}否则{
去除氧自由基(n);
}
}
}
谢谢@YvetteColomb:)谢谢@YvetteColomb:)