呃,怎么说呢,这个和vczh的同名文章是互为补充的。这是最近老板的要求,所以就写了这么个东西。
vczh的方法生成的树是sparse的,而我这里树则要紧凑一些,所使用的坐标系也与之不同。
效果(看起来挺菜,哇咔咔)

布局分为水平布局和竖直布局两个部分,我这里先进行了水平布局再进行了竖直布局。
一般来讲紧凑的树主要指同级节点方向上的紧凑性。由于这里树是父节点在上,子结点在下,因此水平方向上的节点要尽量紧凑。那么便需要我将节点尽量往左布局。
如果自左往右布置节点,那么很显然,左边的节点的位置一旦固定下来就不需要再行调整。
同时,为了保持树的美观,父节点的水平中心应当是子结点的水平中心,这样子结点就会对称分布在父节点的下方,有利于美观。
然而父节点能正常布局的位置,子结点可能无法正常布局(子结点的宽度比父节点宽得多)。因此我们还需要调整子结点的布局。
由于是自左向右布局的,此时子结点的左边的节点都已经确定了,正确的布局很容易便可以通过右移得到。
为了保证正确性,还需要把父节点也右移。因为父节点的右边没有布局限制,因而可以放心的右移。这样一直传递到根节点就可以了。
那么很明显,整体来说,布局顺序就是,自下而上,自左而右。
为了让节点在布局的时候知道自己能被安排的最左位置,需要为每一层保存最左可布局位置的坐标。
一旦有节点被安排妥当,便更新节点所在层次的最左可布局位置。后来的节点只要在这个位置的右方布局,就不会与已布置的节点冲突。
竖直布局并不复杂,算出每一层的Top就可以了。
代码如下: 
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
//布局算法:
//采用平行节点最左布局,父子节点对中布局的原则。
/****
 *  void Layout(int lyr)
 *  {
 *     
 *  }
 * 
*****/
namespace CrowdTree
{
    class LayoutTreeLayerInfo
    {
        //可安排布局的最左坐标
        private Dictionary<int, float> lyrLefts = new Dictionary<int,float>();
        private Dictionary<int, float> heights = new Dictionary<int,float>();
        public void Reset()
        {
            lyrLefts = new Dictionary<int, float>();
            heights = new Dictionary<int, float>();
        }
        public float GetLayoutableLeft(int level)
        {
            if (lyrLefts.ContainsKey(level))
            {
                return lyrLefts[level];
            }
            return 0;
        }
        public void SetLayoutableLeft(int level, float left)
        {
            if (lyrLefts.ContainsKey(level))
            {
                lyrLefts[level] = Math.Max(left, lyrLefts[level]);
            }
            else
            {
                lyrLefts[level] = Math.Max(0, left);
            }
        }
        public void SetLayoutLevelMinHeight(int level, float height)
        {
            if (heights.ContainsKey(level))
            {
                heights[level] = Math.Max(heights[level], height);
            }
            else
            {
                heights[level] = height;
            }
        }
        public float GetLayoutLevelMinHeight(int level)
        {
            if (heights.ContainsKey(level))
            {
                return heights[level];
            }
            return 0;
        }
    }
    class LayoutTreeNode
    {
        protected LayoutTree owner_;
        protected LayoutTreeLayerInfo lyrInfo_;
        protected int lyrLevel_;
        protected RectangleF rect_;
        protected List<LayoutTreeNode> children_ = new List<LayoutTreeNode>();
        public int Level
        {
            get { return lyrLevel_; }
            set { lyrLevel_ = value; }
        }
        public LayoutTree Owner
        {
            get { return owner_; }
            set { owner_ = value; }
        }
        public LayoutTreeLayerInfo LayerInfo
        {
            set { lyrInfo_ = value; }
        }
        public List<LayoutTreeNode> Children
        {
            get { return children_; }
        }
        public RectangleF Extent
        {
            get { return rect_; }
        }
        protected void LayoutHorizontal()
        {
            //获取当前节点能够排布的最左位置,并预先安排当前节点。
            float originLeft = lyrInfo_.GetLayoutableLeft(lyrLevel_);
            rect_.X = originLeft;
            //根据当前结点的坐标,安排子结点,并需要根据子结点的安置情况重新调整父节点的安置
            if (children_.Count > 0)
            {
                //计算子结点最左可以安放的位置
                float childrenTotalWidth = 0.0F;
                foreach (LayoutTreeNode child in children_)
                {
                    childrenTotalWidth += child.Extent.Width;
                }
                childrenTotalWidth += ((children_.Count - 1) * owner_.HorizontalSpacer);
                float childLeftest = originLeft + (rect_.Width / 2.0f) - (childrenTotalWidth / 2.0F);
                //设置子结点安放的最左位
                lyrInfo_.SetLayoutableLeft(lyrLevel_ + 1, childLeftest);
                //安放子结点
                for (int idxChild = 0; idxChild < children_.Count; ++idxChild)
                {
                    children_[idxChild].LayoutHorizontal();
                }
                 //利用子结点重新对中安置当前节点
                float center = (children_[0].Extent.Left + children_[children_.Count - 1].Extent.Right) / 2.0F;
                rect_.X = center - rect_.Width / 2.0F;
            }
            //利用节点坐标设置该层其他子结点所能安放的最左位置,并设置一下当前层元素的最大高度
            lyrInfo_.SetLayoutableLeft(lyrLevel_, this.rect_.Right + owner_.HorizontalSpacer);
            lyrInfo_.SetLayoutLevelMinHeight(lyrLevel_, this.rect_.Height);
        }
        protected void LayoutVertical(float top)
        {
            rect_.Y = top;
            foreach (LayoutTreeNode child in children_)
            {
                child.LayoutVertical(top + lyrInfo_.GetLayoutLevelMinHeight(lyrLevel_) + owner_.VerticalSpacer);
            }
        }
        public void Layout()
        {
            LayoutHorizontal();
            LayoutVertical(0.0f);
        }
        public virtual void CalculateSize(float maxWidth, Font font, Graphics g)
        {
        }
        public virtual void CalculateSizeRecursive(float maxWidth, Font font, Graphics g)
        {
        }
        public virtual void Draw(Graphics g) { }
    }
    class TextLayoutTreeNode: LayoutTreeNode
    {
        private string text;
        private StringFormat strFmt = new StringFormat();
        private Font font;
        public String Text
        {
            get { return text; }
            set { text = value; }
        }
        public override void CalculateSize(float maxWidth, Font font, Graphics g)
        {
            strFmt.Alignment = StringAlignment.Center;
            strFmt.LineAlignment = StringAlignment.Center;
            rect_.Size = g.MeasureString(text, font, (int)maxWidth, strFmt);
            this.font = font;
        }
        public override void CalculateSizeRecursive(float maxWidth, Font font, Graphics g)
        {
            CalculateSize(maxWidth, font, g);
            foreach (LayoutTreeNode node in children_)
            {
                node.CalculateSizeRecursive(maxWidth, font, g);
            }
        }
        public override void Draw(Graphics g)
        {
            //外轮廓,内容,连线
            g.DrawRectangle(Pens.Black, Rectangle.Round(Extent));
            g.DrawString(text, font, Brushes.Red, Extent);
            foreach (LayoutTreeNode childNode in children_)
            {
                //绘制斜线
                
                float childX = (childNode.Extent.Left + childNode.Extent.Right) / 2.0F;
                float childY = childNode.Extent.Top;
                
                float curX = (Extent.Left + Extent.Right) / 2.0f;
                float curY = Extent.Bottom;
                g.DrawLine(Pens.Black, new PointF(childX, childY), new PointF(curX, curY));
            }
        }
    }
    class LayoutTree
    {
        private float vertical_spacer;
        private float horizontal_spacer;
        private LayoutTreeNode root;
        private LayoutTreeLayerInfo lyrInfo = new LayoutTreeLayerInfo();
        public float VerticalSpacer
        {
            get { return vertical_spacer; }
            set { vertical_spacer = value; }
        }
        public float HorizontalSpacer
        {
            get { return horizontal_spacer; }
            set { horizontal_spacer = value; }
        }
        public LayoutTreeNode Root
        {
            get { return root; }
            set { root = value; }
        }
        public void ResetLayout()
        {
            lyrInfo.Reset();
        }
        public T CreateNode<T> (LayoutTreeNode parent) where T:LayoutTreeNode, new()
        {
            T retNode = new T();
            
            retNode.Owner = this;
            retNode.LayerInfo = this.lyrInfo;
            if (parent == null)
            {
                this.root = retNode;
                retNode.Level = 0;
            }
            else
            {
                parent.Children.Add(retNode);
                retNode.Level = parent.Level + 1;
            }
            return retNode;
        }
    }
}