破遞歸

最近經常加班,腦子超級不好使,今天被一個很簡單的遞歸搞到了,爲了避免以後重複發生此類事件,將這件醜事記錄下來,提醒自己以後要注意頭腦清醒!!!

 

 


這個問題是這樣的,存在樹形結構的列表如下

 


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);
            }
        }

 

哎,寫碼時,考慮太多,導致整個代碼的臃腫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章