首先我想知道這是否是一個定義明確的操作:我們首先訪問樹的所有樹葉(從左到右)。然後我們訪問所有葉子的父母(從左到右)。然後,所有父母的父母等......直到最後一個未訪問節點被訪問。請注意,根不一定是最後訪問的節點。如果某位父母已經被訪問過,我們簡單地忽略它。我想不出一個反向例子,這個遍歷將會失敗。以升序生成樹遍歷樹
因此,假設它是明確的。什麼是最有效的算法來做這個遍歷?爲了簡化僞代碼,我們可以假設它是一棵二叉樹。首先獲得所有的葉子已經非常耗時。但與此同時,我們可以通過在獲得葉子時將父母存儲在某個地方,從而隨每個父母一起提取。然後我們訪問這些父母名單,每個名單在樹中比先前的名單高出一代。像那樣的東西?不幸的是,我只知道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);
}
雖然葉的父母可以很容易地從這個繞過去了父母該名單,那所有的父母相繼存儲?或者,不要一次性完成所有事情,首先得到樹葉。然後通過調用->parent
來重複葉子列表以獲得父母。然後和父母一起重複這個過程,等等。但是,這對我來說似乎非常笨拙和耗時,並且也沒有真正檢查重複。
如何在構建樹的同時在樹中和節點中存儲額外的字段以促進此操作?我們是否在假設我們得到了一棵樹並且必須遍歷它並且不能指望有任何特殊領域? –
@ThomasG樹的結構本身可以修改。我認爲「父」成員是我們可以添加到每個節點的唯一新的有用成員。其他成員會爲此提供便利嗎? – prestokeys
我們可以在構建階段向樹添加'LeftMostNode'。我們還可以添加例如兄弟指針。然後,不是從根開始遍歷,我們可以從最左邊的節點開始,並遵循同級指針。這樣,我們可以在第一遍中增加比率(訪問過的葉子節點的數量/父母訪問過的數量)。基本上是空間與速度的權衡。出於某種原因,SO不會允許我在本評論開始處添加@prestokeys! –