2017-10-13 72 views
1

試圖製作一個遞歸函數,該函數能夠正確搜索樹類及其所有後代的值,並在找到該值時返回true,否則返回false。JavaScript遞歸樹搜索函數未檢測到嵌套子代

特別重要的是遞歸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); 
    }); 
}); 

這裏是掉毛的錯誤:

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) 
+0

您是直接從''的循環for'身體return'ing。這意味着只執行循環的第一次迭代。你究竟想要做什麼?你真的想要返回檢查第一個孩子的結果嗎?在編寫代碼之前嘗試描述你想要做什麼。 –

+1

有答案你的代碼有什麼問題。這裏有一種方法可以縮短/改善它:'const checkNode = node => node.value === value || node.children.some(checkNode);'然後'返回checkNode(this);' – Thomas

+0

@FelixKling我剛剛編輯我的描述爲'嘗試做一個遞歸函數,正確搜索Tree類及其所有後代的值如果找到該值,則返回true,否則返回false。'這對你來說足夠描述了嗎?如果堆棧溢出對新手來說更加溫和一點,對所有人來說都會更有利可圖。結束。 –

回答

2

您無條件換內返回循環,所以你只能檢查第一個孩子。

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; 
    } 
+1

你比我快37秒:| –

+2

西部最快的槍:P – Blorgbeard

+0

@Blorgbeard這工作。願我的朋友永遠和你在一起。 –

2

我想,這是你的代碼應該是什麼樣子:

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

您的問題是在這大塊的代碼在這裏:

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

這行代碼將從該函數無論checkNode的結果是第一個孩子,true還是false。如果結果爲false,則需要繼續檢查。

試試這個:

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