妳的“回調”是想說“回溯”麽?回溯(Backtrace,叠代)和回調(Callback,委托反向調用)是兩回事。
這個問題的思路大體上有以下兩種。
常規展開:單就壹個字符串“A|B|C”來說,進行拆分後從樹的根節點壹層壹層加子節點上去即可。唯壹需要註意的事情是在加子節點前要判斷當前搜索層級上有沒有同名節點(可能由其他字符串先行提供)。
回溯展開:回溯指自身調用自身,通常是在Method層面上執行。本題中涉及叠代的部分依舊是單個字符串的解析,回溯可以形如以下偽代碼。同樣的要註意重復節點的問題。
下面第壹段代碼是回溯偽代碼,第二段部分是使用常規展開方法的歷程。
private?void?Build(TreeNode?currentRoot,String?patternString){
if(字符串中已無|分隔符)?
為currentRoot增加最後的壹個子節點,其文本為patternString
else
foreach(每壹個patternString中的節點文本str)
{
為currentRoot添加值為str的子節點;
currentRoot=上面新增的節點;
newPatternString=patternString截取未處理的部分(右側);
Build(currentRoot,newPatternString);
}
}
//--------------------------------------------------------------
public?class?MyTreeView?:?TreeView
{
public?void?AddStringSource(IEnumerable<string>?sources)
{
foreach?(var?v?in?sources)
AddStringSource(v);
}
public?void?AddStringSource(string?source)
{
//基本思路是從左向右逐步拆解字符串,在每壹個步驟上都搜尋樹中對應的節點,
//如果不存在此節點則新建。此舉可以保證路徑的正確性的同時規避同文本節點的問題。
TreeNode?currentNode?=?null;
while?(source.Contains('|'))
{
string?firstSeg?=?source.Split('|')[0];
TreeNode?subNode?=?new?TreeNode(firstSeg);
if?(currentNode?==?null)
{
//在樹的根節點集合中尋找指定節點,若不存在則新建
TreeNode?searchResult?=?TextSearch(firstSeg,?currentNode);
if?(searchResult?==?null)
{
this.Nodes.Add(subNode);
currentNode?=?subNode;
}
else
currentNode?=?searchResult;
}
else
{
//在當前節點(非空)下尋找指定的節點,若不存在則新建
TreeNode?searchResult?=?TextSearch(firstSeg,?currentNode);
if?(searchResult?==?null)
{
currentNode.Nodes.Add(subNode);
currentNode?=?subNode;
}
else
currentNode?=?searchResult;
}
source?=?source.Substring(source.IndexOf('|')+1);
}
currentNode.Nodes.Add(source);
}
private?TreeNode?TextSearch(string?text,?TreeNode?node)
{
if?(node?==?null)
{
foreach?(TreeNode?tn?in?this.Nodes)
if?(tn.Text?==?text)
return?tn;
}
else
foreach?(TreeNode?tn?in?node.Nodes)
if?(tn.Text?==?text)
return?tn;
return?null;
}
}
//調用部分MyTreeView?mtv?=?new?MyTreeView();
mtv.AddStringSource(new?string[]?{?"A|B|C",?"A|B|D",?"A|E","F|G|H","F|G|I","F|G|H|J"});
this.Controls.Add(mtv);
mtv.Dock?=?DockStyle.Fill;
mtv.ExpandAll();