为了制作数据结构算法的图示教学软件,请教各位大哥大姐,如何用代码根据一个未排序的序列画出一棵二叉树呢?O(∩_∩)O谢谢~~
解决方案 »
- C# 里的TreeView ,如何设置仅使特定的 TreeNode前有勾选框?
- log4net插入到数据库---log4net.config里执行数据库操作
- Oracle NUMBER(10,2) 这种类型在C# 对应什么?
- 如何锁定Excel里sheet
- DataTable的Select方法可以写成类似SQL语句那种带参数的形式么?
- 在GridView中,如何去除最后一行的超链接?
- 急问:怎么读取串口 “port A”
- .net的应用程序设置.exe.config怎么用啊?
- datagrid中的一列为combobox格式,但怎样与数据库中数据绑定?
- 在水晶报表里如何将一页里分成两个半页(左右两个半页)来显示查询信息啊?
- 做学费管理系统的准备是什么
- c#读取验证码
tree.Add("北京公司");
tree.Add("董事秘书室特殊机构");
tree.Add("上海公司"); tree.Childs[0].Add("总经理办公室");
tree.Childs[0].Add("财务部");
tree.Childs[0].Add("销售部"); tree.Childs[2].Add("上海销售部"); Bitmap bmp = tree.DrawAsImage();实现代码:using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;namespace Test{
/// <summary>
/// 用来输出组织结构图的类
/// </summary>
/// <typeparam name="T"></typeparam>
public class Tree<T>
{
Tree<T> _Parent = null;
T _Content;
List<Tree<T>> _Childs = new List<Tree<T>>();
SizeF _Size;
Rectangle _Rec; public Tree(Tree<T> parent, T content)
{
_Parent = parent;
_Content = content;
} public Tree<T> Add(T content)
{
Tree<T> tree = new Tree<T>(this, content);
_Childs.Add(tree);
return tree;
} public Tree<T> Parent { get { return _Parent; } } public T Content { get { return _Content; } } public List<Tree<T>> Childs { get { return _Childs; } } public SizeF Size { get { return _Size; } set { _Size = value; } } public Rectangle Rec { get { return _Rec; } set { _Rec = value; } } void MeatureAllSize(Graphics g, Font font, int addWidth)
{
_Size = g.MeasureString(_Content.ToString(), font);
_Size.Width += addWidth;
foreach (Tree<T> tree in Childs)
tree.MeatureAllSize(g, font, addWidth);
} List<List<Tree<T>>> GetTreeLayers()
{
List<List<Tree<T>>> layers = new List<List<Tree<T>>>();
GetTreeLayers(layers, new List<Tree<T>>(new Tree<T>[] { this }), 0); return layers;
} void GetTreeLayers(List<List<Tree<T>>> layers, List<Tree<T>> childs, int level)
{
if (childs.Count == 0) return;
if (layers.Count <= level) layers.Add(new List<Tree<T>>()); for (int i = 0; i < childs.Count; i++)
{
layers[level].Add(childs[i]);
GetTreeLayers(layers, childs[i].Childs, level + 1);
}
} /// <summary>
/// 设置显示区域(从最后一层最左开始)
/// </summary>
/// <param name="level"></param>
/// <param name="height"></param>
/// <param name="interval"></param>
/// <param name="left"></param>
void SetRectangle(int level, int height, int hInterval, int vInterval, int left)
{
int index = 0;
if (Parent != null) index = Parent.Childs.IndexOf(this); if (Childs.Count == 0)
{
// 没有儿子,就向前靠
if (left > 0) left += hInterval;
}
else
{
// 有儿子,就在儿子中间
int centerX = (Childs[0].Rec.Left + Childs[Childs.Count - 1].Rec.Right) / 2;
left = centerX - (int)_Size.Width / 2; // 并且不能和前面的重复,如果重复,联同子孙和子孙的右边节点右移
if (Parent != null && index > 0)
{
int ex = (Parent.Childs[index - 1].Rec.Right + hInterval) - left;
if (index > 0 && ex > 0)
{
for (int i = index; i < Parent.Childs.Count; i++)
Parent.Childs[i].RightChilds(ex);
left += ex;
}
}
}
_Rec = new Rectangle(left, (height + vInterval) * level, (int)_Size.Width, height);
} /// <summary>
/// 所有子孙向右平移
/// </summary>
/// <param name="ex"></param>
void RightChilds(int ex)
{
Rectangle rec;
for (int i = 0; i < _Childs.Count; i++)
{
rec = _Childs[i].Rec;
rec.Offset(ex, 0);
_Childs[i].Rec = rec;
_Childs[i].RightChilds(ex);
}
} void Offset(int x, int y)
{
_Rec.Offset(x, y);
for (int i = 0; i < _Childs.Count; i++)
_Childs[i].Offset(x, y);
} public Bitmap DrawAsImage()
{
return DrawAsImage(Pens.Black, new Font("宋体", 10.5f), 26, 20, 5, 20, 26);
} public Bitmap DrawAsImage(Pen pen, Font font, int h, int horPadding,
int horInterval, int verInterval, int borderWidth)
{
Bitmap bmp = new Bitmap(1, 1);
Graphics g = Graphics.FromImage(bmp);
// 把树扁平化
List<List<Tree<T>>> layers = GetTreeLayers(); // 算出每个单元的大小
MeatureAllSize(g, font, horPadding);
g.Dispose();
bmp.Dispose(); // 从最后一层开始排列
int left = 0;
for (int i = layers.Count - 1; i >= 0; i--)
{
for (int j = 0; j < layers[i].Count; j++)
{
layers[i][j].SetRectangle(i, h, horInterval, verInterval, left);
left = layers[i][j].Rec.Right;
}
} Offset(borderWidth, borderWidth); // 获取画布需要的大小
int maxHeight = (h + verInterval) * layers.Count - verInterval + borderWidth * 2;
int maxWidth = 0;
for (int i = layers.Count - 1; i >= 0; i--)
{
for (int j = 0; j < layers[i].Count; j++)
{
if (layers[i][j].Rec.Right > maxWidth)
maxWidth = layers[i][j].Rec.Right;
}
}
maxWidth += borderWidth; // 边宽 // 画
bmp = new Bitmap(maxWidth, maxHeight);
g = Graphics.FromImage(bmp);
g.Clear(Color.White);
StringFormat format = (StringFormat)StringFormat.GenericDefault.Clone();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center; Rectangle rec, recParent;
for (int i = 0; i < layers.Count; i++)
{
for (int j = 0; j < layers[i].Count; j++)
{
// 画字
rec = (Rectangle)layers[i][j].Rec;
g.DrawRectangle(pen, rec);
g.DrawString(layers[i][j].Content.ToString(), font, new SolidBrush(pen.Color),
rec, format);
// 画到父亲的线
if (layers[i][j].Parent != null)
{
recParent = layers[i][j].Parent.Rec;
g.DrawLine(pen, rec.Left + rec.Width / 2, rec.Top,
rec.Left + rec.Width / 2, rec.Top - verInterval / 2);
g.DrawLine(pen, recParent.Left + recParent.Width / 2, recParent.Bottom,
recParent.Left + recParent.Width / 2, rec.Top - verInterval / 2);
g.DrawLine(pen, rec.Left + rec.Width / 2, rec.Top - verInterval / 2,
recParent.Left + recParent.Width / 2, rec.Top - verInterval / 2);
}
}
} g.Flush();
g.Dispose(); return bmp;
}
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ssdjmcj8048/archive/2007/12/11/1929658.aspx