博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

二叉树的显示

Posted on 2006-12-31 15:16  空气  阅读(1862)  评论(17编辑  收藏  举报

        数据结构的老师写了一个显示二叉树的程序.用C语言实现.在二叉树的基本操作的基础上,利用绘图函数实现了二叉树在屏幕上的输出,并可以通过键盘控制树的显示比例,字体大小,等等.

        我觉得这个程序很有趣,就用C#重写了一次.基本实现了与老师那个相同的功能.不过他的是控制台应用程序,我的是窗体应用程序.而且程序代码完全不同.


这个是程序的截图:




下面是程序的具体代码:

程序主要由四个类组成:
BinaryTree : 实现基本的二叉树数据结构.是程序的底层.
TreeGraph:  实现绘图的操作.是连接底层数据结构和窗体显示的桥梁.程序的中间层.
Form_Tree: 窗体类.
Setting:        在其中设置程序运行时的变量,方便修改.


类图:










下面是各个文件的代码



Setting.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace BinaryTree
{
    
/// <summary>
    
/// Setting 类用于设定环境变量
    
/// </summary>

    class Setting
    
{
        
public static int[] initTree = new int[] 50338920456095102540 };       // 用以初始化Tree

        
public static int distanceHeight = 50;   // 两个节点之间的高度差
        public static int distanceWidth = 20;    // 两个节点之间的宽度差
        public static int disHChange = 3;        // 高度差的变化幅度
        public static int disWChange = 1;        // 宽度差的变化幅度

        
public static int nodeRadius = 15;       // 节点圆圈的半径
        public static int radiusChange = 2;      // 节点圆圈半径的变化幅度
        public static int radiusMin = 15;         // 节点圆圈半径所允许的最小值

        
public static int middleX = 300;         // 绘图中心点的横坐标
        public static int middleY = 260;         // 绘图中心点的纵坐标
        public static int screenH = 350;         // 屏幕高度
        public static int screenW = 600;         // 屏幕宽度

        
public static Color backColor = Color.LightSteelBlue;   // 背景颜色
        private static Color fontColor = Color.Black;      // 字体颜色
        public static Brush fontBrush = new SolidBrush(fontColor);
        
private static Color lineColor = Color.Orange;     // 线条颜色
        public static SolidBrush cirBrush = new SolidBrush(lineColor);
        
public static Pen myPen = new Pen(lineColor);
        
public static float myPenChange = 1F;
        
public static Font myFont = new Font("Arial"18, FontStyle.Regular, GraphicsUnit.Pixel);
        
public static float fontChange = 2.8F;
    }

}





Tree.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace BinaryTree
{
    
/// <summary>
    
/// 实现基本的数据结构
    
/// 提供二叉树的基本操作
    
/// 包括构造一个空树,插入,查找,删除
    
/// </summary>

    public class BinaryTree
    
{
        
public TreeNode root;     //根节点
        bool found = false;        //默认查找不存在

        
/// <summary>
        
/// 构造函数-构造一个空树
        
/// </summary>

        public BinaryTree()
        
{
            root 
= null;
        }


        
public TreeNode TreeNode
        
{
            
get
            
{
                
throw new System.NotImplementedException();
            }

            
set
            
{
            }

        }


        
internal TreeGraph TreeGraph
        
{
            
get
            
{
                
throw new System.NotImplementedException();
            }

            
set
            
{
            }

        }


        
/// <summary>
        
/// 获得树的高度
        
/// </summary>
        
/// <returns></returns>

        public int Height()
        
{
            
if (root == null)
            
{
                
return 1;
            }


            
return Math.Max(Height(root.LeftNode), Height(root.RightNode)) + 1;
        }


        
/// <summary>
        
/// 删除元素
        
/// </summary>
        
/// <param name="data">要删除的元素的值</param>

        public void Remove(int data)
        
{
            
if (root == null)
            
{
                
return;
            }


            
if (!Search(data))
            
{
                
return;
            }


            
if (root.data == data)
            
{
                TreeNode tmp 
= Min(root.RightNode);
                
if (tmp == null)
                
{
                    root 
= root.LeftNode;
                }

                
else
                
{
                    root.data 
= tmp.data;
                    Remove(root, root.RightNode, 
1, tmp.data);
                }

            }

            
else if (root.data < data)
            
{
                Remove(root, root.RightNode, 
1, data);
            }

            
else
            
{
                Remove(root, root.LeftNode, 
0, data);
            }

        }


        
/// <summary>
        
/// 查找是否存在该元素
        
/// </summary>
        
/// <param name="data">要查找的元素的值</param>
        
/// <returns></returns>

        public bool Search(int data)
        
{
            
if (root == null)
            
{
                
return false;
            }


            
bool temp = false;
            found 
= false;
            
if (root.data == data)
            
{
                temp 
= true;
            }

            
else
            
{
                temp 
= Search(root, data);
            }

            
return temp;
        }


        
/// <summary>
        
/// 插入元素
        
/// </summary>
        
/// <param name="data">要插入的元素的值</param>

        public void Insert(int data)
        
{
            
if (Search(data))
            
{
                
return;
            }


            
if (root == null)
            
{
                root 
= new TreeNode();
                root.data 
= data;
            }

            
else
            
{
                Insert(root, data);
            }

        }


        
/// <summary>
        
/// 打印
        
/// </summary>

        public void Print()
        
{
            
if (root == null)
            
{
                Console.WriteLine(
"Empty");
            }

            
else
            
{
                Print(root);
                Console.WriteLine();
            }

        }


        
/// <summary>
        
/// 获得树的高度,递归
        
/// </summary>
        
/// <param name="parent"></param>
        
/// <returns></returns>

        private int Height(TreeNode parent)
        
{
            
if (parent == null)
            
{
                
return 0;
            }


            
return Math.Max(Height(parent.LeftNode), Height(parent.RightNode)) + 1;
        }


        
/// <summary>
        
/// 获得该节点最小右子女,用于删除元素使用
        
/// </summary>
        
/// <param name="parent"></param>
        
/// <returns></returns>

        private TreeNode Min(TreeNode parent)
        
{
            TreeNode temp 
= parent;
            
while (temp != null)
            
{
                
if (temp.LeftNode == null)
                    
return temp;
                
else
                    temp 
= temp.LeftNode;
            }

            
return null;
        }


        
/// <summary>
        
/// 删除元素递归
        
/// </summary>
        
/// <param name="parent"></param>
        
/// <param name="cur"></param>
        
/// <param name="direction"></param>
        
/// <param name="data"></param>

        private void Remove(TreeNode parent, TreeNode cur, int direction, int data)
        
{
            
if (cur == null)
            
{
                
return;
            }


            
if (cur.data == data)
            
{
                
if (cur.LeftNode == null)
                
{
                    
if (direction == 0)
                        parent.LeftNode 
= cur.RightNode;
                    
else
                        parent.RightNode 
= cur.RightNode;
                }

                
else if (cur.RightNode == null)
                
{
                    
if (direction == 0)
                        parent.LeftNode 
= cur.LeftNode;
                    
else
                        parent.RightNode 
= cur.LeftNode;
                }

                
else
                
{
                    TreeNode tmp 
= Min(cur.RightNode);
                    cur.data 
= tmp.data;
                    Remove(cur, cur.RightNode, 
1, tmp.data);
                }

            }

            
else if (cur.data > data)
            
{
                Remove(cur, cur.LeftNode, 
0, data);
            }

            
else
            
{
                Remove(cur, cur.RightNode, 
1, data);
            }

        }


        
/// <summary>
        
/// 查找是否存在该元素,递归
        
/// </summary>
        
/// <param name="node"></param>
        
/// <param name="data"></param>
        
/// <returns></returns>

        private bool Search(TreeNode node, int data)
        
{
            
if (node.data == data)
            
{
                found 
= true;
            }

            
else
            
{
                
if (node.data > data)
                
{
                    
if (node.LeftNode != null)
                    
{
                        Search(node.LeftNode, data);
                    }

                }

                
else
                
{
                    
if (node.RightNode != null)
                    
{
                        Search(node.RightNode, data);
                    }

                }

            }

            
return found;
        }


        
/// <summary>
        
/// 插入元素,递归
        
/// </summary>
        
/// <param name="node"></param>
        
/// <param name="data"></param>

        private void Insert(TreeNode node, int data)
        
{
            
if (node.data > data)
            
{
                
if (node.LeftNode == null)
                
{
                    TreeNode temp 
= new TreeNode();
                    temp.data 
= data;
                    node.LeftNode 
= temp;
                }

                
else
                
{
                    Insert(node.LeftNode, data);
                }

            }

            
else
            
{
                
if (node.RightNode == null)
                
{
                    TreeNode temp 
= new TreeNode();
                    temp.data 
= data;
                    node.RightNode 
= temp;
                }

                
else
                
{
                    Insert(node.RightNode, data);
                }

            }

        }


        
/// <summary>
        
/// 打印,递归
        
/// </summary>
        
/// <param name="node"></param>

        private void Print(TreeNode node)
        
{
            
if (node == null)
            
{
                
return;
            }


            Console.Write(node.data);
            Console.Write(
" ");
            Print(node.LeftNode);
            Print(node.RightNode);
        }

    }



    
/// <summary>
    
/// 树类型的节点
    
/// </summary>

    public class TreeNode
    
{
        
public int data;               //节点数据
        public TreeNode LeftNode;      //左子女
        public TreeNode RightNode;     //右子女
        /// 
        
/// 构造函数,初始化左右子女为空
        
/// 

        public TreeNode()
        
{
            LeftNode 
= RightNode = null;
        }

    }


}




TreeGraph.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace BinaryTree
{
    
/// <summary>
    
/// 绘图函数
    
/// 是连接底层数据结构和窗体显示的桥梁
    
/// </summary>

    class TreeGraph
    
{
        
/// <summary>
        
/// 绘图相关变量
        
/// </summary>

        private int distanceHeight;    // 两个节点之间的高度差
        private int distanceWidth;     // 两个节点之间的宽度差
        private int nodeRadius;        // 节点圆圈的半径
        private Point middlePoint;     // 绘图的中心点

        
private Graphics myGraphics;
        
private Color backColor;       // 窗体的背景颜色
        private Brush fontBrush;       // 字体颜色
        private SolidBrush cirBrush;   // 圆圈的颜色
        private Pen myPen;             // 连线的颜色
        private Font myFont;           // 字体



        
/// <summary>
        
/// 数据(树)相关变量
        
/// </summary>

        private BinaryTree myBT = new BinaryTree();



        
/// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="gc"></param>

        public TreeGraph(Graphics gc)
        
{
            
/* 初始化绘图相关变量 */
            distanceHeight 
= Setting.distanceHeight;
            distanceWidth  
= Setting.distanceWidth;
            nodeRadius     
= Setting.nodeRadius;
            middlePoint 
= new Point(Setting.middleX, Setting.middleY);

            myGraphics 
= gc;
            backColor 
= Setting.backColor;
            cirBrush 
= Setting.cirBrush;
            fontBrush 
= Setting.fontBrush;
            myPen 
= Setting.myPen;
            myFont 
= Setting.myFont;

            
/* 初始化树 */
            
foreach (int i in Setting.initTree)
            
{
                myBT.Insert(i);
            }

        }


        
public Form_Tree Form_Tree
        
{
            
get
            
{
                
throw new System.NotImplementedException();
            }

            
set
            
{
            }

        }


        
/// <summary>
        
/// 增加节点
        
/// </summary>
        
/// <param name="data">要增加的节点的值</param>

        public void AddNode(int data)
        
{
            myBT.Insert(data);
        }


        
/// <summary>
        
/// 删除节点
        
/// </summary>
        
/// <param name="data">要删除的节点的值</param>

        public void DelNode(int data)
        
{
            myBT.Remove(data);
        }


        
/// <summary>
        
/// 删除整个树
        
/// </summary>

        public void DestoryTree()
        
{
            myBT 
= new BinaryTree();
        }


        
/// <summary>
        
/// 设置字体颜色
        
/// </summary>
        
/// <param name="color"></param>

        public void SetFontColor(Color color)
        
{
            fontBrush 
= new SolidBrush(color);
        }


        
/// <summary>
        
/// 设置圆圈颜色
        
/// </summary>
        
/// <param name="color"></param>

        public void SetLineColor(Color color)
        
{
            myPen.Color 
= color;
            cirBrush.Color 
= color;
        }


        
/// <summary>
        
/// 设置背景颜色
        
/// </summary>
        
/// <param name="color"></param>

        public void SetBackColor(Color color)
        
{
            backColor 
= color;
        }




        
/// <summary>
        
/// 绘图
        
/// </summary>

        public void Draw()
        
{
            myGraphics.Clear(backColor);
            
int high = myBT.Height() * distanceHeight;
            Point top 
= new Point(middlePoint.X, middlePoint.Y - high / 2);
            Draw(myBT.root, top, top, myBT.Height()
-2);
        }


        
/// <summary>
        
/// 增加两个节点之间的高度差
        
/// </summary>

        public void IncreaseDisH()
        
{
            
int high = (myBT.Height()-1* distanceHeight;
            
if (high + nodeRadius > Setting.screenH)
            
{
                
return;
            }

            distanceHeight 
+= Setting.disHChange;
        }


        
/// <summary>
        
/// 减少两个节点之间的高度差
        
/// </summary>

        public void ReduceDisH()
        
{
            
if (distanceHeight <= nodeRadius * 2)
            
{
                
return;
            }

            distanceHeight 
-= Setting.disHChange;
        }


        
/// <summary>
        
/// 增加两个节点之间的宽度差
        
/// </summary>

        public void IncreaseDisW()
        
{
            
int h = myBT.Height()-1;
            
int w = distanceWidth;
            
int r = nodeRadius;
            
int width = (r + w) * (int)(Math.Pow(2.0, (double)h) - 1);
            
if (width*2+nodeRadius*2 > Setting.screenW)
            
{
                
return;
            }

            distanceWidth 
+= Setting.disWChange;
        }


        
/// <summary>
        
/// 减少两个节点之间的宽度差
        
/// </summary>

        public void ReduceDisW()
        
{
            
if (distanceWidth <= 0)
            
{
                
return;
            }

            distanceWidth 
-= Setting.disWChange;
        }


        
/// <summary>
        
/// 增加节点圆圈的半径
        
/// </summary>

        public void IncreaseRadius()
        
{
            
int h = distanceHeight;
            
int w = distanceWidth + nodeRadius;
            
if (nodeRadius*2 > h ||
                nodeRadius
*2 > w ||
                nodeRadius 
* nodeRadius*4  > h*+ w*w)
            
{
                
return;
            }

            h 
= myBT.Height() - 1;
            w 
= distanceWidth;
            
int r = nodeRadius;
            
int width = (r + w) * (int)(Math.Pow(2.0, (double)h) - 1);
            
if (width * 2 + nodeRadius * 2 > Setting.screenW)
            
{
                
return;
            }


            nodeRadius 
+= Setting.radiusChange;

            
/* 字体 */
            
float currentSize = myFont.Size;
            currentSize 
+= Setting.fontChange;
            myFont 
= new Font(myFont.Name, currentSize, myFont.Style, myFont.Unit);
            myPen.Width 
+= Setting.myPenChange;

        }


        
/// <summary>
        
/// 减少节点圆圈的半径
        
/// </summary>

        public void ReduceRadius()
        
{
            
if (nodeRadius <= Setting.radiusMin)
            
{
                
return;
            }


            nodeRadius 
-= Setting.radiusChange;

            
/* 字体 */
            
float currentSize = myFont.Size;
            currentSize 
-= Setting.fontChange;
            myFont 
= new Font(myFont.Name, currentSize, myFont.Style, myFont.Unit);
            myPen.Width 
-= Setting.myPenChange;
        }



        
/// <summary>
        
/// 绘制树的图形,递归
        
/// </summary>
        
/// <param name="parent">要绘制的节点</param>
        
/// <param name="cur">要绘制的位置</param>
        
/// <param name="last">上一次绘制的位置</param>
        
/// <param name="deep">深度,用以确定位置</param>

        private void Draw(TreeNode parent, Point cur, Point last, int deep)
        
{
            
if (parent == null)
            
{
                
return;
            }


            
/* 画圆圈 */
            Size size 
= new Size(nodeRadius*2, nodeRadius*2);
            Point center 
= new Point();
            center.X 
= cur.X - nodeRadius;
            center.Y 
= cur.Y - nodeRadius;
            Rectangle rec 
= new Rectangle(center, size);
            myGraphics.FillEllipse(cirBrush, rec);

            
/* 画线 */
            myGraphics.DrawLine(myPen, cur, last);

            
/* 绘制左右子树 */
            Point left 
= new Point();
            
int len = (int)Math.Pow(2.0, (double)deep);
            
//left.X = cur.X - (distanceWidth + nodeRadius) * deep - distanceWidth;
            
//left.X = cur.X - (nodeRadius + distanceWidth) * deep;
            left.X = cur.X - (nodeRadius + distanceWidth) * len;
            left.Y 
= cur.Y + distanceHeight;
            Draw(parent.LeftNode, left, cur, deep
-1);

            Point right 
= new Point();
            
//right.X = cur.X + (distanceWidth + nodeRadius) * deep + distanceWidth;
            
//right.X = cur.X + (nodeRadius + distanceWidth) * deep;
            right.X = cur.X + (nodeRadius + distanceWidth) * len;
            right.Y 
= cur.Y + distanceHeight;
            Draw(parent.RightNode, right, cur, deep
-1);

            
/* 写字 */
            center.X 
= cur.X - nodeRadius * 9 / 10;
            center.Y 
= cur.Y - nodeRadius * 9 / 10;
            myGraphics.DrawString(parent.data.ToString(), myFont, fontBrush, center);
        }


    }

}




Form_Tree.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace BinaryTree
{
    
public partial class Form_Tree : Form
    
{
        TreeGraph myTreeGraph;

        
public Form_Tree()
        
{
            InitializeComponent();
            myTreeGraph 
= new TreeGraph(this.CreateGraphics());
            comboBox_color.SelectedIndex 
= 0;
        }


        
private void Form_Tree_Shown(object sender, EventArgs e)
        
{
            myTreeGraph.Draw();
        }


        
/** 按钮"上"的事件--增加两个节点之间的高度差 **/
        
private void btn_DisUp_Click(object sender, EventArgs e)
        
{
            myTreeGraph.IncreaseDisH();
            myTreeGraph.Draw();
        }


        
/** 按钮"下"的事件--减少两个节点之间的高度差 **/
        
private void btn_DisDown_Click(object sender, EventArgs e)
        
{
            myTreeGraph.ReduceDisH();
            myTreeGraph.Draw();
        }


        
/** 按钮"左"的事件--减少两个节点之间的宽度差 **/
        
private void btn_DisLeft_Click(object sender, EventArgs e)
        
{
            myTreeGraph.ReduceDisW();
            myTreeGraph.Draw();
        }


        
/** 按钮"右"的事件--增加两个节点之间的宽度差 **/
        
private void btn_DisRight_Click(object sender, EventArgs e)
        
{
            myTreeGraph.IncreaseDisW();
            myTreeGraph.Draw();
        }



        
/** 按钮"+"的事件--增加节点的半径 **/
        
private void btn_Rincrese_Click(object sender, EventArgs e)
        
{
            myTreeGraph.IncreaseRadius();
            myTreeGraph.Draw();
        }


        
/** 按钮"-"的事件--减少节点的半径 **/
        
private void btn_Rdecrese_Click(object sender, EventArgs e)
        
{
            myTreeGraph.ReduceRadius();
            myTreeGraph.Draw();
        }




        
/** 按钮"增加节点"的事件 **/
        
private void btn_addNode_Click(object sender, EventArgs e)
        
{
            
int data = Convert.ToInt32(this.textBox_Key.Text);
            myTreeGraph.AddNode(data);
            myTreeGraph.Draw();
        }


        
/** 按钮删除节点"的事件 **/
        
private void btn_delNode_Click(object sender, EventArgs e)
        
{
            
int data = Convert.ToInt32(this.textBox_Key.Text);
            myTreeGraph.DelNode(data);
            myTreeGraph.Draw();
        }


        
/** 按钮"删除树"的事件 **/
        
private void btn_desTree_Click(object sender, EventArgs e)
        
{
            myTreeGraph.DestoryTree();
            myTreeGraph.Draw();
        }


        
/** 设置颜色 **/
        
private void btn_fontColor_Click(object sender, EventArgs e)
        
{
            colorDialog1.ShowDialog();
            Color myColor 
= colorDialog1.Color;
            
switch (comboBox_color.SelectedIndex)
            
{
                
case 0// 字体
                    myTreeGraph.SetFontColor(myColor);
                    
break;
                
case 1// 圆圈
                    myTreeGraph.SetLineColor(myColor);
                    
break;
                
case 2// 背景
                    myTreeGraph.SetBackColor(myColor);
                    
this.BackColor = myColor;
                    
break;
                
default:
                    
break;
            }

            myTreeGraph.Draw();
        }


    }

}





代码下载

/Files/air8712/BinaryTree.rar