首先我想知道这是否是一个明确定义的操作:我们首先访问树的所有叶子(从左到右)。然后我们访问叶子的所有父母(从左到右)。然后是那些父母的所有父母等......直到访问最后一个未访问的节点。请注意,根不一定是最后访问的节点。如果某个父母已经被访问过,我们就会忽略它。我想不出这个遍历会失败的反例。
所以假设它定义明确。进行此遍历的最有效算法是什么?为了简化伪代码,我们可以假设它是二叉树。首先获得所有叶子已经非常耗时。但与此同时,我们可以通过在获得叶子时将父母存储在某个地方来提取每个连续的父母。然后我们访问这些父母列表,每个列表在树中比上一个列表高一代。那样的东西?不幸的是我只知道c ++,但可以找出其他语言的伪代码。
获取二叉树的所有叶子(已测试):
template <typename T, typename Comparator>
inline void BinaryTree<T, Comparator>::obtainLeaves (const std::shared_ptr<Node>& node,
std::list<std::shared_ptr<Node>>& leaves) const {
if (!node)
return;
if (node->isLeaf())
return leaves.emplace_back(node);
obtainLeaves(node->left, leaves);
obtainLeaves(node->right, leaves);
}
虽然叶子的父母可以很容易地存储起来,父母的名单也会被传递,但所有后续的父母呢?
template <typename T, typename Comparator>
inline void BinaryTree<T, Comparator>::obtainLeaves (const std::shared_ptr<Node>& node,
std::list<std::shared_ptr<Node>>& leaves, std::set<std::shared_ptr<Node>>& parents) const {
if (!node)
return;
if (node->isLeaf()) {
leaves.emplace_back(node);
parents.emplace(node->parent);
return;
}
obtainLeaves(node->left, leaves, parents);
obtainLeaves(node->right, leaves, parents);
}
或者不是一次性完成所有操作,首先得到树叶。然后通过调用->parent
迭代叶子列表以获得他们的父母。然后与那些父母重复这个过程,依此类推。但这对我来说似乎非常笨拙和耗时,而且也不能很好地检查重复。
答案 0 :(得分:0)
简单明了的解决方案:
构建一个颠倒的树。当你遍历时,保持一组向根的反向链接。
创建叶子的矢量。在执行此操作时,将其指针值记录在哈希映射中。现在走吧。
现在,对于该向量中的每个元素,将其替换为其父元素。并将其添加到哈希映射中。如果它已经在哈希映射中,则省略它。
重复直到父母用完为止。
这可能不是最佳的。
答案 1 :(得分:0)
以下我测试了正常工作。我不知道它的时间复杂性如何与Yakk的解决方案相比,甚至它的时间复杂性是什么。我知道每个非叶子节点至少要访问两次,这不是一件好事。
$(function() {
$('*[class^="js-toggle-"]').hide();
var myListRef = {'email':'email','tel':'tel','writing':'writing'}
$('[name="contact"]').click(function() {
var $this = $(this);
$('.js-toggle-' + myListRef[$this.val()]).show();
$.each( myListRef , function( key, value ) {
if(value !== $this.val()) {
$('.js-toggle-' + value).hide();
}
});
});
$('#problem').change(function(){
if($('#problem').val() == 'parcel') {
$('.js-toggle-problem').show();
} else {
$('.js-toggle-problem').hide();
}
});
});