Бинарное дерево windows forms c

Введение

Бинарное дерево — это структура данных, которая состоит из узлов и связей между ними, где каждый узел содержит какое-то значение и две ссылки на его левого и правого потомков. Бинарное дерево может использоваться для решения многих задач, включая поиск, сортировку, и многое другое. В данной статье мы рассмотрим, как создать WindowsForm приложение с функционалом отображения бинарного дерева с помощью языка программирования C#.

Шаги

Шаг 1: Создание элемента управления PictureBox

Первым шагом в создании приложения для отображения бинарного дерева является создание новой WindowsForm. Далее добавляем компонент PictureBox на форму, который будет использоваться для отображения бинарного дерева. Вы можете использовать свойства PictureBox, такие как Width, Height, BorderStyle и т. д., что бы настроить его внешний вид.

Шаг 2: Создание класса узла для бинарного дерева

Создаем класс Node, который представляет собой узел бинарного дерева. Каждый узел содержит значение (число), ссылки на левый и правый потомки, а также конструктор, который позволяет создавать новые узлы.

public class Node
{
  public int Value;
  public Node Left;
  public Node Right;
  
  public Node(int value)
  {
    Value = value;
    Left = null;
    Right = null;
  }
}

Шаг 3: Создание класса для бинарного дерева

Создание класса BinaryTree, который будет содержать ссылку на корневой узел и методы для добавления новых узлов и отображения бинарного дерева на PictureBox.

public class BinaryTree
{
  public Node Root;
  
  public BinaryTree()
  {
    Root = null;
  }
  
  // метод для добавления нового узла
  public void AddNode(int value)
  {
    Node newNode = new Node(value);

    if (Root == null)
    {
      Root = newNode;
      return;
    }
    
    Node current = Root;
    
    while (true)
    {
      if (value < current.Value)
      {
        if (current.Left == null)
        {
          current.Left = newNode;
          return;
        }
        else
        {
          current = current.Left;
        }
      }
      else
      {
        if (current.Right == null)
        {
          current.Right = newNode;
          return;
        }
        else
        {
          current = current.Right;
        }
      }
    }
  }
  
  // метод для отображения бинарного дерева на PictureBox
  public void DrawTree(Graphics graphics, Font font, Brush brush, int x, int y, Node node)
  {
    if (node == null)
    {
      return;
    }
    
    string value = node.Value.ToString();
    
    SizeF size = graphics.MeasureString(value, font);
    
    int px = x - (int)(size.Width / 2);
    int py = y - (int)(size.Height / 2);
    
    Point point = new Point(px, py);
    
    graphics.DrawString(value, font, brush, point);
    
    if (node.Left != null)
    {
      graphics.DrawLine(Pens.Black, x, y, x - 50, y + 50);
      DrawTree(graphics, font, brush, x - 50, y + 50, node.Left);
    }
    
    if (node.Right != null)
    {
      graphics.DrawLine(Pens.Black, x, y, x + 50, y + 50);
      DrawTree(graphics, font, brush, x + 50, y + 50, node.Right);
    }
  }
}

Шаг 4: Связывание элемента управления PictureBox с классом BinaryTree

Теперь необходимо создать экземпляр класса BinaryTree и связать его с элементом управления PictureBox в форме. Добавляем обработчик события Paint для PictureBox, который будет вызваться при отображении формы, и вызываем метод DrawTree, который нарисует бинарное дерево.

public partial class TreeForm : Form
{
  BinaryTree binaryTree;
  
  public TreeForm()
  {
    InitializeComponent();
    
    binaryTree = new BinaryTree();
    
    // добавляем несколько узлов
    binaryTree.AddNode(50);
    binaryTree.AddNode(30);
    binaryTree.AddNode(70);
    binaryTree.AddNode(20);
    binaryTree.AddNode(40);
    binaryTree.AddNode(60);
    binaryTree.AddNode(80);
    
    pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
  }
  
  private void pictureBox1_Paint(object sender, PaintEventArgs e)
  {
    binaryTree.DrawTree(e.Graphics, new Font("Arial", 12), Brushes.Black, 200, 50, binaryTree.Root);
  }
}

Шаг 5: Запуск приложения

Запускаем приложение и убеждаемся, что бинарное дерево успешно отображается на PictureBox.

Заключение

В данной статье мы рассмотрели, как создать WindowsForm приложение с функционалом отображения бинарного дерева с помощью языка программирования C#. Бинарные деревья могут быть использованы для решения многих задач, и благодаря нашему коду, мы можем легко отображать их на форме. Надеюсь, эта статья будет полезной для Вас.

I might translate this later for a quick, working example in C#, but here is a Java homework assignment I did way back in 2000!
enter image description here

You should be able to glean the algorithm and code necessary to draw the Tree based on the Java class:

//    FileName: DrawBinaryTree.java
/************************************
 *     Student: Michael Tomlinson   *
 *      Course: CS 145-Section 1    *
 *  Instructor: Dareleen Schaffer   *
 *                                  *
 *   Assignment #4, Problem #1      *
 *    Due Date: July 24, 2000       *
 ************************************
 */
package BinaryTree;

import java.awt.*;
import javax.swing.*;

public class DrawBinaryTree {

// Data Fields
     private BinaryTree tree=null;
     private double xDiv=50, yDiv=50;
     private boolean sizeToFit=true;
     private Panel outputPanel=null;

// Constructors
     public DrawBinaryTree() {} // default constructor
     public DrawBinaryTree(BinaryTree tree) {
          setBinaryTree(tree);
     } // end constructor with (BinaryTree) parameters
     public DrawBinaryTree(Panel panel) {
          setOutputPanel(panel);
     } // end constructor with (JPanel) parameters
     public DrawBinaryTree(BinaryTree tree, Panel panel) {
          setBinaryTree(tree);
          setOutputPanel(panel);
     } // end constructor with (BinaryTree, JPanel) parameters

// Modifiers
     public void setBinaryTree(BinaryTree tree) {
          this.tree = tree;
     } // end method setBinaryTree

     public void setOutputPanel(Panel panel) {
          this.outputPanel = panel;
     } // end method setOutputPanel

     public void setSizeToFit(boolean sizeToFit) {
          this.sizeToFit = sizeToFit;
     } // end method setSizeToFit

     public void increaseXDiv() {
          xDiv*=1.1;
     } // end method increaseXDiv

     public void increaseYDiv() {
          yDiv*=1.1;
     } // end method increaseYDiv

     public void decreaseXDiv() {
          xDiv*=.9;
     } // end method decreaseXDiv

     public void decreaseYDiv() {
          yDiv*=.9;
     } // end method decreaseyDiv

// Public Methods
     public void drawTree(Point translate) {
          if(outputPanel!=null  && tree!=null) {
               Graphics g = outputPanel.getGraphics();
               g.translate(translate.x, translate.y);
               Dimension panelSize = outputPanel.getSize();
               if(!tree.isEmpty()) {
                    int treeDepth = tree.maxLevel();
                    if(sizeToFit) {
                         xDiv = (double)panelSize.width/(Math.pow(2,treeDepth+1)+1);
                         yDiv = (double)panelSize.height/((double)treeDepth+1);
                    }

                    Point rootCoord = new Point(panelSize.width/2, (int)(yDiv/2));
                    drawTreeNode(rootCoord, tree.getRoot(), 0, g);
               }
               else {
                    Font f = g.getFont();
                    String message = "The Tree is Empty.";
                    FontMetrics fm = g.getFontMetrics(f);
                    int messageLength = fm.stringWidth(message);
                    int messageHeight = fm.getHeight();
                    g.drawString(message, panelSize.width/2 - messageLength/2,
                         panelSize.height/2 - messageHeight/2);

               }
               g.dispose();
          }
     } // end method drawTree

// Private Methods
     private void drawTreeNode(Point coord, SearchTreeNode node, int depth,
               Graphics g) {
          double xOffset = (Math.pow(2, tree.maxLevel() - depth)/2)*xDiv;
          int newY =(int)(((double)depth+1)*yDiv+yDiv/2.0);
          if(node.leftChild!=null) {
               int lcx = (int)(coord.x - xOffset);
               g.setColor(Color.blue);
               g.drawLine(coord.x, coord.y, lcx, newY);
               Point leftChildCoord = new Point(lcx, newY);
               drawTreeNode(leftChildCoord, node.leftChild, (depth + 1), g);
          }
          if(node.rightChild!=null) {
               int rcx = (int)(coord.x + xOffset);
               g.setColor(Color.red);
               g.drawLine(coord.x, coord.y, rcx, newY);
               Point rightChildCoord = new Point(rcx, newY);
               drawTreeNode(rightChildCoord, node.rightChild, (depth + 1), g);
          }
          g.setColor(Color.black);
          g.drawOval(coord.x-5, coord.y-5, 10, 10);
          g.fillOval(coord.x-5, coord.y-5, 10, 10);
          g.drawString(node.item.toString(), coord.x+10, coord.y+5);
     } // end method drawTreeNode

} // end class DrawBinary Tree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
 
namespace Курсовая_Вар_16
{
    class Verhina
    {
        //параметры дерева
        const int R = 20;
        int n;
        Verhina left;
        Verhina right;
        Color color;
        //типо конструктор
        public Verhina(int n)
        {
            this.n = n;
            left = right = null;
            color = Color.White;
        }
        //добавляем вершины
        internal void DobavimVershinu(int n)
        {
            if (n == this.n)
            {
                MessageBox.Show("Такая вершина уже есть!",
                "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (n < this.n)
            {
                if (left == null)
                    left = new Verhina(n);
                else
                    left.DobavimVershinu(n);
            }
            else
            {
                if (right == null)
                    right = new Verhina(n);
                else
                    right.DobavimVershinu(n);
            }
        }
        //далее идет рисование кружочков и стрелочек на форме
        internal void Risovat(Graphics g, int x1, int x2, int y, int dy)
        {
            int x = (x1 + x2) / 2;
 
            if (left != null)
            {
                g.DrawLine(Pens.Blue, x, y, x - (x2 - x1) / 4, y+ dy);
            }
            if (right != null)
            {
                g.DrawLine(Pens.Blue, x, y, x + (x2 - x1) / 4, y+ dy);
            }
            g.FillEllipse(new SolidBrush(color), x - R, y - R, 2* R, 2 * R);
            g.DrawEllipse(Pens.Black, x - R, y - R, 2 * R, 2 *
            R);
            g.DrawString(n.ToString(), new Font("Calibri", 14),Brushes.Red, x - 12, y - 10);
 
            if (left != null)
            {
                left.Risovat(g, x1, x, y + dy, dy);
            }
            if (right != null)
            {
                right.Risovat(g, x, x2, y + dy, dy);
            }
        }
        public int Search(int vSh, int x1, int x2, int y, int dy)
        {
            Graphics g;
              
            int count = 0;
            if (n % vSh == 0)
                count += 1;
 
            if (n % vSh == 0)
            {
                if (left != null)
                    g.FillEllipse(new SolidBrush(Color.Blue), x1 - R, y - R, 2 * R, 2 * R);
                    count += left.Search(vSh , x1, x2, y, dy);
                
 
                if (right != null)
                    g.FillEllipse(new SolidBrush(Color.Blue), x1 - R, y - R, 2 * R, 2 * R);
                    count += right.Search(vSh, x1, x2,  y, dy);
                
            }
            else
            {
                if (left != null) 
                    g.FillEllipse(new SolidBrush(Color.Blue), x1 - R, y - R, 2 * R, 2 * R);
                    count += left.Search(vSh, x1, x2,  y,  dy);
               
                if (right != null)         
                    g.FillEllipse(new SolidBrush(Color.Blue), x1 - R, y - R, 2 * R, 2 * R);
                    count += right.Search(vSh,   x1,  x2, y,  dy);
 
            }
 
            return  count ;
        }
 
        //вот далее идет магия и я хз как это работает
       internal Verhina PoiskVeshiny(int xm, int ym, int x1, int x2, int y, int dy)
        {
            int x = (x1 + x2) / 2;
            int rasst = (int)Math.Sqrt((xm - x) * (xm - x) + (ym - y) * (ym - y));
            if (rasst <= R)
            {
                return this;
            }
            if (xm < x)
            {
                if (left == null)
                    return null;
                else
                    return left.PoiskVeshiny(xm, ym, x1, x, y + dy, dy);
            }
            else
            {
                if (right == null)
                    return null;
                else
                    return right.PoiskVeshiny(xm, ym, x, x2, y + dy, dy);
            }
        }
        internal void SetColor(Color color)
        {
            this.color = color;
        }
 
        internal int GetN()
        {
            return n;
        }
    }
        
    class Tree
    {
        Verhina koren;
        public Tree()
        {
            koren = null;
        }
        internal void DobavimVershinu(int n)
        {
            if (koren == null)
                koren = new Verhina(n);
            else
                koren.DobavimVershinu(n);
        }
        internal void Risovat(Graphics g, int x1, int x2, int y0, int dy)
        {
            if (koren == null)
                return;
 
            koren.Risovat(g, x1, x2, y0, dy);
        }
        
    }
}

Необходимо создать двоичное дерево поиска, а затем скопировать дерево и отобразить в TreeView.
метод создания дерева

public DTreeNode Created(DTreeNode root,char temp, int nums) //temp - information field.nums - key
   {
        if (root == null)
        {
            root = new DTreeNode(temp, nums);
            root.Left = null;
            root.Right = null;
        }
        else
        {
            if (nums < root.Key)
            {
                root.Left = Created(root.Left, temp, nums);
            }
            else
            {
                root.Right = Created(root.Right, temp, nums);
            }
        }
        return root;
    }

Методы вывода дерева в TreeView

public void Show(TreeView tree, DTreeNode root)
    {
        tree.Nodes.Clear();
        if (root != null)
        {
            tree.Nodes.Add(root.Info + "  (" + root.Key + ")");
            KLP(tree.Nodes[0], root.Left);
            KLP(tree.Nodes[0], root.Right);
        }
    }
    public void KLP(TreeNode node, DTreeNode place)
    {
        if (place != null)
        {
            TreeNode branch = node.Nodes.Add(place.Info + "  (" + place.Key + ")");
            KLP(branch, place.Left);
            KLP(branch, place.Right);
        }
    }

Но как скопировать двоичное дерево поиска и отобразить его в TreeView, я не знаю. Пожалуйста, помогите. Я не могу сделать это уже 5 дней. Вся работа выполняется в Windows Forms.

Последнее обновление: 31.10.2015

TreeView представляет визуальный элемент в виде дерева. Дерево содержит узлы, которые представляют объекты TreeNode.
Узлы могут содержать другие подузлы и могут находиться как скрытом, так и в раскрытом состоянии. Все узлы содержатся в свойстве Nodes.

Если мы нажем в панели Свойств на свойство Nodes, то нам откроется окно редактирования узлов TreeView:

TreeNode в Windows Forms

В этом окне мы можем добавить новые узлы, создать для них подузлы, удалить уже имеющиеся, настроить свойства узлов. Рассмотрим некоторые свойства, которые
мы здесь может установить:

  • BackColor: фоновый цвет узла

  • Checked: если равно true, то данный узел будет отмечен флажком

  • NodeFont: шрифт узла

  • ForeColor: цвет шрифта

  • Text: текст узла

  • ImageIndex: получает или задает индекс изображения, выводимого для данного узла

  • ImageKey: получает или задает индекс изображения для данного узла

  • SelectedImageKey: получает или задает индекс изображения для данного узла в выбранном состоянии

  • SelectedImageIndex: получает или задает индекс изображения, выводимого для данного узла в выбранном состоянии

  • StateImageIndex: получает или задает индекс изображения состояния (например установленного или снятого флажка,
    указывающего состояние элемента)

  • Tag: тег узла

И затем все добавленные узлы мы сможем увидеть в приложении на форме:

Элемент TreeView в Windows Forms

Кроме данных свойств, управляющих визуализацией, элемент TreeNode имеет еще ряд важных свойств, которые мы можем использовать к коде:

  • FirstNode: первый дочерний узел

  • LastNode: последний дочерний узел

  • NextNode: возвращает следующий сестринский узел по отношению к текущему

  • NextVisibleNode: возвращает следующий видимый узел по отношению к текущему

  • PrevNode: возвращает предыдущий сестринский узел по отношению к текущему

  • PrevVisibleNode: возвращает предыдущий видимый узел по отношению к текущему

  • Nodes: возвращает коллекцию дочерних узлов

  • Parent: возвращает родительский узел для текущего узла

  • TreeView: возвращает объект TreeView, в котором определен текущий узел

Программное управление узлами

Рассмотрим программное добавление и удаление узлов:

TreeNode tovarNode = new TreeNode("Товары");
// Добавляем новый дочерний узел к tovarNode
tovarNode.Nodes.Add(new TreeNode("Смартфоны"));
// Добавляем tovarNode вместе с дочерними узлами в TreeView
treeView1.Nodes.Add(tovarNode);
// Добавляем второй очерний узел к первому узлу в TreeView
treeView1.Nodes[0].Nodes.Add(new TreeNode("Планшеты"));
// удаление у первого узла второго дочернего подузла
treeView1.Nodes[0].Nodes.RemoveAt(1);
// Удаление узла tovarNode и всех его дочерних узлов
treeView1.Nodes.Remove(tovarNode);

Скрытие и раскрытие узлов

Для раскрытия узлов к объекту TreeNode применяется метод Expand(), а для скрытия — метод Collapse():

// раскрытие узла
tovarNode.Expand();
// раскрытие не только узла, но и всех его дочерних подузлов
tovarNode.ExpandAll();
// скрытие узла
tovarNode.Collapse();

Добавление чекбоксов

Чтобы добавить чекбоксы к узлам дерева, надо у TreeView установить свойство CheckBoxes = true:

treeView1.CheckBoxes = true;
TreeNode smartNode = new TreeNode("Смартфоны");
smartNode.Checked = true;
treeView1.Nodes.Add(smartNode);

treeView1.Nodes.Add(new TreeNode("Планшеты"));
treeView1.Nodes.Add(new TreeNode("Ноутбуки"));

Добавление изображений

Для добавления изображений нам нужен компонент ImageList, в котором имеется несколько картинок. Добавим эти картинки к узлам:

// установка источника изображений
treeView1.ImageList = imageList1;

TreeNode argentinaNode = new TreeNode { Text = "Аргентина", ImageIndex=0, SelectedImageIndex=0 };
treeView1.Nodes.Add(argentinaNode);

TreeNode braziliaNode = new TreeNode { Text = "Бразилия", ImageIndex = 1, SelectedImageIndex=1 };
treeView1.Nodes.Add(braziliaNode);

TreeNode chilieNode = new TreeNode { Text = "Чили", ImageIndex = 2, SelectedImageIndex=2 };
treeView1.Nodes.Add(chilieNode);

TreeNode columbiaNode = new TreeNode { Text = "Колумбия", ImageIndex = 3, SelectedImageIndex=3 };
treeView1.Nodes.Add(columbiaNode);

При установке изображений надо учитывать, что если мы не установим свойство SelectedImageIndex для каждого узла,
то в качестве картинки для выделенного узла по умолчанию будет использоваться первое изображение из ImageList.

TreeView. Практический пример

Выполним небольшую задачу с TreeView. А именно попробуем сделать примитивный интерфейс на подобие проводника. Для этого добавим
на форму элемент TreeView. А в файле кода формы пропишим следующий код:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;

namespace HelloApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            treeView1.BeforeSelect += treeView1_BeforeSelect;
            treeView1.BeforeExpand += treeView1_BeforeExpand;
			// заполняем дерево дисками
            FillDriveNodes();
        }
		// событие перед раскрытием узла
        void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            e.Node.Nodes.Clear();
            string[] dirs;
            try
            {
                if (Directory.Exists(e.Node.FullPath))
                {
                    dirs = Directory.GetDirectories(e.Node.FullPath);
                    if (dirs.Length != 0)
                    {
                        for (int i = 0; i < dirs.Length; i++)
                        {
                            TreeNode dirNode = new TreeNode(new DirectoryInfo(dirs[i]).Name);
                            FillTreeNode(dirNode, dirs[i]);
                            e.Node.Nodes.Add(dirNode);
                        }
                    }
                }
            }
            catch (Exception ex) { }
        }
		// событие перед выделением узла
        void treeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {
            e.Node.Nodes.Clear();
            string[] dirs;
            try
            {
                if(Directory.Exists(e.Node.FullPath))
                {
                    dirs = Directory.GetDirectories(e.Node.FullPath);
                    if (dirs.Length!= 0)
                    {
                        for(int i=0; i<dirs.Length;i++)
                        {
                            TreeNode dirNode = new TreeNode(new DirectoryInfo(dirs[i]).Name);
                            FillTreeNode(dirNode, dirs[i]);
                            e.Node.Nodes.Add(dirNode);
                        }
                    }
                } 
            }
            catch (Exception ex) { }
        }
		
		// получаем все диски на компьютере
        private void FillDriveNodes()
        {
            try
            {
                foreach(DriveInfo drive in DriveInfo.GetDrives())
                {
                    TreeNode driveNode = new TreeNode { Text = drive.Name };
                    FillTreeNode(driveNode, drive.Name);
                    treeView1.Nodes.Add(driveNode);
                }
            }
            catch (Exception ex) { }
        }
		// получаем дочерние узлы для определенного узла
        private void FillTreeNode(TreeNode driveNode, string path)
        {
            try
            {
                string[] dirs = Directory.GetDirectories(path);
                foreach (string dir in dirs)
                {
                    TreeNode dirNode = new TreeNode();
                    dirNode.Text = dir.Remove(0, dir.LastIndexOf("\\") + 1);
                    driveNode.Nodes.Add(dirNode);
                }
            }
            catch (Exception ex) { }
        }
    }
}

Проводник в Windows Forms на основе TreeView

TreeView имеет ряд событий, которые позволяют нам управлять деревом. Наиболее важные из них:

  • BeforeSelect / AfterSelect: срабатывает перед / после выбора узла дерева

  • BeforeExpand / AfterExpand: срабатывает перед / после раскрытия узла дерева

  • BeforeCollapse / AfterCollapse: срабатывает перед / после скрытия узла дерева

В вышеприведенном коде мы заблаговременно перед раскрытием или выбором наполняем выбранный узел дочерними подузлами,
благодаря чему у нас появляется видимость, что узлы заполнены.

  • Бильярд братья пилоты скачать для windows 10
  • Битлокер windows 10 как разблокировать
  • Биос видит флешку но не грузится с нее windows 10
  • Беспроводной дисплей windows 10 как работает
  • Биг бейби тейп кизару windows