Смирнов Илья#2
Conversation
|
@KorotinEgor, @kermanglobe, хоть с CMake и проблемы, но сам код можете проверять |
kermanglobe
left a comment
There was a problem hiding this comment.
если мне не изменяет память, то должна ещё быть упорядоченная таблица на массиве
| std::vector<Node*> memorysearch(std::string name); | ||
| int balance(Node* nd); | ||
| void smallleftrot(Node* xparent, Node* x); | ||
| void smallrightrot(Node* xparent, Node* x); | ||
| void bigleftrot(Node* xparent, Node* x); | ||
| void bigrightrot(Node* xparent, Node* x); |
There was a problem hiding this comment.
я бы эти методы в private поместил
| void clear(std::string name); | ||
| polynoms Arithmetic(std::string strexpr); |
There was a problem hiding this comment.
в чём резон помещать метод для вычисления выражений внутрь таблиц?
| ~AVLTreeTable(); | ||
| polynoms search(std::string name); |
There was a problem hiding this comment.
ключ-строку нужно передавать как const std::string& (иначе каждый раз при вызове функции будет происходить копирование)
| } | ||
| polynoms entered(entmon); | ||
| table.add(name, entered); | ||
| cout << "UnorderedTable: add. Operations: " << counttable << endl; | ||
| tree.add(name, entered); | ||
| cout << "AVLTreeTable: add. Operations: " << counttree << endl; | ||
| hashtable.add(name, entered); |
There was a problem hiding this comment.
если я правильно понял, то пользователь должен выбирать, в какую из таблиц он хочет положить полином
There was a problem hiding this comment.
В задании написано "Работа происходит сразу с таблицами всех типов.", как я и сделал
| file(GLOB hdrs "*.h*" "../include/*.h") | ||
| file(GLOB srcs "*.cpp") |
There was a problem hiding this comment.
Да что с ним, что без него - не работает =)
|
|
||
| static int counttree = 0; |
There was a problem hiding this comment.
так counttree работать не будет, ты либо прописываешь эту переменную в хедере как extern int counttree и в исходниках пишешь int counttree, либо помещаешь внутрь класса
при текущей реализации программа-сэмпл выводит 0 операций при вставке, поиске и удалении (что, очевидно, не так)
| } | ||
| try { | ||
| search(name); | ||
| } | ||
| catch (std::logic_error& e) { | ||
| Node* cur = head; | ||
| std::vector<Node*> path = memorysearch(name); |
There was a problem hiding this comment.
интересная, конечно, схема с try/catch блоком...
если уж на то пошло, то в catch должно быть const std::exception& e
There was a problem hiding this comment.
search выбрасывает logic_error, поэтому и ловится именно он
|
|
||
| polynoms AVLTreeTable::search(std::string name) { |
There was a problem hiding this comment.
неплохо бы возвращать не собственно полином, а указатель на cur->data.second
можно будет как минимум сделать проще проверку на наличие элемента в таблице
| if (i >= 1) { | ||
| if (s[i] == 'x' && (s[i - 1] == '0' || s[i - 1] == '1' || s[i - 1] == '2' || s[i - 1] == '3' || s[i - 1] == '4' || s[i - 1] == '5' || s[i - 1] == '6' || s[i - 1] == '7' || s[i - 1] == '8' || s[i - 1] == '9')) { |
There was a problem hiding this comment.
| if (i >= 1) { | |
| if (s[i] == 'x' && (s[i - 1] == '0' || s[i - 1] == '1' || s[i - 1] == '2' || s[i - 1] == '3' || s[i - 1] == '4' || s[i - 1] == '5' || s[i - 1] == '6' || s[i - 1] == '7' || s[i - 1] == '8' || s[i - 1] == '9')) { | |
| if (i >= 1) { | |
| if (s[i] == 'x' && s[i - 1] >= '0' && s[i - 1] <= '9') { |
так компактнее будет
| } | ||
| TEST(AVLTreeTable, can_clear) { | ||
| list<pair<int, double>>a; | ||
| a.push_back(make_pair(100, 1)); | ||
| polynoms A(a); | ||
| AVLTreeTable T; | ||
| T.add("pol", A); | ||
| ASSERT_NO_THROW(T.clear("pol")); | ||
| } | ||
| TEST(AVLTreeTable, clear_is_correct) { | ||
| list<pair<int, double>>a; | ||
| a.push_back(make_pair(100, 1)); | ||
| polynoms A(a); | ||
| AVLTreeTable T; | ||
| T.add("pol", A); | ||
| T.clear("pol"); | ||
| ASSERT_ANY_THROW(T.search("pol")); | ||
| } |
There was a problem hiding this comment.
можно добавить тесты на удаление с различными сценариями (удаление листа, вершины с одним или двумя потомками, головы с потомками или без потомков)
KorotinEgor
left a comment
There was a problem hiding this comment.
Методы с арифметикой я не проверял, скажем, что они правильные изначально, а если это не так, то виноват госопдин проверяющий.
|
|
||
| class UnorderedTable { | ||
| std::vector<std::pair<std::string, polynoms>> table; | ||
| size_t size; |
There was a problem hiding this comment.
А в чём вообще смысл этой переменной? Ты хранишь размер, чтобы, если что, выдать количество элементов пользователю за О(1), но с данной функцией прекрасно спровляется return table.size()
| this->add(rec.first, rec.second); | ||
| } | ||
| } | ||
| void UnorderedTable::add(std::string name, polynoms pol) { |
There was a problem hiding this comment.
В некоторых методах деревьев вроде бы поправил, а тут - нет. Лучше передавать что строку, что полином по ссылке, чтобы не копировать одно и то же по 10 раз
В хэшах и тех методах деревьев, что не попали под "некоторые" аналогично
| polynoms search(std::string name); | ||
| void add(std::string name, polynoms pol); | ||
| void clear(std::string name); | ||
| void resize(); |
There was a problem hiding this comment.
А разве не логичнее будет засунуть resize в private? А так, это нарушение принципов ООП
| int res, strsum = 0; | ||
| for (int i = 0; i < name.size(); i++) { | ||
| strsum += int(name[i]); | ||
| } | ||
| res = strsum % size; | ||
| return res; |
There was a problem hiding this comment.
А зачем res вообще существует?, то же можно сказать и про Hash2.
| if (table[(Hash1(name) + i * Hash2(name)) % size] != nullptr) { | ||
| if (table[(Hash1(name) + i * Hash2(name)) % size]->state == 0 || table[(Hash1(name) + i * Hash2(name)) % size]->state == -1) { | ||
| table[(Hash1(name) + i * Hash2(name)) % size] = new Rec(name, pol); | ||
| return; |
There was a problem hiding this comment.
Утечка памяти, если элемент явяется удалённым ты просто присваиваешь в Table[...] новый указатель, в то время как старый элемент, на который там раньше был указатель остаётся где-то непонятно где, но точно не удаляется.
| while (true) { | ||
| counttree++; | ||
| if (name < cur->data.first) { | ||
| if (cur->left) { | ||
| cur->h += 1; | ||
| cur = cur->left; | ||
| } | ||
| else { | ||
| break; | ||
| } | ||
| } | ||
| else { | ||
| if (cur->right) { | ||
| cur->h += 1; | ||
| cur = cur->right; | ||
| } | ||
| else { | ||
| break; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Не понял смысл этого действия, разве нельзя просто пройтись по path и всем там h++ сделать?
| else { | ||
|
|
||
| if (balance(path[i]) == 2) { | ||
| if (balance(path[i]->left) >= 0) { | ||
| if (i == 0) smallrightrot(nullptr, path[i]); | ||
| else smallrightrot(path[i - 1], path[i]); | ||
| } | ||
| else if (balance(path[i]->left) < 0) { | ||
| if (i == 0) bigrightrot(nullptr, path[i]); | ||
| else bigrightrot(path[i - 1], path[i]); | ||
| } | ||
| } | ||
| if (balance(path[i]) == -2) { | ||
| if (balance(path[i]->right) <= 0) { | ||
| if (i == 0) smallleftrot(nullptr, path[i]); | ||
| else smallleftrot(path[i - 1], path[i]); | ||
| } | ||
| else if (balance(path[i]->right) > 0) { | ||
| if (i == 0) bigleftrot(nullptr, path[i]); | ||
| else bigleftrot(path[i - 1], path[i]); | ||
| } | ||
| } | ||
| seth(path[i]); | ||
|
|
There was a problem hiding this comment.
Эта часть бесполезна, как и весь этот огромный if, его единтсенное теоретичсекое предназначение - чтоб не залесть, куда не надо, но в твоём случае, это опбеспечивает метод balance (в него уже встроена проверка на то, являются ли 1 или 2 потомка нулевыми или нет)
| void smallleftrot(Node* xparent, Node* x); | ||
| void smallrightrot(Node* xparent, Node* x); | ||
| void bigleftrot(Node* xparent, Node* x); | ||
| void bigrightrot(Node* xparent, Node* x); |
There was a problem hiding this comment.
повороты должны быть в private, тк они могут изменить дерево так, что оно перестанет быть AVL-деревом или, могут уронить программу(при попытке прочитать не принадлежащую им память), чего ты, как разработчик классов на C++, допускать не должен.
| else if (minval->left != nullptr && minval->right == nullptr) { | ||
| path[path.size() - 2]->right == minval->left; | ||
| counttree++; | ||
| } |
There was a problem hiding this comment.
опять бесполезная часть, после цикла while у cur никогда нет потомков слева, т.е. minnval->left=nullptr всегда
| else { | ||
| counttree++; | ||
| if (path[path.size() - 2]->left == cur) { | ||
| path[path.size() - 2]->left = cur->left; | ||
| } | ||
| else { | ||
| path[path.size() - 2]->right = cur->left; | ||
| } | ||
| } |
There was a problem hiding this comment.
Не рассмтариваешь случай, когда у тебя дерево это голова с 1м левым потомком и ты хочешь удалить голову. Тогда path.size()=1, path[path.size() - 1]->h!=0, cur->right==nullptr, ты попадаешь в это место и деалешь path[path.size() - 2]
There was a problem hiding this comment.
Кроме того, если ты попал сюда, то ты даже не удаляешь cur, а просто исключешь его из дерева, т.е. ещё одна утечка памяти
|
@ValentinV95, Здравствуйте, код готов к проверке |
ValentinV95
left a comment
There was a problem hiding this comment.
Лабораторная принята, часть справидливых замечаний от одногруппников осталась не исправленной и не прокомментирована
No description provided.