Нужно исправить класс Tree, представляющий АВЛ-дерево, так, чтобы: 
1. Каждый элемент дерева хранил хеш-таблицу класса HashTable из элементов типа Cell;
2. В дерево добавлялись элементы типа Sorts, считываемые из файла (чтение файла уже реализовано корректно) и распределялись по дереву по полю productname, а затем добавлялись в хеш-таблицы соответствующих элементов. Соответственно, при поиске по дереву и удалении из него так же применяется поле productname. Напиши только класс Tree, остальные классы менять не нужно.
Вот код:
#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
{
    int tin;

    TIN(int t) : tin(t) {}
};
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(0), 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:
    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()
    {

    }
    ~HashTable()
    {
        table.clear();
    }
    int searchItem(int key1, int key2, int key3)
    {
        int n = table.size();
        int hash = hash1(key1, key2, key3, n);
        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 0;
        }
        else
        {
            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 1;
                }
            }
            std::cout << "Item is not in the table." << std::endl;
            return -1;
        }
    }
    void printTable()
    {
        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;
        }
    }
    void writeFile(std::string file)
    {
        std::ofstream out(file);
        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;
        }
    }
};

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

class Tree
{
private:
    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;
    }
public:

    void add(int vc, std::string pn, 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.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;
        switch (p->balance)
        {
        case -1:
            p->balance = 0;
            break;
        case 0:
            p->balance = 1;
            h = false;
            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 = 0;
            h = false;
            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;
            }
        }
    }
    Node* del(Node* r, Node* q, bool& h)
    {
        if (r->right != NULL)
        {
            r->right = del(r->right, q, h);
            if (h)
                balance2(r, h);
            return r;
        }
        else
        {
            q->key = r->key;
            Node* left = r->left;
            delete r;
            h = true;
            return left;
        }
    }
    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);
            }
            else if (p->left != NULL && p->right == NULL)
            {
                p->list.remove(linenumber);
                if (p->list.head == NULL)
                {
                    Node* temp = p->left;
                    delete p;
                    p = temp;
                    h = true;
                }
            }
            else if (p->left == NULL && p->right != NULL)
            {
                p->list.remove(linenumber);
                if (p->list.head == NULL)
                {
                    Node* temp = p->right;
                    delete p;
                    p = temp;
                    h = true;
                }
            }
            else
            {
                p->list.remove(linenumber);
                if (p->list.head == NULL)
                {
                    p->list.freeMemory();
                    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->list = temp->list;
                    delete temp;
                    h = true;
                }
            }
        }
    }

    void search(Key x, Node*& p, bool& h) // поиск элемента
    {
        Node* q;
        if (p == NULL || x.f1 != 'Б')
        {
            cout << "В дереве нет такого элемента" << endl;
            h = false;
        }
        else if (x.f2 < p->key.f2)
        {
            search(x, p->left, h);
        }
        else if (x.f2 > p->key.f2)
        {
            search(x, p->right, h);
        }
        else
        {
            cout << "Элемент содержится в строке(ах) входного файла ";
            p->list.print();
            h = false;
        }
    }

    ofstream out("outdata.txt");
    void walktree(Node* t, short hh) // обход дерева справа налево и вывод в файл
    {

        if (t != NULL)
        {
            walktree(t->right, hh + 1);
            out << t->key.f1 << t->key.f2 << endl;
            walktree(t->left, hh + 1);
        }
    }

    void printtree(Node* t, short hh) // печать дерева
    {
        if (t != NULL)
        {
            printtree(t->right, hh + 1);
            for (int i = 1; i <= hh; i++)
                cout << "   ";
            cout << t->key.f1 << t->key.f2 << " Строки ";
            t->list.print();
            cout << endl;
            printtree(t->left, hh + 1);
        }
    }

    void deletetree(Node* t, short hh) // удаление дерева
    {

        if (t != NULL)
        {
            deletetree(t->right, hh + 1);
            delete t;
            deletetree(t->left, hh + 1);
        }
    }

    void initialize(Node*& p, bool& h)
    {
        Key key;

        string line;

        int f;
        int linenumber = 0;
        if (in.is_open())
        {
            while (getline(in, line))
            {
                if (size(line) != 5)
                    continue;
                ++linenumber;
                key.f1 = line[0];
                key.f2 = 0;
                for (int i = 1; i < 5; i++)
                {
                    key.f2 += (line[i] - '0') * pow(10, 4 - i);
                }
                add(key, p, linenumber, h);
            }
        }
        h = false;
    }
    Tree(const std::string readFile, int n)
    {
        Node* root = NULL;
        bool h = true;
        std::vector <Sorts> sorts = readFromFile(readFile);

        for (int i = 0; i < n; i++)
        {
            if (i < sorts.size())
                add(sorts[i], root, h);
        }
    }
};