【问题标题】:JavaScript Recursive Tree Searching Function Not Detecting Nested ChildrenJavaScript递归树搜索函数未检测到嵌套子项
【发布时间】:2017-10-13 18:09:08
【问题描述】:

尝试创建一个递归函数,正确搜索 Tree 类及其所有后代的值,如果找到该值则返回 true,否则返回 false。

特别重要的是递归 contains() 函数。试图让代码通过 linter。我只收到一个关于不检测嵌套子级的错误。其他一切都在过去。

我的代码:

/* eslint-disable no-trailing-spaces */
/* eslint-disable no-unused-vars */
class Tree {
  constructor(value) {
    this.value = value;
    this.children = [];
  }
  // Adds a new Tree node with the input value to the current Tree node 
  addChild(value) {
    this.children.push(new Tree(value));
  }
  // Checks this node's children to see if any of them matches the given value
  // Continues recursively until the value has been found or all of the children
  // have been checked
  contains(value) {
    const thisNode = this;
    function checkNode(node) {
      if (node.value === value) {
        return true;
      }
      if (node.children.length > 0) {
        for (let i = 0; i < node.children.length; i++) {
          return checkNode(node.children[i]);
        }
      }
      return false;
    }
    return checkNode(thisNode);
  }
}

module.exports = Tree;

这是测试它的文件:

/* eslint-disable no-undef */
const Tree = require('../src/tree');

describe('Tree', () => {
  let tree;

  beforeEach(() => {
    tree = new Tree(true);
  });

  it('should have methods named "addChild" and "contains"', () => {
    expect(typeof tree.addChild).toBe('function');
    expect(typeof tree.contains).toBe('function');
  });

  it('should add children to the tree', () => {
    tree.addChild(5);
    expect(tree.children[0].value).toBe(5);
  });

  it('should return true for a value that the tree contains', () => {
    tree.addChild(5);
    expect(tree.contains(5)).toBe(true);
  });

  it('should return false for a value that was not added', () => {
    tree.addChild(5);
    expect(tree.contains(6)).toBe(false);
  });

  it('should be able to add children to a tree\'s child', () => {
    tree.addChild(5);
    tree.children[0].addChild(6);
    expect(tree.children[0].children[0].value).toBe(6);
  });

  it('should correctly detect nested children', () => {
    tree.addChild(5);
    tree.addChild(6);
    tree.children[0].addChild(7);
    tree.children[1].addChild(8);
    expect(tree.contains(7)).toBe(true);
    expect(tree.contains(8)).toBe(true);
  });
});

这是 linting 错误:

Tree
    ✓ should have methods named "addChild" and "contains" (5ms)
    ✓ should add children to the tree (1ms)
    ✓ should return true for a value that the tree contains (3ms)
    ✓ should return false for a value that was not added (1ms)
    ✓ should be able to add children to a tree's child (1ms)
    ✕ should correctly detect nested children (9ms)

【问题讨论】:

  • 您是来自for 循环体的直接returning。这意味着只执行循环的第一次迭代。你究竟想做什么?你真的要返回检查第一个孩子的结果吗?在编写代码之前尝试描述您想要做什么。
  • 有答案你的代码有什么问题。这是一种缩短/改进它的方法:const checkNode = node =&gt; node.value === value || node.children.some(checkNode); 然后return checkNode(this);
  • @FelixKling 我刚刚将我的描述编辑为“尝试创建一个递归函数,该函数可以正确搜索 Tree 类及其所有后代的值,如果找到该值则返回 true,否则返回 false。”这对你来说足够描述吗?如果对新手更温和一点,Stack Overflow 对所有人来说都会更有利可图。结束。
  • 对不起,我认为我的评论并不清楚它的意图是什么。我不是要批评你的问题,我是想帮助你思考这个问题。我的意思是你应该用语言(对你自己或这里或其他什么)描述你想和孩子们发生的事情。例如,我会将其描述为“对于每个孩子,调用 checkNode。如果结果为真,则返回真,否则继续”。只是描述这个想法,你可能会自己发现问题。
  • @FelixKling 我最终同意你的看法。我是一个菜鸟,用纸和铅笔在电脑上玩这个问题已经超过 18 个小时了。让我感到安慰的是,我知道我至少在朝着正确的方向思考。

标签: javascript recursion tree lint


【解决方案1】:

你的问题出在这段代码里:

  if (node.children.length > 0) {
    for (let i = 0; i < node.children.length; i++) {
      return checkNode(node.children[i]);
    }
  }

无论第一个孩子的 checkNode 的结果是 true 还是 false,这行代码都会从函数返回。如果结果为假,则需要继续检查。

试试这个:

  if (node.children.length > 0) {
    for (let i = 0; i < node.children.length; i++) {
      if (checkNode(node.children[i])) {
        return true;
      }
    }
  }

【讨论】:

    【解决方案2】:

    你在for循环内无条件返回,所以你只检查第一个孩子。

        for (let i = 0; i < node.children.length; i++) {
          return checkNode(node.children[i]);
        }
    

    应该是

        for (let i = 0; i < node.children.length; i++) {
          if (checkNode(node.children[i])) return true;
        }
    

    【讨论】:

    • 你比我快 37 秒 :|
    • 西部最快的枪:P
    • @Blorgbeard 成功了。愿源永远与你同在,我的朋友。
    【解决方案3】:

    我想,你的代码应该是这样的:

    for (let childIndex = 0; childIndex < node.children.length; childIndex++) {
       const foundInChildren = checkNode(node.children[childIndex]);
       if (foundInChildren)
         return true;
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      相关资源
      最近更新 更多