遞歸構建樹,即使是經驗豐富的程序員一個艱鉅的挑戰。考慮到這個問題最初是在2011年3月發佈的,我意識到我對這個問題的晚會有點晚。
創建樹的一個重要因素就是確保數據集格式正確。您只需要一種將父母關聯到孩子的方法。一旦關聯被明確定義,那麼你就可以開始編碼解決方案。我選擇了這樣一個簡單的格式:
ParentId ChildId
1 2
1 3
2 4
3 5
等等。
一旦建立了這種關係,我開發了一種遞歸方法來遍歷數據集來構建樹。
首先我確定所有的父節點,並將它們存儲在一個集合中給他們使用父ID和子ID的組合中的各一個唯一的標識符:
private void IdentifyParentNodes()
{
SortedList<string, MyTreeNode> newParentNodes = new SortedList<string,MyTreeNode>();
Dictionary<string, string> parents = new Dictionary<string, string>();
foreach (MyTreeNode oParent in MyTreeDataSource.Values)
{
if (!parents.ContainsValue(oParent.ParentId))
{
parents.Add(oParent.ParentId + "." + oParent.ChildId, oParent.ParentId);
newParentNodes.Add(oParent.ParentId + "." + oParent.ChildId, oParent);
}
}
this._parentNodes = newParentNodes;
}
然後根調用方法將遍歷家長和調用遞歸方法來構建樹:
// Build the rest of the tree
foreach (MyTreeNode node in ParentNodes.Values)
{
RecursivelyBuildTree(node);
}
遞歸方法:
private void RecursivelyBuildTree(MyTreeNode node)
{
int nodePosition = 0;
_renderedTree.Append(FormatNode(MyTreeNodeType.Parent, node, 0));
_renderedTree.Append(NodeContainer("open", node.ParentId));
foreach (MyTreeNode child in GetChildren(node.ParentId).Values)
{
nodePosition++;
if (IsParent(child.ChildId))
{
RecursivelyBuildTree(child);
}
else
{
_renderedTree.Append(FormatNode(MyTreeNodeType.Leaf, child, nodePosition));
}
}
_renderedTree.Append(NodeContainer("close", node.ParentId));
}
方法來獲得父母的孩子:
private SortedList<string, MyTreeNode> GetChildren(string parentId)
{
SortedList<string, MyTreeNode> childNodes = new SortedList<string, MyTreeNode>();
foreach (MyTreeNode node in this.MyTreeDataSource.Values)
{
if (node.ParentId == parentId)
{
childNodes.Add(node.ParentId + node.ChildId, node);
}
}
return childNodes;
}
不那麼複雜或優雅,但它得到了這份工作完成。這是2007年的時間框架,所以它是舊的代碼,但它仍然有效。 :-) 希望這可以幫助。
你的方案似乎有很多冗餘。特別是,每個節點編碼它形成根的路徑。用這種方案,列出葉節點的編碼就足以完全表示樹。不知道,如果這有幫助,只是一個觀察。 – 2011-03-28 13:33:21
我需要保留該路線,以便我可以有效地確定子表達式以及它們如何作爲整體進行交互。 – user648132 2011-03-28 13:39:49