Постановка задачи:
Реализация работы со справочником предметной области “Магазин”( с ключами Артикул, Наименование товара, ИНН поставщика,  Дата) с использованием структур данных АВЛ-дерево (по нему распределяем по ключу Наименование товара), состоящее из хеш-таблиц (по ним распределяем по ключу Дата).
Общие требования:
Оконный интерфейс (среда разработки WinForms)
Нельзя использовать универсальные классы-коллекции в System.Collections для реализации заданных структур данных
В интерфейсе отображать справочник в табличном виде и окно отладки для вывода структур данных
Какой должен быть функционал: 
Возможность задания в интерфейсе первоначального размера ХТ
Работа со справочником:
- загрузка из текстового файла / сохранение в текстовый файл
- добавление
- удаление
- поиск
- просмотр
Окно отладки (печать структур данных)
Форма использует файлы Kursovaya.cpp, MyForm.h и MyForm.cpp.
Код Kursovaya.cpp:
#include <iostream>
#include <vector>
#include <istream>
#include <fstream>
#include <list>
#include <cstring>
using namespace std;

struct VendorCode
{
    int vendorcode;

    VendorCode(int vc) : vendorcode(vc) {}
};
struct ProductName {
    std::string productname;

    ProductName(std::string pn) : productname(pn) {}
};
struct TIN
{
    long long int tin;

    TIN(long long int t) {
        long long int n = t;
        int c = 0;
        while (n != 0)
        {
            c++;
            n /= 10;
        }
        if (c == 12)
        {
            tin = t;
        }
        else
        {
            std::cerr << "Invalid TIN. Setting default TIN to 100000000000" << std::endl;
            tin = 100000000000;
        }
    }
};
struct Date {
    int day;
    int month;
    int year;

    Date(int d, int m, int y) {
        bool correct = true;
        if (y > 2024 || y < 1900)
            correct = false;
        else
        {
            switch (m)
            {
            case 1: case 3: case 5: case 7: case 8: case 10: case 12:
                if (d < 1 || d > 31)
                    correct = false;
                break;
            case 4: case 6: case 9: case 11:
                if (d < 1 || d > 30)
                    correct = false;
                break;
            case 2:
                if (d < 1 || d > 28)
                    correct = false;
                break;
            default:
                correct = false;
                break;
            }
        }
        if (correct)
        {
            day = d;
            month = m;
            year = y;
        }
        else
        {
            std::cerr << "Invalid date. Setting default date to 1.1.2000." << std::endl;
            day = 1;
            month = 1;
            year = 2000;
        }
    }
};
struct Sorts {
    VendorCode vendorcodes;
    ProductName productnames;
    TIN tins;
    Date dates;
    int firstHash;
    Sorts(const VendorCode& vc, const ProductName& pn, const TIN& t, const Date& d) : vendorcodes(vc), productnames(pn), tins(t), dates(d), firstHash(0) {}
};
struct Cell {
    Sorts sorts;
    int flag;
    int firstHash;
    Cell() : sorts(VendorCode(0), ProductName(""), TIN(100000000000), Date(1, 1, 2000)), flag(0), firstHash(0) {}
};
class HashTable
{
private:
    std::vector <Cell> table;
    std::vector<Sorts> readFromFile(const std::string& filename) {
        std::vector<Sorts> sorts;
        std::ifstream file(filename);

        if (file.is_open()) {
            int vc;
            std::string pn;
            int t;
            int day;
            int month;
            int year;


            while (file >> vc >> pn >> t >> day >> month >> year) {
                VendorCode vendorcode(vc);
                ProductName productname(pn);
                TIN tin(t);
                Date date(day, month, year);

                sorts.push_back(Sorts(vendorcode, productname, tin, date));
            }

            file.close();
        }
        else {
            std::cerr << "Enable open file" << filename << std::endl;
        }

        return sorts;
    }
    int digitsCount(int n)
    {
        int c = 0;
        while (n != 0)
        {
            c++;
            n /= 10;
        }
        return c;
    }
    int hash1(int key1, int key2, int key3, int n)
    {
        int d = digitsCount(n - 1);

        int l = digitsCount(key1);
        int e = (2 * l - d) / 2;
        int r = pow(10, e);
        int h1 = (key1 * key1) / r;
        int mod = pow(10, d);
        h1 %= mod;

        l = digitsCount(key2);
        e = (2 * l - d) / 2;
        r = pow(10, e);
        int h2 = (key2 * key2) / r;
        mod = pow(10, d);
        h2 %= mod;

        l = digitsCount(key3);
        e = (2 * l - d) / 2;
        r = pow(10, e);
        int h3 = (key3 * key3) / r;
        mod = pow(10, d);
        h3 %= mod;

        int h = (h1 + h2 + h3) % n;
        return h;
    }
    int hash2(int key1, int key2, int key3, int j, int k, int n)
    {
        int hash = (hash1(key1, key2, key3, n) + j * k) % n;

        return hash;
    }
    int collisionInsert(int key1, int key2, int key3, int n, int hash)
    {
        int h = hash;
        int j = 0;
        int k = 3;
        do
        {
            if (table[h].sorts.dates.day == key1 && table[h].sorts.dates.month == key2 && table[h].sorts.dates.year == key3)
                return -2;
            if (table[h].flag != 1)
            {
                return h;
            }
            else
            {
                h = hash2(key1, key2, key3, j, k, n);
                ++j;
            }
        } while (j != n);
        return -1;
    }
    int collisionSearch(int key1, int key2, int key3, int n, int hash)
    {
        int h = hash;
        int j = 0;
        int k = 3;
        do
        {
            if (table[h].sorts.dates.day == key1 && table[h].sorts.dates.month == key2 && table[h].sorts.dates.year == key3)
            {
                return h;
            }
            else
            {
                h = hash2(key1, key2, key3, j, k, n);
                ++j;
            }
        } while (j != n);
        return -1;
    }
public:
    bool isEmpty()
    {
        for (int i = 0; i < table.size(); i++)
        {
            if (table[i].flag == 1)
                return false;
        }
        return true;
    }
    int insertItem(Sorts s)
    {
        int n = table.size();
        int key1 = s.dates.day;
        int key2 = s.dates.month;
        int key3 = s.dates.year;
        int hash = hash1(key1, key2, key3, n);
        s.firstHash = hash;
        if (table[hash].flag != 1)
        {
            table[hash].sorts = s;
            table[hash].firstHash = s.firstHash;
            table[hash].flag = 1;
            return 0;
        }
        else
        {
            int secondhash = collisionInsert(key1, key2, key3, n, hash);
            if (secondhash == -2)
            {
                std::cout << "Item is already in the table." << std::endl;
                return -2;
            }
            else if (secondhash == -1)
            {
                std::cout << "Can't insert, table is full." << std::endl;
                return -1;
            }
            else
            {
                for (int i = 0; i < table.size(); i++)
                {
                    if (table[i].sorts.dates.day == key1 && table[i].sorts.dates.month == key2 && table[i].sorts.dates.year == key3)
                        return -2;
                }
                table[secondhash].sorts = s;
                table[secondhash].firstHash = s.firstHash;
                table[secondhash].flag = 1;
                return 1;
            }
        }
    }
    int removeItem(int key1, int key2, int key3)
    {
        int n = table.size();
        int hash = hash1(key1, key2, key3, n);
        if (table[hash].sorts.dates.day == key1 && table[hash].sorts.dates.month == key2 && table[hash].sorts.dates.year == key3)
        {
            table[hash].flag = 2;
            std::cout << "Removed" << std::endl;
            return 0;
        }
        else
        {
            int secondhash = collisionSearch(key1, key2, key3, n, hash);
            if (secondhash != -1)
            {
                if (table[secondhash].flag == 1)
                {
                    table[secondhash].flag = 2;
                    std::cout << "Removed" << std::endl;
                    return 1;
                }
            }
            std::cout << "Item is not in the table." << std::endl;
            return -1;
        }
    }
    HashTable(const std::string readFile, int n)
    {
        table.resize(n);
        std::vector <Sorts> sorts = readFromFile(readFile);

        for (int i = 0; i < n; i++)
        {
            if (i < sorts.size())
                insertItem(sorts[i]);
        }
    }
    HashTable()
    {

    }
    void changeSize(int hashtablesize)
    {
        table.resize(hashtablesize);
    }
    ~HashTable()
    {
        table.clear();
    }
    int searchItem(int key1, int key2, int key3, int searchsteps)
    {
        int n = table.size();
        int hash = hash1(key1, key2, key3, n);
        searchsteps++;
        if (table[hash].flag == 1 && table[hash].sorts.dates.day == key1 && table[hash].sorts.dates.month == key2 && table[hash].sorts.dates.year == key3)
        {
            std::cout << "Found: " << hash << " | " << table[hash].sorts.vendorcodes.vendorcode << " " << table[hash].sorts.productnames.productname << " " << table[hash].sorts.tins.tin << " " << table[hash].sorts.dates.day << "." << table[hash].sorts.dates.month << "." << table[hash].sorts.dates.year << " | first hash: " << table[hash].firstHash << " | flag: " << table[hash].flag << std::endl;
            return searchsteps;
        }
        else
        {
            searchsteps++;
            int secondhash = collisionSearch(key1, key2, key3, n, hash);
            if (secondhash != -1)
            {
                if (table[secondhash].flag == 1)
                {
                    std::cout << "Found: " << hash << " | " << table[hash].sorts.vendorcodes.vendorcode << " " << table[hash].sorts.productnames.productname << " " << table[hash].sorts.tins.tin << " " << table[hash].sorts.dates.day << "." << table[hash].sorts.dates.month << "." << table[hash].sorts.dates.year << " | first hash: " << table[hash].firstHash << " | flag: " << table[hash].flag << std::endl;
                    return searchsteps;
                }
            }
            std::cout << "Item is not in the table." << std::endl;
            return -1;
        }
    }
    void printTable(std::string key)
    {
        std::cout << key << ": " << std::endl;
        for (int i = 0; i < table.size(); i++)
        {
            if (table[i].flag != 1)
                std::cout << i << " | flag: " << table[i].flag << std::endl;
            else
                std::cout << i << " | " << table[i].sorts.vendorcodes.vendorcode << " " << table[i].sorts.productnames.productname << " " << table[i].sorts.tins.tin << " " << table[i].sorts.dates.day << "." << table[i].sorts.dates.month << "." << table[i].sorts.dates.year << " | first hash: " << table[i].firstHash << " | flag: " << table[i].flag << std::endl;
        }
        std::cout << std::endl;

    }
    void writeFile(std::ofstream& out, std::string key)
    {
        out << key << ": " << std::endl;
        for (int i = 0; i < table.size(); i++)
        {
            if (table[i].flag != 1)
                out << i << " | flag: " << table[i].flag << std::endl;
            else
                out << i << " | " << table[i].sorts.vendorcodes.vendorcode << " " << table[i].sorts.productnames.productname << " " << table[i].sorts.tins.tin << " " << table[i].sorts.dates.day << "." << table[i].sorts.dates.month << "." << table[i].sorts.dates.year << " | first hash: " << table[i].firstHash << " | flag: " << table[i].flag << std::endl;
        }
        out << std::endl;
    }
};

struct Node
{
    std::string key;
    HashTable ht;
    Node* left;
    Node* right;
    int balance;
};

class Tree
{
private:
    Node* root = NULL;
    int hashTableSize = 10;
    std::vector<Sorts> readFromFile(const std::string& filename) {
        std::vector<Sorts> sorts;
        std::ifstream file(filename);

        if (file.is_open()) {
            int vc;
            std::string pn;
            long long int t;
            int day;
            int month;
            int year;


            while (file >> vc >> pn >> t >> day >> month >> year) {
                VendorCode vendorcode(vc);
                ProductName productname(pn);
                TIN tin(t);
                Date date(day, month, year);

                sorts.push_back(Sorts(vendorcode, productname, tin, date));
            }

            file.close();
        }
        else {
            std::cerr << "Enable open file" << filename << std::endl;
        }

        return sorts;
    }
    void add(int vc, std::string pn, long long int t, int d, int m, int y, Node*& p, bool& h) // поиск и добавление элемента
    {
        VendorCode vendorcode(vc);
        ProductName productname(pn);
        TIN tin(t);
        Date date(d, m, y);
        Sorts s(vendorcode, productname, tin, date);
        if (p == NULL) // слова нет в дереве; включить его
        {
            p = new Node;
            h = true;
            p->key = s.productnames.productname;
            p->ht.changeSize(hashTableSize);
            p->ht.insertItem(s);
            p->balance = 0;
            p->left = NULL;
            p->right = NULL;
        }
        else if (pn < p->key)
        {
            add(vc, pn, t, d, m, y, p->left, h);
            if (h) // выросла левая ветвь
            {
                switch (p->balance)
                {
                case 1:
                    p->balance = 0;
                    h = false;
                    break;
                case 0:
                    p->balance = -1;
                    break;
                case -1: // балансировка
                    Node * p1 = p->left;
                    if (p1->balance == -1) // L-поворот
                    {
                        p->left = p1->right;
                        p1->right = p;
                        p->balance = 0;
                        p = p1;
                    }
                    else // LR-поворот
                    {
                        Node* p2 = p1->right;
                        p1->right = p2->left;
                        p2->left = p1;
                        p->left = p2->right;
                        p2->right = p;
                        if (p2->balance == -1)
                            p->balance = 1;
                        else
                            p->balance = 0;
                        if (p2->balance == 1)
                            p1->balance = -1;
                        else
                            p1->balance = 0;
                        p = p2;
                    }
                    p->balance = 0;
                    h = false;
                    break;
                }
            }
        }
        else if (pn > p->key)
        {
            add(vc, pn, t, d, m, y, p->right, h);
            if (h == true) // выросла правая ветвь
            {
                switch (p->balance)
                {
                case -1:
                    p->balance = 0;
                    h = false;
                    break;
                case 0:
                    p->balance = 1;
                    break;
                case 1: // балансировка
                    Node * p1 = p->right;
                    if (p1->balance == 1) //R-поворот
                    {
                        p->right = p1->left;
                        p1->left = p;
                        p->balance = 0;
                        p = p1;
                    }
                    else // RL-поворот
                    {
                        Node* p2 = p1->left;
                        p1->left = p2->right;
                        p2->right = p1;
                        p->right = p2->left;
                        p2->left = p;
                        if (p2->balance == 1)
                            p->balance = -1;
                        else
                            p->balance = 0;
                        if (p2->balance == -1)
                            p1->balance = 1;
                        else
                            p1->balance = 0;
                        p = p2;
                    }
                    p->balance = 0;
                    h = false;
                    break;
                }
            }
        }
        else
        {
            p->ht.insertItem(s);
            h = false;
        }
    }
    void balance1(Node* p, bool& h)
    {
        Node* p1, * p2;
        short b1, b2;
        if (p == NULL)
            return;
        switch (p->balance)
        {
        case -1:
            p->balance = 0;
            break;
        case 0:
            p->balance = 1;
            h = true;
            break;
        case 1: // балансировка
            p1 = p->right;
            b1 = p1->balance;
            if (b1 >= 0) // R-поворот
            {
                p->right = p1->left;
                p1->left = p;
                if (b1 == 0)
                {
                    p->balance = 1;
                    p1->balance = -1;
                    h = false;
                }
                else
                {
                    p->balance = 0;
                    p1->balance = 0;
                }
                p = p1;
            }
            else // RL-поворот
            {
                p2 = p1->left;
                b2 = p2->balance;
                p1->left = p2->right;
                p2->right = p1;
                p->right = p2->left;
                p2->left = p;
                if (b2 == 1)
                    p->balance = -1;
                else
                    p->balance = 0;
                if (b2 == -1)
                    p1->balance = 1;
                else
                    p1->balance = 0;
                p = p2;
                p2->balance = 0;
            }
        }
    }
    void balance2(Node* p, bool& h)
    {
        Node* p1, * p2;
        short b1, b2;
        switch (p->balance)
        {
        case 1:
            p->balance = 0;
            break;
        case 0:
            p->balance = -1;
            h = true;
            break;
        case -1:
            p1 = p->left;
            b1 = p1->balance;
            if (b1 <= 0) // L-поворот
            {
                p->left = p1->right;
                p1->right = p;
                if (b1 == 0)
                {
                    p->balance = -1;
                    p1->balance = 1;
                    h = false;
                }
                else
                {
                    p->balance = 0;
                    p1->balance = 0;
                }
                p = p1;
            }
            else // LR-поворот
            {
                p2 = p1->right;
                b2 = p2->balance;
                p1->right = p2->left;
                p2->left = p1;
                p->left = p2->right;
                p2->right = p;
                if (b2 == -1)
                    p->balance = 1;
                else
                    p->balance = 0;
                if (b2 == 1)
                    p1->balance = -1;
                else
                    p1->balance = 0;
                p = p2;
                p2->balance = 0;
            }
        }
    }

    void delet(std::string pn, int d, int m, int y, Node*& p, bool& h) // удаление элемента, выше вспомогательные подпрограммы
    {
        Node* q;
        if (p == NULL)
        {
            h = false;
        }
        else if (pn < p->key)
        {
            delet(pn, d, m, y, p->left, h);
            if (h)
                balance1(p, h); // вызов функции балансировки
        }
        else if (pn > p->key)
        {
            delet(pn, d, m, y, p->right, h);
            if (h)
                balance2(p, h);
        }
        else
        {
            if (p->left == NULL && p->right == NULL)
            {
                p->ht.removeItem(d, m, y);
                if (p->ht.isEmpty())
                {
                    delete p;
                    p = NULL;
                    h = true;
                }
            }
            else if (p->left != NULL && p->right == NULL)
            {
                p->ht.removeItem(d, m, y);
                if (p->ht.isEmpty())
                {
                    Node* temp = p->left;
                    delete p;
                    p = temp;
                    h = true;
                }
            }
            else if (p->left == NULL && p->right != NULL)
            {
                p->ht.removeItem(d, m, y);
                if (p->ht.isEmpty())
                {
                    Node* temp = p->right;
                    delete p;
                    p = temp;
                    h = true;
                }
            }
            else
            {
                p->ht.removeItem(d, m, y);
                if (p->ht.isEmpty())
                {
                    Node* temp = p->left;
                    Node* parent = p;
                    while (temp->right != NULL)
                    {
                        parent = temp;
                        temp = temp->right;
                    }
                    if (parent != p)
                        parent->right = temp->left;
                    else
                        parent->left = temp->left;
                    p->key = temp->key;
                    p->ht = temp->ht;
                    delete temp;
                    h = true;
                }
            }

            if (h)
                balance1(p, h); // вызов функции балансировки
        }
    }
    void print(Node* t, short hh) // печать дерева
    {
        if (t != NULL)
        {
            print(t->right, hh + 1);
            for (int i = 1; i <= hh; i++)
                cout << "   ";
            t->ht.printTable(t->key);
            std::cout << std::endl;
            print(t->left, hh + 1);
        }
    }
    void walk(Node* t, short hh, std::ofstream& out) // обход дерева справа налево и вывод в файл
    {
        if (t != NULL)
        {
            walk(t->right, hh + 1, out);
            t->ht.writeFile(out, t->key);
            walk(t->left, hh + 1, out);
        }
    }
    void search(std::string pn, int d, int m, int y, Node*& p, bool& h, int searchsteps) // поиск элемента
    {
        Node* q;
        if (p == NULL)
        {
            cout << "Haven't found." << endl;
            h = false;
        }
        else if (pn < p->key)
        {
            searchsteps++;
            search(pn, d, m, y, p->left, h, searchsteps);
        }
        else if (pn > p->key)
        {
            searchsteps++;
            search(pn, d, m, y, p->right, h, searchsteps);
        }
        else
        {
            searchsteps = p->ht.searchItem(d, m, y, searchsteps);
            if (searchsteps == -1)
                std::cout << "Haven't found." << std::endl;
            else
                std::cout << "Found in " << searchsteps << " steps." << std::endl;
            h = false;
        }
    }
    int getSizeHelper(Node* p)
    {
        if (p == NULL) {
            return 0;
        }
        else {
            return 1 + getSizeHelper(p->left) + getSizeHelper(p->right);
        }
    }
public:
    int getSize()
    {
        return getSizeHelper(root);
    }
    void setHashTableSize(int size)
    {
        hashTableSize = size;
    }

    bool isEmpty()
    {
        if (root == NULL)
            return true;
        else
            return false;
    }

    void addItem(int vc, std::string pn, long long int t, int d, int m, int y)
    {
        bool h = false;
        add(vc, pn, t, d, m, y, root, h);
    }

    void removeItem(std::string pn, int d, int m, int y)
    {
        bool h = false;
        delet(pn, d, m, y, root, h);
    }

    void searchItem(std::string pn, int d, int m, int y)
    {
        bool h = false;
        search(pn, d, m, y, root, h, 0);
    }

    void printTree()
    {
        print(root, 0);
    }

    void writeFile(std::string file)
    {
        std::ofstream out(file);
        walk(root, 0, out);
    }

    Tree(){}
    void readFile(const std::string readFile, int n)
    {
        std::vector <Sorts> sorts = readFromFile(readFile);

        for (int i = 0; i < n; i++)
        {
            if (i < sorts.size())
                addItem(sorts[i].vendorcodes.vendorcode, sorts[i].productnames.productname, sorts[i].tins.tin, sorts[i].dates.day, sorts[i].dates.month, sorts[i].dates.year);
        }
    }
};
Код MyForm.h:
#pragma once
#include"Kursovaya.cpp"

namespace KursovayaCLR {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	/// <summary>
	/// Сводка для MyForm
	/// </summary>
	public ref class MyForm : public System::Windows::Forms::Form
	{
	public:
		MyForm(void)
		{
			InitializeComponent();
			//
			//TODO: добавьте код конструктора
			//
			tree = new Tree();
		}

	protected:
		/// <summary>
		/// Освободить все используемые ресурсы.
		/// </summary>
		~MyForm()
		{
			if (components)
			{
				delete components;
				delete tree;
			}
		}
	private: System::Windows::Forms::Button^ btnAdd;
	protected:
	private: System::Windows::Forms::Button^ btnRemove;
	private: System::Windows::Forms::TextBox^ textBoxHTSize;
	private: System::Windows::Forms::Label^ HTsize;
	private: System::Windows::Forms::Button^ LoadFile;
	private: System::Windows::Forms::Button^ SaveFile;
	


	protected:

	protected:

	private:
		/// <summary>
		/// Обязательная переменная конструктора.
		/// </summary>
		System::ComponentModel::Container ^components;
	private: System::Windows::Forms::DataGridView^ dataGridView1;
	private: System::Windows::Forms::DataGridViewTextBoxColumn^ ProductName;
		   Tree* tree;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// Требуемый метод для поддержки конструктора — не изменяйте 
		/// содержимое этого метода с помощью редактора кода.
		/// </summary>
		void InitializeComponent(void)
		{
			this->btnAdd = (gcnew System::Windows::Forms::Button());
			this->btnRemove = (gcnew System::Windows::Forms::Button());
			this->textBoxHTSize = (gcnew System::Windows::Forms::TextBox());
			this->HTsize = (gcnew System::Windows::Forms::Label());
			this->LoadFile = (gcnew System::Windows::Forms::Button());
			this->SaveFile = (gcnew System::Windows::Forms::Button());
			this->dataGridView1 = (gcnew System::Windows::Forms::DataGridView());
			this->ProductName = (gcnew System::Windows::Forms::DataGridViewTextBoxColumn());
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->dataGridView1))->BeginInit();
			this->SuspendLayout();
			// 
			// btnAdd
			// 
			this->btnAdd->Location = System::Drawing::Point(238, 12);
			this->btnAdd->Name = L"btnAdd";
			this->btnAdd->Size = System::Drawing::Size(107, 45);
			this->btnAdd->TabIndex = 0;
			this->btnAdd->Text = L"Add";
			this->btnAdd->UseVisualStyleBackColor = true;
			this->btnAdd->Click += gcnew System::EventHandler(this, &MyForm::btnAdd_Click);
			// 
			// btnRemove
			// 
			this->btnRemove->Location = System::Drawing::Point(351, 12);
			this->btnRemove->Name = L"btnRemove";
			this->btnRemove->Size = System::Drawing::Size(107, 45);
			this->btnRemove->TabIndex = 1;
			this->btnRemove->Text = L"Remove";
			this->btnRemove->UseVisualStyleBackColor = true;
			this->btnRemove->Click += gcnew System::EventHandler(this, &MyForm::btnRemove_Click);
			// 
			// textBoxHTSize
			// 
			this->textBoxHTSize->Location = System::Drawing::Point(790, 23);
			this->textBoxHTSize->Name = L"textBoxHTSize";
			this->textBoxHTSize->Size = System::Drawing::Size(53, 22);
			this->textBoxHTSize->TabIndex = 2;
			this->textBoxHTSize->TextChanged += gcnew System::EventHandler(this, &MyForm::textBoxHTSize_TextChanged);
			// 
			// HTsize
			// 
			this->HTsize->AutoSize = true;
			this->HTsize->Location = System::Drawing::Point(787, 3);
			this->HTsize->Name = L"HTsize";
			this->HTsize->Size = System::Drawing::Size(56, 17);
			this->HTsize->TabIndex = 3;
			this->HTsize->Text = L"HT size";
			// 
			// LoadFile
			// 
			this->LoadFile->Location = System::Drawing::Point(12, 12);
			this->LoadFile->Name = L"LoadFile";
			this->LoadFile->Size = System::Drawing::Size(107, 45);
			this->LoadFile->TabIndex = 4;
			this->LoadFile->Text = L"Load File";
			this->LoadFile->UseVisualStyleBackColor = true;
			// 
			// SaveFile
			// 
			this->SaveFile->Location = System::Drawing::Point(125, 12);
			this->SaveFile->Name = L"SaveFile";
			this->SaveFile->Size = System::Drawing::Size(107, 45);
			this->SaveFile->TabIndex = 5;
			this->SaveFile->Text = L"Save File";
			this->SaveFile->UseVisualStyleBackColor = true;
			// 
			// dataGridView1
			// 
			this->dataGridView1->ColumnHeadersHeightSizeMode = System::Windows::Forms::DataGridViewColumnHeadersHeightSizeMode::AutoSize;
			this->dataGridView1->Columns->AddRange(gcnew cli::array< System::Windows::Forms::DataGridViewColumn^  >(1) { this->ProductName });
			this->dataGridView1->Location = System::Drawing::Point(71, 175);
			this->dataGridView1->Name = L"dataGridView1";
			this->dataGridView1->RowHeadersWidth = 51;
			this->dataGridView1->RowTemplate->Height = 24;
			this->dataGridView1->Size = System::Drawing::Size(421, 290);
			this->dataGridView1->TabIndex = 6;
			// 
			// ProductName
			// 
			this->ProductName->HeaderText = L"Product Name";
			this->ProductName->MinimumWidth = 6;
			this->ProductName->Name = L"ProductName";
			this->ProductName->Width = 125;
			// 
			// MyForm
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(8, 16);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(874, 477);
			this->Controls->Add(this->dataGridView1);
			this->Controls->Add(this->SaveFile);
			this->Controls->Add(this->LoadFile);
			this->Controls->Add(this->HTsize);
			this->Controls->Add(this->textBoxHTSize);
			this->Controls->Add(this->btnRemove);
			this->Controls->Add(this->btnAdd);
			this->Name = L"MyForm";
			this->Text = L"MyForm";
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->dataGridView1))->EndInit();
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion
	private: System::Void btnAdd_Click(System::Object^ sender, System::EventArgs^ e) {
		// Очистить таблицу перед загрузкой новых данных
		dataGridView1->Rows->Clear();

		int size = tree->getSize();

		// Добавить каждый элемент в таблицу
		for (int i = 0; i < size; i++) {
			// Получить данные для i-го элемента из дерева
			// С использованием функции tree->get(i) или подобной
			// Добавить строку в dataGridView1 с полученными данными
			// Пример: 
			/*
				dataGridView1->Rows->Add(gcnew array<System::String^> {
					vendorcode,
					productname,
					tin,
					day,
					month,
					year
				});
			*/
		}
	}
	private: System::Void btnRemove_Click(System::Object^ sender, System::EventArgs^ e) {
	}
	private: System::Void textBoxHTSize_TextChanged(System::Object^ sender, System::EventArgs^ e) {
		int newSize;
		if (Int32::TryParse(textBoxHTSize->Text, newSize))
		{
			if (newSize >= 5)
			{
				if (tree->isEmpty())
					tree->setHashTableSize(newSize);
				else
					MessageBox::Show("Tree is not empty.");
			}
			else
			{
				MessageBox::Show("The number is invalid.");
			}
		}
		else
		{
			MessageBox::Show("Please enter a valid integer number.");
		}
	}
};
}
Код MyForm.cpp:
#include "MyForm.h"

using namespace System;
using namespace System::Windows::Forms;

[STAThreadAttribute]
int main()
{
	Application::SetCompatibleTextRenderingDefault(false);
	Application::EnableVisualStyles();
	KursovayaCLR::MyForm form;
	Application::Run(% form);
}

Сейчас нужно добавить в интерфейс таблицу, которая будет хранить данные из tree, tree уже объявлено в MyForm.h, и я уже начал добавление dataGridView1. Правильно понимаю, что у таблицы должен быть всего один столбец с названием товара, и при нажатии на ячейку должна открываться хеш-таблица из товаров с таким названием?