如何從樹葉層開始建樹?

來源:互聯網
上載者:User

     在開發軟體的過程中,遇到一個樹形結構的問題,如:

      

     由於樹形結構太大,只顯示部分葉節點,並且報價是分葉節點的數量和報價的成積。

 問題經分析很顯然:變成了如下兩個問題:

1從樹的根節點開始建樹就是一個簡單的遞迴,但現在的問題是從樹的分葉節點開始如何建樹,涉及到一個如何合并子節點的問題。

2如何根據分葉節點的數量和報價計算各級父節點的報價?


1如何從樹的分葉節點開始如何建樹?

 有一種思路,就是按照正常思路建好後,然後把沒有子節點的刪掉,很麻煩。

於是想著能不能通過分葉節點的遞迴一層一層向上,最終完成樹的建立。

最總實現代碼如下:

 /// <summary>    /// 返回需要的樹    /// </summary>    /// <param name="listAllNodes">所有的節點資訊</param>    /// <param name="dicNode">鍵為父節點編號,值為父節點對應的子節點  ,初始為需要顯示的分葉節點</param>    /// <returns></returns>    public static List<TreeNode> GeTree(List<TreeNode> listAllNodes, Dictionary<int, List<TreeNode>> dicNode)    {        int rootNodeId = -1;//虛擬根節點編號        while (!dicNode.ContainsKey(rootNodeId)) //如果沒有到根節點繼續        {            dicNode = GetOneLevelNodes(listAllNodes, dicNode);        }        return dicNode[rootNodeId];    }    /// <summary>    /// 返回某一層的所有節點,包含子節點    /// </summary>    /// <param name="listAllNodes">所有的節點資訊</param>    /// <param name="dicNode">鍵為父節點編號,值為父節點對應的子節點</param>    /// <returns></returns>    private static Dictionary<int, List<TreeNode>> GetOneLevelNodes(List<TreeNode> listAllNodes, Dictionary<int, List<TreeNode>> dicNode)    {        int rootNodeId = -1; //虛擬根節點編號              List<int> ParentsIdList = new List<int>();        ParentsIdList.AddRange(dicNode.Keys);//這次需要添加的節點編號        Dictionary<int, List<TreeNode>> dicNode2 = new Dictionary<int, List<TreeNode>>();//鍵為父節點編號,值為父節點對應的子節點        for (int i = listAllNodes.Count - 1; i >= 0; i--)        {            TreeNode item = listAllNodes[i];            if (ParentsIdList.Contains(item.ID))            {                               int parentId = rootNodeId;//預設為頂級節點                if (item.ParentID.HasValue)//如果存在父節點                {                    parentId = item.ParentID.Value;                }                List<TreeNode> children = dicNode[item.ID];//擷取此節點對應的父節點                item.children = children;//添加子節點                AddOneNode(parentId, dicNode2, item);//添加節點到字典中                listAllNodes.RemoveAt(i);//移除已經處理的節點            }        }        return dicNode2;    }    /// <summary>    /// 合并具有相同父節點的兄弟節點    /// </summary>    /// <param name="parentId">需要處理的節點的父節點</param>    /// <param name="dicNode">此層對應的節點字典</param>    /// <param name="node">需要處理的節點</param>    private static void AddOneNode(int parentId, Dictionary<int, List<TreeNode>> dicNode, TreeNode node)    {        if (dicNode.ContainsKey(parentId))//如果有        {            dicNode[parentId].Add(node);//如果具有相同的父節點,則添加到相應的兄弟節點列表中        }        else//如果沒有        {            List<TreeNode> listChild = new List<TreeNode>();            listChild.Add(node);//兄弟節點列表            dicNode.Add(parentId, listChild);        }    }   

由於每一個節點的報價都是通過它的子節點的報價計算出來的,似乎在樹建成後,還需要遍曆一次計算報價?如何寫代碼?似乎還真不好處理?

     想不到最總卻是通過屬性解決的。

核心代碼如下:

  

 private double m_Price = 0;//預設為0,    public double Price    {        get        {            if (m_Price == 0)//如果是預設值,則調用方法計算            {                m_Price = GetPrice();             }            return m_Price;        }        set { m_Price = value; }    }    /// <summary>    /// 通過子節點計算此節點的報價    /// </summary>    /// <returns></returns>    private double GetPrice()    {        if (m_Price > 0)//已經計算過,直接返回        {            return m_Price;        }        double PriceTemp = 0;        if (children != null && children.Count > 0)        {            foreach (TreeNode node in children)// 通過子節點計算此節點的報價            {                if (node.Count.HasValue)                {                    PriceTemp += node.Count.Value * node.Price;                }                else                {                    PriceTemp += node.Price;                }            }        }              return PriceTemp;    }

  完整代碼:

public class TreeNode{    private int m_ID;    public int ID    {        get { return ID; }        set { ID = value; }    }    private int? m_ParentID;    public int? ParentID    {        get { return m_ParentID; }        set { m_ParentID = value; }    }    private int? m_Count;    public int? Count    {        get { return m_Count; }        set { m_Count = value; }    }    private string m_PL_Code;    public string PL_Code    {        get { return m_PL_Code; }        set { m_PL_Code = value; }    }      private string m_Name;    public string Name    {        get { return m_Name; }        set { m_Name = value; }    }    private double m_Price = 0;//預設為0,    public double Price    {        get        {            if (m_Price == 0)//如果是預設值,則調用方法計算            {                m_Price = GetPrice();             }            return m_Price;        }        set { m_Price = value; }    }    /// <summary>    /// 通過子節點計算此節點的報價    /// </summary>    /// <returns></returns>    private double GetPrice()    {        if (m_Price > 0)//已經計算過,直接返回        {            return m_Price;        }        double PriceTemp = 0;        if (children != null && children.Count > 0)        {            foreach (TreeNode node in children)// 通過子節點計算此節點的報價            {                if (node.Count.HasValue)                {                    PriceTemp += node.Count.Value * node.Price;                }                else                {                    PriceTemp += node.Price;                }            }        }              return PriceTemp;    }    private List<TreeNode> m_children;    public List<TreeNode> children    {        get { return m_children; }        set { m_children = value; }    }    /// <summary>    /// 返回需要的樹    /// </summary>    /// <param name="listAllNodes">所有的節點資訊</param>    /// <param name="dicNode">鍵為父節點編號,值為父節點對應的子節點  ,初始為需要顯示的分葉節點</param>    /// <returns></returns>    public static List<TreeNode> GeTree(List<TreeNode> listAllNodes, Dictionary<int, List<TreeNode>> dicNode)    {        int rootNodeId = -1;//虛擬根節點編號        while (!dicNode.ContainsKey(rootNodeId)) //如果沒有到根節點繼續        {            dicNode = GetOneLevelNodes(listAllNodes, dicNode);        }        return dicNode[rootNodeId];    }    /// <summary>    /// 返回某一層的所有節點,包含子節點    /// </summary>    /// <param name="listAllNodes">所有的節點資訊</param>    /// <param name="dicNode">鍵為父節點編號,值為父節點對應的子節點</param>    /// <returns></returns>    private static Dictionary<int, List<TreeNode>> GetOneLevelNodes(List<TreeNode> listAllNodes, Dictionary<int, List<TreeNode>> dicNode)    {        int rootNodeId = -1; //虛擬根節點編號              List<int> ParentsIdList = new List<int>();        ParentsIdList.AddRange(dicNode.Keys);//這次需要添加的節點編號        Dictionary<int, List<TreeNode>> dicNode2 = new Dictionary<int, List<TreeNode>>();//鍵為父節點編號,值為父節點對應的子節點        for (int i = listAllNodes.Count - 1; i >= 0; i--)        {            TreeNode item = listAllNodes[i];            if (ParentsIdList.Contains(item.ID))            {                               int parentId = rootNodeId;//預設為頂級節點                if (item.ParentID.HasValue)//如果存在父節點                {                    parentId = item.ParentID.Value;                }                List<TreeNode> children = dicNode[item.ID];//擷取此節點對應的子節點                item.children = children;//添加子節點                AddOneNode(parentId, dicNode2, item);//添加節點到字典中                listAllNodes.RemoveAt(i);//移除已經處理的節點            }        }        return dicNode2;    }    /// <summary>    /// 合并具有相同父節點的兄弟節點    /// </summary>    /// <param name="parentId">需要處理的節點的父節點</param>    /// <param name="dicNode">此層對應的節點字典</param>    /// <param name="node">需要處理的節點</param>    private static void AddOneNode(int parentId, Dictionary<int, List<TreeNode>> dicNode, TreeNode node)    {        if (dicNode.ContainsKey(parentId))//如果有        {            dicNode[parentId].Add(node);//如果具有相同的父節點,則添加到相應的兄弟節點列表中        }        else//如果沒有        {            List<TreeNode> listChild = new List<TreeNode>();            listChild.Add(node);//兄弟節點列表            dicNode.Add(parentId, listChild);        }    }   }

     

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.