计算一棵树的深度和宽度[Treeview的深度和宽度](多题头的表格问题解决的基础)

当我有一棵树,我想知道它的枝叶最深的级别是多少?它有多少个叶子(最终的节点,我称它为宽度)?
用.net怎么来作呢?
这个题目的提出是由于要设计一个多题头的表格而抽象出来的。
动态生成一个多题头的表格如下:


由如下xml描述
 1    <item HeaderText="Lifecycle Status (Start Date)" >
 2        <item HeaderText="Sample"  TitleCss="trTitle2">
 3            <item HeaderText="α"  ColumnName="sample" TitleCss="trTitle2"   Format="d" />    
 4            <item HeaderText="β"  ColumnName="Sampleb"  TitleCss="trTitle2"  Format="d"  />    
 5            <item HeaderText="ES" ColumnName="SampleES" TitleCss="trTitle2"   Format="d" />    
 6        </item>
 7        <item HeaderText="NPI" ColumnName="NPI" TitleCss="trTitle2"  Format="d" />
 8        <item HeaderText="CEM" ColumnName="CEM" TitleCss="trTitle2"  Format="d" />
 9    
10    </item>
11    <item HeaderText="Under developing and technically immature" >
12        <item HeaderText="Start Date" Width="120" ColumnName="red" TitleCss="trTitle2" Format="d"  />
13        <item HeaderText="Sample Available"  Width="120"  ColumnName="redsample" TitleCss="trTitle2"   Format="d" />    
14    </item>

完成动态的创建多题头的表格的难点在于,
一棵树的深度和宽读,一个叶枝的级别以及这个叶枝有多少个子叶枝(宽度).
=============================================================
现在我完成一些基本的东西。


先计算一个树的宽度[由此可得到一个节点的宽度的算法]
定义初始宽度
private int _treeWidth = 0 ;

利用递归算法来遍历父节点下面的所有的节点,发现是叶子的则加一
#region 计算树的宽度
        
/// <summary>
        
/// 遍历所有节点。
        
/// 发现节点是树叶则加一
        
/// 否则,取节点的子节点循环
        
/// </summary>
        
/// <param name="node"></param>

        private void CountTreeWidth(TreeNode node)
        
{
            
if(node.Nodes.Count==0)
                
this._treeWidth ++;
            
else
            
{
                
for(int i=0;i<node.Nodes.Count;i++)
                
{
                    CountTreeWidth(node.Nodes[i]);
                }

            }


        }

        
#endregion


计算树的深度算法我开始想了一个,结果发现有一点问题:
还是先定义初始变量,一个为最大的值,一个为目前的深度值
private int _max = 0;
private int _level =0;

第一个算法:
基本想法是,遍历所有的节点,如果节点还有子节点则加1,
否则目前深度值置为零。

    #region 算法一
        
private void CountLevel(TreeNode MyNode)
        
{
            _level
++;
            
if(_level>_max)
                _max 
= _level;
            System.Diagnostics.Debug.WriteLine(MyNode.Text);
            
if(MyNode.Nodes.Count!=0)
            
{
                
                
for(int i=0;i<MyNode.Nodes.Count;i++)
                
{
                    System.Diagnostics.Debug.WriteLine(_level);
                    CountLevel(MyNode.Nodes[i]);
                    

                }

            }

            
else
            
{
                System.Diagnostics.Debug.WriteLine(_level);
            
                    
//_level --;
                _level = 0;

            }

            
            

        }

        
#endregion


这个算法对单根线的计算是没有问题的,
但是对于多个子节点的计算是有问题的:
看看图

为了降低解释问题的负责度,我只取这个图树的一个节点来分析。
假如我们的这个树是上图节点1开始(包括节点1下面所有子节点)。
我们看算法是怎么算的。。。
算法遍历的过程是

节点1->节点2->节点3->节点13
此时最大深度_max=4
_level = 0[因为节点13是叶子]
继续。。
这时递归退回到节点2
节点2->节点4
_level = 1
这个时候已经出现问题,
因为节点2的level是3
而计算出来节点4的深度应该是
_level = 3
计算节点4的深度不应该重新计数



如上图如果按照算法,
节点4的
_level = 1
最后算出来的_max = 5
而真实的值应该为6


现在把算法二改进版
#region 算法二改进
        
/// <summary>
        
/// 算法还可以改进
        
/// 如果知道parent的级别,则本级别则等于parent的level+1
        
/// </summary>
        
/// <param name="MyNode"></param>

        private void CountLevel3(TreeNode MyNode)
        
{
            _level 
= 1;

            
if(MyNode.Parent!=null)
            
{
                MyNode.Tag 
= (int)MyNode.Parent.Tag + 1;
                _level 
= (int)MyNode.Tag;
            }


            
//getMaxDeep(MyNode);
            if(_level>_max)
                _max 
= _level;
            
for(int i=0;i<MyNode.Nodes.Count;i++)
            
{
                CountLevel3(MyNode.Nodes[i]);
            }


        }


      
        
        
#endregion

这个算法的想法是确定每个节点的级别,最顶上的是一,
节点向下遍历的时候,子节点的级别为parent level+1,
最大的付给_max,这样就可以得到树的深度了。

posted on 2005-05-11 12:35  一望无际的南  阅读(5171)  评论(2编辑  收藏  举报

导航