Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
23 changes: 23 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.24)
project(CourseProject)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

set(CMAKE_PREFIX_PATH "/opt/homebrew/opt/qt/lib/cmake")

find_package(Qt6 COMPONENTS
Core
Gui
Widgets
REQUIRED)

add_executable(CourseProject main.cpp mainwindow.cpp mainwindow.ui Model.cpp View.cpp Controller.cpp Connection.cpp)
target_link_libraries(CourseProject
Qt::Core
Qt::Gui
Qt::Widgets
)

9 changes: 9 additions & 0 deletions Connection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "Connection.h"

Connection::Connection(MainWindow *mainWindow)
: _view(mainWindow)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если спрятать mainWindow внутри view, то тебе не придется заниматься этим жонглированием и вне view ты все равно не используешь mainWindow.

{
_controller.ptr = &_model;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если у тебя есть класс, то не делай в нем открытых полей. Потому что класс подразумевает, что у тебя есть инварианты на его переменные члены. А если ты их делаешь открытыми, то ты не можешь гарантировать инварианты, так как их может любой нарушить. Лучше сделать конструктор контоллера, который будет съедать адрес модели и этом можно сделать в списке инициализации.

_view.subscribe(_controller.input());
_model.subscribe(_view.input());
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не надо радовать пользователя гит репозитория "кирпичами". Делай пустую строку в конце каждого файла.

17 changes: 17 additions & 0 deletions Connection.h
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Переименуй файл в Application

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef COURSEPROJECT_CONNECTION_H
#define COURSEPROJECT_CONNECTION_H

#include "Controller.h"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Помести весь свой проект в namespace. Не пиши ничего в global namespace.

class Connection{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вот этот объект надо сделать Application, а MainWindow запихнуть во view.

public:
Connection(MainWindow* mainWindow);
//~Connection();

private:
AVLTree _model;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не делай _ в начале имен. Дело в том, что имена начинающиеся с _ или __ зарезервированы по стандарту (в данном случае проблем нет, но очень легко ошибиться). Потому лучше сделать их в конце.

View _view;
Controller _controller;
};

#endif //COURSEPROJECT_CONNECTION_H
17 changes: 17 additions & 0 deletions Controller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "Controller.h"

Controller::Controller(AVLTree* ptr)
:ptr(ptr)
{

}

void Controller::action(const View::SendData &data) {
const std::vector<int> vec = data.addValue;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вот это плохая строчка, тут ты копируешь целиком вектор. Надо написать
const std::vector& vec = data.addValue;

if(vec.size() == 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это сделано потому что ты можешь получать пустые данные? Может просто не отправлять пустые данные?

return;
if(vec.back() == 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что эта проверка означает?

ptr->insert(vec[0]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Во-первых, вот тут лучше ptr переименовать в model_, чтобы было понятно, что происходит.
Во-вторых, не понятно, почему ты обращаешься к элементу vec[0].

else
ptr->deleteNode(vec[0]);
}
31 changes: 31 additions & 0 deletions Controller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef COURSEPROJECT_CONTROLLER_H
#define COURSEPROJECT_CONTROLLER_H

#include <memory>

#include "Model.h"
#include "View.h"

class Controller {
public:
Controller() = default;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Убери дефолтный конструктор. У тебя контроллер не должен уметь конструироваться без валидной модели. Иначе у тебя ломаются инварианты корректного состояния контроллера.

Controller(AVLTree* ptr);

///what to do with data
void action(const View::SendData& data);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сделай эту функцию приватной. Никто кроме контроллера не должен ее видеть. Контоллер умеет лишь присоединяться к модели и выдавать порт на прослушку view.


///subscribe controller to view
NSLibrary::CObserver<View::SendData>* input() { return &observerAdd; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не используй сырые длинные типы, заведи в начале класса в приватной части соответствующие юзинги. Например

using ViewData = View::SendData;
using Observer = NSLibrary::CObserver<ViewData >;
using Input = NSLibrary::CColdInput<ViewData >;

Для контоллера лучше использовать ColdInput, который не оповещается при подключении.


///public, but let it be like that
AVLTree* ptr;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сделай приватным. Никто не должен видеть внутренности контроллера.


private:
NSLibrary::CHotInput<View::SendData> observerAdd = [this](const View::SendData& data)
{ action(data); };
NSLibrary::CHotInput<View::SendData> observerDelete = [this](const View::SendData& data)
{ action(data); };
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Судя по всему тебе не надо два порта. Второй можно удалить, а первый переименовать в observer_. И все.

};


#endif //COURSEPROJECT_CONTROLLER_H
218 changes: 218 additions & 0 deletions Model.cpp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не могу найти Model.h файл.

Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
#include "Model.h"

int AVLTree::findMaxHeight(Node* left, Node* right)
{
int l = 0, r = 0;
if(left != nullptr)
l = left->height;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

static int getHeight(const Node* node) {
  if (node == nullptr)
    return 0;
  return node->height;
}

И тогда можно будет просто написать

static int findMaxHeight(const Node* left, const Node* right) {
  return std::max(getHeight(left), getHeight(right));
}

if(right != nullptr)
r = right->height;
return std::max(l, r);
}

int AVLTree::findBalanceFactor(Node* node)
{
int l = 0, r = 0;
if(node == nullptr)
return 0;
if(node->leftCh != nullptr)
l = node->leftCh->height;
if(node->rightCh != nullptr)
r = node->rightCh->height;
return l - r;
}

Node* AVLTree::rightRotate(Node* node)
{
Node* lCh = node->leftCh;
Node* rGrCh = node->leftCh->rightCh;
node->leftCh->rightCh = node;
node->leftCh = rGrCh;
node->height = findMaxHeight(node->leftCh, node->rightCh) + 1;
lCh->height = findMaxHeight(lCh->leftCh, lCh->rightCh) + 1;
return lCh;
}
Node* AVLTree::leftRotate(Node *node)
{
Node* rCh = node->rightCh;
Node* lGrCh = node->rightCh->leftCh;
node->rightCh->leftCh = node;
node->rightCh = lGrCh;
node->height = findMaxHeight(node->leftCh, node->rightCh) + 1;
rCh->height = findMaxHeight(rCh->leftCh, rCh->rightCh) + 1;
return rCh;
}


Node* AVLTree::insert(Node* node, int key)
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Очень похоже, что в этом случае ты можешь разбить эту функцию на подфункции с теми именами, которые лежат в комментариях.

///find leaf node, where to insert newNode
if(node == nullptr)
return new Node(key);
if(key < node->key)
node->leftCh = insert(node->leftCh, key);
else if(key > node->key)
node->rightCh = insert(node->rightCh, key);
else
return node;

///update height of ancestor
node->height = findMaxHeight(node->leftCh, node->rightCh) + 1;

///find balance factor
int balanceFactor = findBalanceFactor(node);

///check whether tree is unbalanced and balance it
if(balanceFactor > 1 && key < node->leftCh->key)
return rightRotate(node);
if(balanceFactor > 1 && key > node->leftCh->key)
{
node->leftCh = leftRotate(node->leftCh);
return rightRotate(node);
}
if(balanceFactor < -1 && key > node->rightCh->key)
return leftRotate(node);
if(balanceFactor < -1 && key < node->rightCh->key)
{
node->rightCh = rightRotate(node->rightCh);
return leftRotate(node);
}
return node;
}

void AVLTree::insert(int key)
{
int t = 1;
root_ = insert(root_, key);

if(root_== nullptr)
return;
insertPort.notify();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если я правильно понял, то у тебя нет анимации.

}

Node* AVLTree::inorderSuccessor(Node* x)
{
Node* cur = x->rightCh;
while(cur->leftCh != nullptr)
cur = cur->leftCh;
return cur;
}

Node* AVLTree::deleteNode(Node *node, int key)
{
///findNode, which should be deleted, and delete it
if(node == nullptr)
return node;
if(key < node->key)
node->leftCh = deleteNode(node->leftCh, key);
else if(key > node->key)
node->rightCh = deleteNode(node->rightCh, key);
else
{
///one or zero children
if(node->leftCh == nullptr || node->rightCh == nullptr)
{
Node* cur = nullptr;
if(node->leftCh)
cur = node->leftCh;
if(node->rightCh)
cur = node->rightCh;
if(cur == nullptr)
{
cur = node;
node = nullptr;
}
else
*node = *cur;
delete cur;
}
///two children
else
{
Node* cur = AVLTree::inorderSuccessor(node);
node->key = cur->key;
node->rightCh = deleteNode(node->rightCh, cur->key);
}
}

if(node == nullptr)
return node;
///update height of the node
node->height = findMaxHeight(node->rightCh, node->leftCh) + 1;

///find balance factor
int balanceFactor = findBalanceFactor(node);
///check whether tree is unbalanced and balance it
if(balanceFactor > 1 && findBalanceFactor(node->leftCh) >= 0)
return rightRotate(node);
if(balanceFactor > 1 && findBalanceFactor(node->leftCh) < 0)
{
node->leftCh = leftRotate(node->leftCh);
return rightRotate(node);
}
if(balanceFactor < -1 && findBalanceFactor(node->rightCh) < 0)
return leftRotate(node);
if(balanceFactor < -1 && findBalanceFactor(node->rightCh) >= 0)
{
node->rightCh = rightRotate(node->rightCh);
return leftRotate(node);
}
return node;
}

void AVLTree::deleteNode(int key)
{
root_ = deleteNode(root_, key);
insertPort.notify();
}

void AVLTree::clearHelp(Node*& node)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Функции в cpp файле должны идти в том же порядке, в каком они объявлены в header-е. Иначе невозможно искать нужную функцию.

{
if (node != nullptr)
{
clearHelp(node->leftCh);
clearHelp(node->rightCh);
delete node;
node = nullptr;
}
}
AVLTree::~AVLTree()
{
clearHelp(root_);
}

//Node* AVLTree::search(Node *node, int key)
//{
// if(node == nullptr)
// return node;
// if(key < node->key)
// node->leftCh = search(node->leftCh, key);
// else if(key > node->key)
// node->rightCh = search(node->rightCh, key);
// else
// return node;
//}

//Node* AVLTree::search(int key)
//{
// return search(_root, key);
//}

//void AVLTree::levelPrint(Node* root)
//{
// if (!root)
// return;
// std::queue<Node*> q;
// q.push(root);

// while (!q.empty())
// {
// Node* cur = q.front();
// q.pop();
// std::cout << cur->key <<"\n";
// if (cur->leftCh)
// q.push(cur->leftCh);
// if (cur->rightCh)
// q.push(cur->rightCh);
// }
//}
63 changes: 63 additions & 0 deletions Model.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#ifndef COURSEPROJECT_MODEL_H
#define COURSEPROJECT_MODEL_H

#include <iostream>
#include <vector>
#include "/Users/mayyaspirina/Documents/CourseProject/Observer/Observer.h"

class Node{
public:

Node(){}
Node(int key)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Убрать конструкторы и сделать структуру. Дефолтные значения присваивать явно.

: key(key), height(1), rightCh(nullptr), leftCh(nullptr)
{}
int key;
int height;
Node* leftCh;
Node* rightCh;
};

class AVLTree{
public:
AVLTree()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если у тебя дерево собрано на указателях, то надо удалить возможность его копировать и мувать.

AVLTree(const AVLTree&) = delete;
AVLTree(AVLTree&&) noexcept = delete;
AVLTree& operator=(const AVLTree&) = delete;
AVLTree& operator=(AVLTree&&) noexcept = delete;

: root_(nullptr)
{}

void clearHelp(Node*& treeptr);
~AVLTree();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Специальные функции, такие как конструкторы, операторы копирования, перемещения и деструктор пиши рядом, не вставляй между ними всякие функции хелперы. Функции хелперы делай приватными.


void insert(int key);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Оставь в публичном интерфейсе только те функции, которые должны быть видны снаружи, например, используются контроллером.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А что если вставить нельзя? Если повторяющийся ключ, тебе не хочется вернуть bool, который говорит что вставили или нет? Это не обязательно, но мало ли, вдруг это пригодится.

int findMaxHeight(Node* left, Node* right);
int findBalanceFactor(Node* node);
Node* rightRotate(Node* node);
Node* leftRotate(Node* node);
Node* insert(Node* node, int key);

Node* inorderSuccessor(Node* x);
void deleteNode(int key);
Node* deleteNode(Node* node, int key);
void levelPrint(Node* root);

Node* search(int key);
Node* search(Node* node, int key);


struct ModAddData{
std::reference_wrapper<Node* const> Value;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • А почему ты не сообщаешь ссылку на само дерево? Ну или тогда указатель на корень? Зачем заворачивать в ссылку?
  • Я бы ожидал const Node*, потому что ты не хочешь менять что внутри дерева.

};
void subscribe(NSLibrary::CObserver<ModAddData>* observer)
{
assert(observer);
insertPort.subscribe(observer);
}
private:

// std::vector<Node*> root_;
Node* root_ = nullptr;
int Value;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вот это что такое? Зачем в дереве какое-то value дополнительно? Кроме того, ты имена переменных пишешь то с большой то с маленькой буквы. Надо определиться и выбрать единый стиль.

NSLibrary::CObservableData<ModAddData> insertPort = ModAddData{std::cref(root_)};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Плохое название, лучше пусть будет port_ и все.

};


#endif //COURSEPROJECT_MODEL_H
Loading