破递归
来源:互联网 发布:凤凰登陆器源码 编辑:程序博客网 时间:2024/04/30 05:18
最近经常加班,脑子超级不好使,今天被一个很简单的递归搞到了,为了避免以后重复发生此类事件,将这件丑事记录下来,提醒自己以后要注意头脑清醒!!!
这个问题是这样的,存在树形结构的列表如下
ID
Name
ParentID
BackUp
1
根1
Null
Null
2
根1 子节点1
1
3
根1子节点2
1
4
根1 子节点2 子节点1
3
5
根1子节点2 子节点2
3
6
根2子节点1
7
7
根2
Null
8
根2子节点2
7
9
根2子节点2子节点1
8
10
根2子节点2子节点1子节点1
9
11
根2子节点2子节点1子节点1子节点1
10
12
根2子节点2子节点1子节点1子节点2
10
典型的树形结构
将这些数据读入DataTable dt里,dt的view和该表结构一样。由于树的节点level比较深,用递归来的最省事
开始的代码如下:
public void InitTreeView()
{
for (int i = 0; i < dt.Rows.Count; i++ )
{
if (dt.Rows[i][2].ToString() == "")
{
treeView1.Nodes.Add(dt.Rows[i][1].ToString());
treeView1.Nodes[treeView1.Nodes.Count - 1].Tag = dt.Rows[i][0].ToString();
FillTreeView(treeView1.Nodes, dt.Rows[i][0].ToString());
}
}
}
public void FillTreeView(TreeNodeCollection tnc, string dtid)
{
DataTable dtcopy = dt.Copy();
dtcopy.DefaultView.RowFilter = "ParentID='" + dtid + "'";
DataTable dtf = dtcopy.DefaultView.ToTable();
foreach (TreeNode tn in tnc)
{
for (int i = 0; i < dtf.Rows.Count; i++)
{
if (tn.Tag.ToString() == dtid)
{
tn.Nodes.Add(dtf.Rows[i][1].ToString());
tn.Nodes[tn.Nodes.Count - 1].Tag = dtf.Rows[i][0].ToString();
}
else
{
FillTreeView(tn.Nodes, tn.Tag.ToString());
}
}
}
}
在InitTreeView里,将没有父ID的值添加为顶级节点,添加一个节点,指定Tag为添加值的ID。
我之前写的时候比较犹豫,一直想添加完一个节点,立刻调用FillTreeView为其添加子节点,还是添加完本级节点再调用。
但是调用该方法时一直报错,在使用treeView1.Nodes[dt.Rows[i]["DICTEXT"].ToString()].Nodes
添加时,提示未将对象设置引用到对象的实例。原因应该是treeview的nodes没有添加完,无法对treeview进行检索。
但使用FillTreeView(treeView1.Nodes[treeView1.Nodes.Count-1].Nodes)添加,不会报错,
没有办法只好将添加子节点的方法放在了循环外面,这样就变成了添加0级节点,添加1级节点,添加2级节点....添加N级节点,
显而易见的,这种做法使算法复杂度大大的提高了。
再来看下FillTreeView方法,
FillTreeView方法的参数为TreeViewNodeCollection 和父节点ID,由于已经将node的Tag存为ID了,这里的dtid就没有
必要添加了,
而且有一个重要问题,想着用递归,并没有弄清递归的调用条件,就是没搞清什么时候调用自己,是应该在添加完本个节点后
就调用呢还是添加完本级节点再调用,最终结果是层层添加后倒腾出来了
public void InitTreeView()
{
for (int i = 0; i < dt.Rows.Count; i++)
{
if (dt.Rows[i][2].ToString() == "")
{
treeView1.Nodes.Add(dt.Rows[i][1].ToString());
treeView1.Nodes[treeView1.Nodes.Count - 1].Tag = dt.Rows[i][0].ToString();
}
} FillTreeView(treeView1.Nodes);
}
public void FillTreeView(TreeNodeCollection tnc)
{
foreach (TreeNode tn in tnc)
{
DataTable dtcopy = dt.Copy();
dtcopy.DefaultView.RowFilter = "ParentID='" + tn.Tag + "'";
DataTable dtf = dtcopy.DefaultView.ToTable();
for (int i = 0; i < dtf.Rows.Count; i++)
{
tn.Nodes.Add(dtf.Rows[i][1].ToString());
tn.Nodes[tn.Nodes.Count - 1].Tag = dtf.Rows[i][0].ToString();
}
FillTreeView(tn.Nodes);
}
}
哎,写码时,考虑太多,导致整个代码的臃肿