破递归

来源:互联网 发布:凤凰登陆器源码 编辑:程序博客网 时间: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);
            }
        }

 

哎,写码时,考虑太多,导致整个代码的臃肿

原创粉丝点击