问题
I have a tree selection in which every node has a name. I want to search through the node names and return a subset of the tree which only contains the found nodes and its parents.
Does anybody know an efficient algorithm in JavaScript for this problem which return the node with all of its parents.
Here is an example. when user type a search term, example "Elephant" and the tree looks like this:
- Elephant
- Hamster
- Fish
- Duck
- Hamster
- Hamster
- dog
- Fish
- Elephant
- Fish
- dog
- Dog
- Fish
- Unicorn
- Elephant
- Elephant
- Hamster
- Unicorn
- Unicorn
- Fish
- Elephant
- Hamster
- Fish
- Elephant
- Elephant
- Elephant
- Hamster
Would like to output the search result in tree format with children like this:
- Elephant
- Hamster
- Elephant
- Dog
- Fish
- Unicorn
- Elephant
- Elephant
- Unicorn
- Fish
- Elephant
- Hamster
- Elephant
- Elephant
- Elephant
- Hamster
Given:
this.tree =[
{childs: Array(2), id: 2, name: "Elephant", …}
{childs: Array(2), id: 3, name: "Hamster", ...}
{childs: Array(2), id: 3, name: "Dog", ...}
{childs: Array(2), id: 3, name: "Elephant", ...}
]
Given
// animal target name
target = 'Elephant',
// tree data structure
tree = [
{ name: 'Elephant', childs: [
{ name: 'Duck' },
{ name: 'Hamster', childs: [
{ name: 'Fish' }
]}
]},
{ name: 'Hamster', childs: [
{ name: 'Elephant', childs: [
{ name: 'Fish' }
]},
{ name: 'Dog', childs: [
{ name: 'Fish' }
]}
]},
{ name: 'Dog', childs: [
{ name: 'Unicorn' },
{ name: 'Fish', childs: [
{ name: 'Hamster' },
{ name: 'Unicorn', childs: [
{ name: 'Elephant' }
]},
]}
]},
{ name: 'Elephant', childs: [
{ name: 'Duck' },
{ name: 'Hamster', childs: [
{ name: 'Elephant' },
{ name: 'Fish' },
]}
]}
],
Attempt to modify the tree from Nave's solution (output result in original tree object format, set property to display = false to hide the node, keep on searching the other node in the same level even if found matching node). This seems like a DFS, however am still taking lots of time to figure the backtracking. Final result is to return the tree which contains only the matching result and its parent/ancestor.
searchHelper(term, children, showParent) {
let found;
if (showParent == null || showParent == undefined) {
showParent = false;
}
children.forEach(child => {
if (found = this.search(term, child)){
console.log('found--------------------------------');
child.display = true;
} else {
console.log('not foond-----------------------------------------')
child.display = false;
}
showParent = showParent || found;
})
return showParent;
}
search(term, parent) {
let ans, showParent, found, { name, children } = parent;
if (children.length) {
showParent = this.searchHelper(term, children, showParent);
}
return name.toLowerCase().indexOf(term.toLowerCase()) != -1;
}
this.search("Elephant", this.tree);
回答1:
I guess that's what you're looking for:
search = node => {
let found, { name, childs = [] } = node;
if (childs.length)
for (let child of node.childs)
if (found = search(child))
return [name].concat(found);
return name === target && [name];
}
And here is my full solution:
const
// Your animal target name
target = 'Elephant',
// Your tree data structure
tree = [
{ name: 'Elephant', childs: [
{ name: 'Duck' },
{ name: 'Hamster', childs: [
{ name: 'Fish' }
]}
]},
{ name: 'Hamster', childs: [
{ name: 'Elephant', childs: [
{ name: 'Fish' }
]},
{ name: 'Dog', childs: [
{ name: 'Fish' }
]}
]},
{ name: 'Dog', childs: [
{ name: 'Unicorn' },
{ name: 'Fish', childs: [
{ name: 'Hamster' },
{ name: 'Unicorn', childs: [
{ name: 'Elephant' }
]},
]}
]},
{ name: 'Elephant', childs: [
{ name: 'Duck' },
{ name: 'Hamster', childs: [
{ name: 'Elephant' },
{ name: 'Fish' },
]}
]}
],
// The recursive tree search function. Her exit point is
// a child who matches the target. He returns the path to
// target - if found - as an array. Otherwise, false
search = node => {
let found, { name, childs = [] } = node;
if (childs.length)
for (let child of node.childs)
if (found = search(child))
return [name].concat(found);
return name === target && [name];
},
// The result, as a set of arrays. We filter out the
// branches that do not contain the result
result = tree.map(search).filter(Boolean);
// The result as a formatted string for easy viewing
formattedResult = result.map((path, index) => `${index + 1}: ${path.join(' > ')}`).join('\n');
console.log(formattedResult);
来源:https://stackoverflow.com/questions/60102867/javascript-tree-search-algorithm-which-return-subset-of-the-tree-which-contains