Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
251 changes: 251 additions & 0 deletions lab 1 mid 1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>

/**
* Структура для хранения одной записи (Record).
* Допустим, у неё есть:
* - ID (целое число)
* - координаты X и Y (вещественные),
* как упрощенный пример «ключевых точек».
*/
struct Node
{
int id;
float x;
float y;
Node *left;
Node *right;

Node(int _id, float _x, float _y)
: id(_id), x(_x), y(_y), left(nullptr), right(nullptr) {}
};

class CompositeIndex
{
public:
/**
* Конструктор по умолчанию
*/
CompositeIndex() : root(nullptr) {}

/**
* Деструктор
*/
~CompositeIndex()
{
destroy(root);
}

/**
* Парсим дерево из потока, используя preorder-формат, где:
* - "ID X Y" означает узел с (id, x, y)
* - "#" означает отсутствие поддерева
*
* @param iss поток данных (преобразованный из строки)
*/
void parseIndex(std::istringstream &iss)
{
// TODO
destroy(root);
root = parseNode(iss);
}

/**
* Подсчет количества узлов
*
* @return общее количество узлов в дереве
*/
int totalNodes() const
{
// TODO
return countNodes(root);
}

/**
* Высота дерева
*
* @return высота дерева
*/
int height() const
{
// TODO
return treeHeight(root);
}

/**
* Количество листьев
*
* @return количество листьев в дереве
*/
int leaves() const
{
// TODO
return countLeaves(root);
}

/**
* Проверка, что дерево удовлетворяет свойству BST:
* - Все ключи в левом поддереве < ключа в корне
* - Все ключи в правом поддереве > ключа в корне
* - Рекурсивно для всех поддеревьев
*
* @return true, если дерево корректно, иначе false
*/
bool isValid() const
{
// TODO
std::vector<int> arr;
getInorder(root, arr);
for (size_t i = 1; i < arr.size(); ++i)
{
if (arr[i - 1] >= arr[i]) return false;
}
return true;
}

/**
* Минимальный ID в дереве
*
* @return минимальный ID
* @throws std::runtime_error если дерево пустое
*/
int minID() const
{
// TODO
std::vector<int> arr;
getInorder(root, arr);
if (arr.empty()) throw std::runtime_error("Дерево пустое");
return *std::min_element(arr.begin(), arr.end());
}

/**
* Максимальный ID в дереве
*
* @return максимальный ID
* @throws std::runtime_error если дерево пустое
*/
int maxID() const
{
// TODO
std::vector<int> arr;
getInorder(root, arr);
if (arr.empty()) throw std::runtime_error("Дерево пустое");
return *std::max_element(arr.begin(), arr.end());
}

private:
Node *root;

/**
* Рекурсивный парсинг (preorder):
* 1) считываем токен. Если "#", значит пустое поддерево
* 2) иначе это ID, за ним два float (x и y)
* 3) создаём узел, рекурсивно парсим левое и правое поддерево
*
* @param iss входной поток
* @return созданный узел (корень поддерева)
*/
Node *parseNode(std::istringstream &iss)
{
// TODO
std::string tok;
if (!(iss >> tok)) return nullptr;
if (tok == "#") return nullptr;

int id = std::stoi(tok);
float x, y;
if (!(iss >> x >> y))
throw std::runtime_error("Неверный формат ввода при разборе узла");

Node *node = new Node(id, x, y);
node->left = parseNode(iss);
node->right = parseNode(iss);
return node;
}

/**
* Подсчитать количество узлов
*
* @param node корневая нода
* @return количество узлов в поддереве
*/
int countNodes(Node *node) const
{
// TODO
if (!node) return 0;
return 1 + countNodes(node->left) + countNodes(node->right);
}

/**
* Подсчитывает высоту дерева
*
* @param node корневая нода
* @return высота поддерева
*/
int treeHeight(Node *node) const
{
// TODO
if (!node) return 0;
int lh = treeHeight(node->left);
int rh = treeHeight(node->right);
return 1 + (lh > rh ? lh : rh);
}

/**
* Подсчитывает количество листьев
*
* @param node корневая нода
* @return количество листьев в поддереве
*/
int countLeaves(Node *node) const
{
// TODO
if (!node) return 0;
if (!node->left && !node->right) return 1;
return countLeaves(node->left) + countLeaves(node->right);
}

/**
* Выполняет inorder-обход дерева, сохраняя ID узлов
* в переданный вектор
*
* @param node корневая нода
* @param arr вектор, куда будут сохраняться ID
*/
void getInorder(Node *node, std::vector<int> &arr) const
{
// TODO
if (!node) return;
getInorder(node->left, arr);
arr.push_back(node->id);
getInorder(node->right, arr);
}

/**
* Удаляет всё дерево (рекурсивно)
*
* @param node корень поддерева
*/
void destroy(Node *node)
{
// TODO
if (!node) return;
destroy(node->left);
destroy(node->right);
delete node;
}
};

/**
* Пример ввода:
* 10 1.0 2.0 5 0.0 0.0 # # 20 0.0 0.0 # #
*
* Структура дерева:
* 10
* / \
* 5 20
*/
137 changes: 137 additions & 0 deletions lab 2 5 light.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#include <cassert>
#include <iostream>
#include <vector>
#include <list>

/**
+ Ключ: int
+ Значeние: int
+ Метод разрешения коллизий: свободная адресация
+ Рeaлизация хeш-функций: любой
+ Тип смещения: квадратичное исследование
*/
struct HashTable {
size_t m_TableSize;
std::vector<std::list<std::pair<int, int>>> m_Table;

HashTable(int size) : m_TableSize(size), m_Table(size) {}

/**
* xeш-функция
*
* @solvе
*/
int Hash(int key) const {
long long mod = static_cast<long long>(m_TableSize);
long long v = key % mod;
if (v < 0) v += mod;
return static_cast<int>(v);
}

/**
* Встaвка пары (ключ, значение)
*
* Если ключ ужe существует, обновляет значение
*
* @solvе
*/
void Insert(int key, int value) {
int h = Hash(key);
for (size_t i = 0; i < m_TableSize; ++i) {
int idx = static_cast<int>((h + i * 1LL * i) % m_TableSize);
auto &bucket = m_Table[idx];
if (!bucket.empty()) {
if (bucket.front().first == key) {
bucket.front().second = value;
return;
}
} else {
bucket.push_back({key, value});
return;
}
}
}

/**
* Поиск знaчения по ключу
*
* Если ключ нaйден, в value записывается найденное значение
* и вoзврaщается true, иначе false
*
* @solvе
*/
bool Get(int key, int &value) const {
int h = Hash(key);
for (size_t i = 0; i < m_TableSize; ++i) {
int idx = static_cast<int>((h + i * 1LL * i) % m_TableSize);
const auto &bucket = m_Table[idx];
if (!bucket.empty() && bucket.front().first == key) {
value = bucket.front().second;
return true;
}
}
return false;
}

/**
* Удаление элемента по ключу
*
* Возвращает true, если элемент был найден и удалён, иначе false
*
* @solvе
*/
bool Remove(int key) {
int h = Hash(key);
for (size_t i = 0; i < m_TableSize; ++i) {
int idx = static_cast<int>((h + i * 1LL * i) % m_TableSize);
auto &bucket = m_Table[idx];
if (!bucket.empty() && bucket.front().first == key) {
bucket.clear();
return true;
}
}
return false;
}

std::string getTable() const {
std::string ans = "";
for (int i = 0; i < m_TableSize; i++) {
ans += "Bucket " + std::to_string(i) + ": ";
for (const auto &entry : m_Table[i]) {
ans += "[" + std::to_string(entry.first) + ":" + std::to_string(entry.second) + "]";
}
ans += "\n";
}
return ans;
}

};

int main() {
HashTable ht(7);

ht.Insert(1, 10);
ht.Insert(8, 80);
ht.Insert(15, 150);
ht.Insert(2, 20);
ht.Insert(9, 90);

int v = -1;
assert(ht.Get(1, v) && v == 10);
assert(ht.Get(8, v) && v == 80);
assert(ht.Get(15, v) && v == 150);
assert(ht.Get(2, v) && v == 20);
assert(ht.Get(9, v) && v == 90);
assert(!ht.Get(100, v));

ht.Insert(1, 15);
assert(ht.Get(1, v) && v == 15);

assert(ht.Remove(8));
assert(!ht.Get(8, v));

std::cout << ht.getTable() << std::endl;

std::cout << "OK" << std::endl;
return 0;
}
Binary file added lab 3 light 1.pdf
Binary file not shown.
Loading