
ТП_23_ИСТ_1_1_Какушкина_Ольга_Витальевна_ЛР_5.2
.docxМИНОБРНАУКИ РОССИИ
Ф
едеральное
государственное бюджетное образовательное
учреждение высшего образования
НИЖЕГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ
УНИВЕРСИТЕТ им. Р.Е.АЛЕКСЕЕВА
Институт радиоэлектроники и информационных технологий
Кафедра информатики и систем управления
ОТЧЕТ по лабораторной работе №5
(наименование темы проекта или работы)
по дисциплине
Технологии программирования
(наименование дисциплины)
РУКОВОДИТЕЛЬ:
________________ Капранов С. Н.
(подпись) (фамилия, и.,о.)
СТУДЕНТ:
________________ Какушкина О.В
(подпись) (фамилия, и.,о.)
23-ИСТ-1-1
(шифр группы)
Работа защищена «___» ____________
С оценкой ________________________
Нижний Новгород 2024
Текст задания:
Реализовать алгоритмы поиска, вставки, удаления элементов таблицы и распечатки таблицы и метод ре-хэширования таблицы при увеличении размера данных.
-
№ Варианта
Ключ
1
СНИЛС
2
Номер телефона
3
Адрес Компании(Страна, Город, Улица, Дом).
4
Фамилия Имя Отчество
-
№ Варианта
Хэш-функция
1
функция деления
2
функция умножения
3
функция «середины квадрата»
4
функция свертки (слияния)
5
функции работы со строковыми ключами
-
№ Варианта
Метод разрешения коллизий
1
Метод цепочек
2
Квадратичное опробование
3
Использование бинарных деревьев
-
№ Варианта
Ключ
Хэш-функция
Метод разрешения коллизий
7
3
2
1
Список функций и структур данных с описанием:
struct Node |
Узел для хэш-таблицы, который содержит ключ, значение и указатель на следующий узел. Инициализирует узел с заданным ключом и значением, а также устанавливает next в nullptr. |
class HashTable |
Реализация хэш-таблицы, использующая метод цепочек для разрешения коллизий. Инициализирует хэш-таблицу заданного размера и создает вектор узлов. |
int hashFunction(const string& key) |
Параметры: key: Ключ для которого нужно вычислить хэш. Возвращает: Индекс в пределах размера таблицы. Действие: Вычисляет хэш для ключа, используя простую хэш-функцию
|
int getSize() const |
Возвращает: Размер хэш-таблицы. Действие: Возвращает текущее значение размера таблицы.
|
vector<Node*>& getTable() |
Возвращает: Ссылку на вектор узлов. Действие: Позволяет получить доступ к вектору узлов хэш-таблицы.
|
void insert(const string& key, const string& value) |
Параметры: key: Ключ, по которому будет храниться значение. value: Значение, связанное с ключом. Действие: Вставляет новый узел в хэш-таблицу. Если количество элементов превышает порог, вызывается метод rehash
|
bool isThresholdReached(Node* node) |
Параметры: node: Указатель на узел, с которого начинается подсчет. Возвращает: true, если количество узлов в цепочке превышает порог. Действие: Проверяет, превышает ли количество узлов заданный порог.
|
bool remove(const string& key) |
Параметры: key: Ключ узла для удаления. Возвращает: true, если узел был удален; false в противном случае. Действие: Удаляет узел из хэш-таблицы по заданному ключу.
|
void display() |
Действие: Выводит содержимое хэш-таблицы, перечисляя все ключи и значения в каждой цепочке. |
bool isHashTableEmpty() |
Возвращает: true, если таблица пуста; иначе false. Действие: Проверяет, есть ли хотя бы один узел в таблице.
|
void rehash() |
Действие: Увеличивает размер таблицы и перераспределяет все существующие узлы по новым индексам. |
string search(const string& key) |
Параметры: key: Ключ для поиска. Возвращает: Значение, связанное с ключом, если найден; иначе сообщение об отсутствии. Действие: Ищет узел с заданным ключом и возвращает его значение.
|
void loadFromFile(const string& filename, HashTable& hTable) |
Параметры: filename: Имя файла для загрузки данных. hTable: Ссылка на объект HashTable, в который будут загружены данные. Действие: Загружает данные из файла в хэш-таблицу в формате "ключ значение".
|
void saveToFile(const string& filename, HashTable& hTable) |
Параметры: filename: Имя файла для сохранения данных. hTable: Ссылка на объект HashTable, данные которого будут сохранены. Действие: Сохраняет все элементы хэш-таблицы в файл в формате "ключ значение".
|
void appendToFile(const string& filename, HashTable& hTable) |
Параметры: filename: Имя файла для добавления данных. hTable: Ссылка на объект HashTable, данные которого будут добавлены. Действие: Добавляет содержимое хэш-таблицы в конец существующего файла без перезаписи.
|
Программный код:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
struct Node {
string key;
string value;
Node* next;
Node(const string& k, const string& v) : key(k), value(v), next(nullptr) {}
};
class HashTable {
private:
vector<Node*> table;
int size;
int threshold = 5;
int elementCount = 0;
int hashFunction(const string& key) {
const int multiplier = 31;
long long hash = 0;
for (char c : key) {
hash = hash * multiplier + c;
}
return hash % size;
}
public:
HashTable(int initialSize = 4) : size(initialSize) {
table.resize(size, nullptr);
}
int getSize() const {
return size;
}
vector<Node*>& getTable() {
return table;
}
void insert(const string& key, const string& value) {
if (key.empty() || value.empty()) {
cout << "Ключ или значение не могут быть пустыми!" << endl;
return;
}
int idx = hashFunction(key);
Node* newNode = new Node(key, value);
elementCount++; // Увеличиваем общее количество элементов
// Проверяем, достигнут ли порог
if (elementCount >= threshold) {
rehash();
}
if (table[idx] == nullptr) {
table[idx] = newNode;
}
else {
Node* current = table[idx];
while (current->next != nullptr) {
current = current->next;
}
current->next = newNode;
}
}
bool isThresholdReached(Node* node) {
int count = 0;
while (node != nullptr) {
count++;
node = node->next;
}
return count >= threshold;
}
bool remove(const string& key) {
int idx = hashFunction(key);
Node* current = table[idx];
Node* prev = nullptr;
while (current != nullptr) {
if (current->key == key) {
if (prev == nullptr) {
table[idx] = current->next;
}
else {
prev->next = current->next;
}
delete current;
cout << "Компания успешно удалена." << endl;
return true;
}
prev = current;
current = current->next;
}
cout << "Компания не найдена для удаления." << endl;
return false;
}
void display() {
cout << "\nХэш-таблица с методом цепочек (для коллизий):\n";
for (int i = 0; i < size; ++i) {
cout << "Индекс " << i << ": ";
Node* current = table[i];
while (current != nullptr) {
cout << "(" << current->key << ", " << current->value << ") -> ";
current = current->next;
}
cout << "nullptr" << endl;
}
if (isHashTableEmpty()) {
cout << "Хэш-таблица пуста." << endl;
}
}
bool isHashTableEmpty() {
for (Node* node : table) {
if (node != nullptr) {
return false;
}
}
return true;
}
void rehash() {
vector<Node*> oldTable = table;
size *= 2; // Увеличиваем размер таблицы
table.clear();
table.resize(size, nullptr);
elementCount = 0; // Сбрасываем количество и заново будем считать
for (Node* oldNode : oldTable) {
Node* current = oldNode;
while (current != nullptr) {
// Сохраняем следующий элемент
Node* temp = current->next;
// Вычисляем новый индекс для текущего узла
int idx = hashFunction(current->key);
// Вставляем узел в новую таблицу по новому индексу
current->next = table[idx];
table[idx] = current;
// Увеличиваем счетчик элементов
elementCount++;
current = temp; // Переходим к следующему узлу
}
}
cout << "Хэш-таблица успешно ре-хеширована!" << endl;
}
string search(const string& key) {
int idx = hashFunction(key);
Node* current = table[idx];
while (current != nullptr) {
if (current->key == key) {
return current->value;
}
current = current->next;
}
return "Компания не найдена";
}
};
void loadFromFile(const string& filename, HashTable& hTable) {
ifstream file(filename);
if (!file.is_open()) {
cout << "Ошибка открытия файла." << endl;
return;
}
string key, value;
while (file >> key >> value) {
hTable.insert(key, value);
}
file.close();
}
void saveToFile(const string& filename, HashTable& hTable) {
ofstream file(filename);
if (!file.is_open()) {
cout << "Ошибка открытия файла." << endl;
return;
}
for (int i = 0; i < hTable.getSize(); ++i) {
Node* current = hTable.getTable()[i];
while (current != nullptr) {
file << current->key << " " << current->value << endl;
current = current->next;
}
}
file.close();
}
void appendToFile(const string& filename, HashTable& hTable) {
ofstream file(filename, ios_base::app); // Открываем в режиме добавления
if (!file.is_open()) {
cout << "Ошибка открытия файла." << endl;
return;
}
for (int i = 0; i < hTable.getSize(); ++i) {
Node* current = hTable.getTable()[i];
while (current != nullptr) {
file << current->key << " " << current->value << endl;
current = current->next;
}
}
file.close();
}
int main() {
setlocale(LC_ALL, "Russian");
HashTable hTable;
int choice;
string key, value;
string filename = "C:/comp.txt";
loadFromFile(filename, hTable);
while (true) {
cout << "\nМеню:\n"
<< "1. Добавить компанию\n"
<< "2. Найти компанию\n"
<< "3. Удалить компанию\n"
<< "4. Вывести содержимое\n"
<< "5. Сохранить данные в файл\n"
<< "6. Перезаписать данные в файл\n"
<< "7. Загрузить данные из файла\n"
<< "8. Выйти\n";
cin >> choice;
switch (choice) {
case 1:
cout << "Введите адрес компании: ";
cin.ignore();
getline(cin, key);
cout << "Введите название компании: ";
getline(cin, value);
hTable.insert(key, value);
break;
case 2:
cout << "Введите адрес для поиска компании: ";
cin.ignore();
getline(cin, key);
cout << "Результат поиска: " << hTable.search(key) << endl;
break;
case 3:
cout << "Введите адрес компании для удаления: ";
cin.ignore();
getline(cin, key);
if (hTable.remove(key)) {
cout << "Компания успешно удалена." << endl;
}
else {
cout << "Компания не найдена для удаления." << endl;
}
break;
case 4:
hTable.display();
break;
case 5:
saveToFile(filename, hTable);
cout << "Данные успешно сохранены в файл." << endl;
break;
case 6:
appendToFile(filename, hTable);
cout << "Данные успешно добавлены в файл." << endl;
break;
case 7:
loadFromFile(filename, hTable);
cout << "Данные успешно загружены из файла." << endl;
break;
case 8:
return 0;
default:
cout << "Неверный ввод. Попробуйте снова." << endl;
}
}
return 0;
}
Файл:
Вывод в консоли:
Ввод с клавиатуры и чтение из файла
Вывод:
Данная лабораторная работа над проектом хэш-таблицы помогла углубить знания о структурах данных и алгоритмах. Реализация хэш-таблицы с учетом методов разрешения коллизий и динамического изменения размера представляет собой важный шаг в понимании более сложных систем хранения и обработки данных. Использование методов, таких как ре-хеширование и функции хэширования, значительно улучшает эффективность и производительность работы с большими объемами информации.