程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#中一種通用的樹的生成方式

C#中一種通用的樹的生成方式

編輯:C#入門知識

 

在寫程序時,經常要用到樹的這種結構,如果是做界面編程,那麼TreeView是一個不錯的選擇,幾個設置就能把數據綁定好,但是如果自己寫類呢?相對就麻煩一點。

 

這裡討論一下如何快速建立自己的樹型結構,即怎麼把建樹的方法抽離出來加以復用。

 

代碼的復用,不外乎類,接口,泛型。

 

先考慮用接口來實現,定義一個ITreeNode 然後每一個要建立樹型結構的結點去實現?感覺不大好,因為你要定義比如Parent Children等一系列的東西,很是很麻煩,每一個實現起來也很困難。

 

那抽像類?抽象類的繼承到是方便,但是在實際使用中涉及各種類型轉換,代碼寫起來不爽。

 

泛型呢?泛型的結構又過於籠統 ,但是可以折衷一下,就是用泛型定義一個結點的類

 

(小弟寫代碼方式都相對“妥協”,一位大人說的,各位將就著看哈)

 

 

 

 1 namespace Soway.DB.Tree

 2 {

 3     public class  TreeNode<T>

 4     {

 5

 6         public T Data { get; set; }

 7         public TreeNode<T> Parent { get; set; }

 8         public List<TreeNode<T>> Children { get; set; }

 9     }

10 }

 

 

 

結點類定義好了以後,就要去實現一個TreeFactory ,將建樹的通用算法提出來。

 

 

 

namespace Soway.DB.Tree

{

 

   

   

    public class TreeFactory <T>

    {

public List<TreeNode<T>> CreateTreeByLevel

            (List<T> Items )

        {

            //////

        }

    }

}

 

這裡的我的方法名已經默認為ByLevel ,即按層建立樹,這樣,新的問題又出現了:

 

1.怎麼保證輸入值Items是已經按層遍立建立好的結點?

 

2.怎麼分層?即怎麼區分樹的父結點,子結點,同級結點之間的關系 ?

 

這些問題其實都與泛型的具體類型有關,但如果把具體類型約束了,那就違反我們本意了。

 

走一步算一步,先這樣,把樹結點之間的關系定義出來,算是一個枚舉吧:

 

 

 

namespace Soway.DB.Tree

{

    public enum  TeeNodeCompareResult

    {

        /// <summary>

        /// 樹結點

        /// </summary>

        Parent,

        /// <summary>

        /// 子結點

        /// </summary>

        Child,

        /// <summary>

        /// 下一個同級結點

        /// </summary>

        NextNode,

        /// <summary>

        /// 前一個同級結點

        /// </summary>

        PreNode,

        /// <summary>

        /// 同一個結點

        /// </summary>

        EquealNode ,

        /// <summary>

        /// 下一層的結點

        /// </summary>

        NexLevelNode

 

    }

}

 

 

 

有了這個關系以後,於是有了進一步的想法,考慮傳遞給TreeFactory一個委托,可以通過這個來得到兩個結點之間比較關系:

 

 

 

namespace Soway.DB.Tree

{

    public delegate TeeNodeCompareResult TeeNodeCompare<T>(T child, T parent);

}

 

這樣,我們的TreeFactory裡多了一個泛型委托的成員。。。

 

 

 

   private TeeNodeCompare<T> compare;

 

        public TreeFactory(Tree.TeeNodeCompare<T> Compare)

        {

            this.compare = Compare;

 

        }

 

 

 

現在,當這個泛型委托處理好了以後,我們下一步問題也好辦了,就是將輸入的Items進行按層排序,這時,只要有一個Comparison<T>()的實現 ,我直接調用List<T>.Sort(Comprarion<T>)即可了

 

下面給出這個Comparation<T>的實現 :

 

 

 

 private int CompareResult(T ob1, T ob2)

        {

            switch (compare(ob1, ob2))

            {

                case TeeNodeCompareResult.Child:

                case TeeNodeCompareResult.NextNode:

                case TeeNodeCompareResult.NexLevelNode:

                    return 1;

                case TeeNodeCompareResult.Parent :

                case TeeNodeCompareResult.PreNode:

                    return -1;

                default :

                    return 0;

            }

         

                

        }

 

好,這些基礎工作做完以後,建樹的就容易了:

 

 

 

      /// <summary>

        /// 按層建立樹

        /// </summary>

        /// <param name="Items">建立樹的集合</param>

        /// <returns>建立好的樹結構</returns>

        public List<TreeNode<T>> CreateTreeByLevel

            (List<T> Items )

        {

            Items.Sort(new Comparison<T>(this.CompareResult));

            List<TreeNode<T>> result = new List<TreeNode<T>>();

            TreeNode<T> lastNode =null;

            Queue<TreeNode<T>> queue = new Queue<TreeNode<T>>();

            TreeNode<T> currentNode=null;

            var current = result;

            if (Items.Count > 0)

            {

 

 

 

                  for (int i = 0; i < Items.Count ; i++)

                {

 

 

                   

                    TreeNode<T> AddedNode = new  TreeNode<T>(){Data=Items[i],

                        Parent = null,Children = new List<TreeNode<T>>()};//生成要添加的數據

 

                    queue.Enqueue(AddedNode);//入隊

                      //看是否到了下一層的結點

                    if (lastNode != null &&

                        (compare(AddedNode.Data, lastNode.Data) == Tree.TeeNodeCompareResult.Child

                         || compare(AddedNode.Data, lastNode.Data) == Tree.TeeNodeCompareResult.NexLevelNode)//下一層:即結點是子結點或是下一層結點

                        )

                    {

                        currentNode = queue.Dequeue();

                      

                    }

                    //找到對應的父結點

                    while (currentNode != null

                        &&

                        compare(AddedNode.Data, currentNode.Data) != TeeNodeCompareResult.Child

                        )

                    {

                        currentNode = queue.Dequeue();

                    }

                    if (currentNode !=null && compare(AddedNode.Data, currentNode.Data) != TeeNodeCompareResult.EquealNode)

                    {

                        AddedNode.Parent = currentNode;

                        current = currentNode.Children;

                    }

                    current.Add(AddedNode);

                    lastNode = AddedNode;

                }

            }

            return result;

      

 

        }

 

 

 

下面是一個使用的Demo ^_^

 

 

 

//類:

{

    [Table(Name="Auth")]   

    public class Auth

    {

        [Column(IsKey=true)]

        public string Code { get; set; }

        public string Name { get; set; }

        public String Url { get; set; }

        public string View { get; set; }

        public string Action { get; set; }

        public string Text { get; set; }

        public string Image { get; set; }

 

 

        public override string ToString()

        {

            return Code + " " + Name;

        }

 

        

 

    }

//比較結點的關系:

 static Soway.DB.Tree.TeeNodeCompareResult compare(Auth ob1, Auth ob2)

        {

 

            if (ob1.Code == ob2.Code)

                return TeeNodeCompareResult.EquealNode;

            if (ob1.Code.Length > ob2.Code.Length)

                if (ob1.Code.IndexOf(ob2.Code) == 0)

                    return TeeNodeCompareResult.Child;

                else

                    return TeeNodeCompareResult.NexLevelNode;

            else if (ob1.Code.Length < ob2.Code.Length)

                return TeeNodeCompareResult.Parent;

            else if (ob1.Code.CompareTo(ob2.Code) < 0)

                return TeeNodeCompareResult.PreNode;

            else

                return TeeNodeCompareResult.NextNode;

               

 

        }

 

 

///主函數中 www.2cto.com

 var c = new Soway.DB.DBContext(builder.ToString());

            var items = c.Get<Auth  >();//初始化

    var tree = new TreeFactory<Auth>(new TeeNodeCompare<Auth>(compare)).CreateTreeByLevel(items);//建立樹型結構

 

摘自 葛雲飛

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved