Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "iostream"
- #include "fstream"
- #include "string"
- using namespace std;
- class HashTable
- {
- private:
- const int start_size = 10; // Начальная длина таблицы
- const double rehash_coefficient = 0.75; // Пороговый коэффициент нагрузки
- double current_coefficient = 0.0; // Коэффициент нагрузки в данный момент
- int table_size; // Длина таблицы
- int node_amount; // Количество записей с ключами
- struct Node // Счёт в банке
- {
- int key; // Номер
- string company; //
- string fam; // Адрес владельца счёта
- bool state; // Состояние, true - заполнено данными, false - удалено и ждёт освобождения памяти
- Node* next; // Указатель на следующий узел
- };
- Node** arr; // Основной массив хеш-таблицы
- public:
- HashTable()
- {
- table_size = start_size;
- node_amount = 0;
- arr = new Node * [table_size]; // Инициализация основного массива хеш-таблицы
- for (int i = 0; i < table_size; ++i)
- arr[i] = nullptr; // Заполняем таблицу нулевыми указателями
- }
- ~HashTable()
- {
- for (int i = 0; i < table_size; ++i) // Цикл для удаления всех узлов в списках поочерёдно
- if (arr[i])
- {
- Node* pointer = arr[i]; // Указатель на первый узел списка с индексом i в хеш таблице
- Node* del_buf = arr[i]; // Буфер для записи удаляемых узлов до указателя
- while (pointer != nullptr) // Пока узел существует
- {
- pointer = pointer->next; // Двигаем указатель на текущий узел дальше
- delete del_buf; // Освобождаем память, выделенную прошлому узлу
- del_buf = pointer; // Копирум адрес памяти текущего узла в буфер удаления
- }
- delete pointer; // Освобождаем память, выделенную для последнего в списке узла
- }
- delete[] arr; // Освобождаем память, выделенную для массива списков
- }
- void resize()
- {
- int previous_size = table_size; // Запоминаем размер прошлой таблицы
- table_size *= 2; // Удваиваем текущий размер таблицы
- node_amount = 0; // Обнуляем число узлов
- Node** arr2 = new Node * [table_size]; // Инициализируем новый массив с новым размером
- for (int i = 0; i < table_size; ++i)
- arr2[i] = nullptr; // Заполняем новый массив нулевыми указателями
- cout << "\n" << "Произошло удвоение таблицы, у неё теперь длина: " << table_size << "\n";
- cout << "Идёт рехеширование таблицы:" << "\n";
- swap(arr, arr2); // Меняем местами старый и новый массивы
- for (int i = 0; i < previous_size; ++i)
- {
- Node* buf = arr2[i]; // Переменная для прохода по списку для данного индекса
- while (buf != nullptr) // Пока узел существует
- {
- if (buf->state == true) // Если узел включён
- insertItem(buf->key, buf->company, buf->fam); // Копирование узла с рехешированием в новый массив списков
- buf = buf->next; //Ход вперёд
- }
- }
- for (int i = 0; i < previous_size; ++i) // Цикл повторяет все действия деструктора класса, но для прошлого массива
- if (arr2[i])
- {
- Node* pointer = arr2[i];
- Node* del_buf = arr2[i];
- while (pointer != nullptr)
- {
- pointer = pointer->next;
- delete del_buf;
- del_buf = pointer;
- }
- delete pointer;
- }
- delete[] arr2;
- }
- void addAll() {
- int value = 0;
- string path = "table.txt";
- ifstream file(path);
- string output = "";
- string output2 = "";
- string output3 = "";
- while (!file.eof()) {
- getline(file, output, ' ');
- getline(file, output2, ' ');
- getline(file, output3, ' ');
- if (output != "") value = stoi(output);
- insertItem(value, output2, output3);
- }
- }
- void insertItem(int key, string company, string fam)
- {
- int hash_value = hash(key); // Считаем хеш от переданного номера счёта в банке
- while (hash_value > table_size)
- resize();
- if (arr[hash_value] == nullptr) // Если в массиве по индексу находится нулевой указатель
- arr[hash_value] = new Node{ key, company, fam, true, nullptr }; // Добавляем новый узел с переданными ему параметрами
- else
- {
- Node* prev_pointer = arr[hash_value]; // Буфер для хранения прошлого узла в списке
- Node* pointer = arr[hash_value]; // Текущий узел в списке
- while (pointer != nullptr)
- {
- pointer = pointer->next; // Двигаем узел дальше
- if (pointer == nullptr) // Нет узла на этом месте
- {
- }
- else
- {
- prev_pointer = prev_pointer->next; // Двигаем буфер дальше
- }
- }
- pointer = new Node{ key, company, fam, true, nullptr }; // Добавляем новый узел с переданными ему параметрами
- prev_pointer->next = pointer; // Создаём связь между текущим и предыдущим узлом
- }
- node_amount += 1;
- current_coefficient = (double)node_amount / table_size; // Подсчитываем текущий коэффициент
- cout << "Добавлен элемент с индексом: " << hash_value << "\n";
- //cout << "N " << node_amount << " M " << table_size << "\n";
- //cout << "Текущий коэффициент " << current_coefficient << "\n";
- if (current_coefficient >= rehash_coefficient)
- {
- cout << "\n" << "Таблица до увеличения" << "\n";
- display();
- resize();
- cout << "\n" << "Таблица после увеличения" << "\n";
- display();
- }
- }
- void deleteItem(int key)
- {
- int hash_value = hash(key); // Считаем хеш от переданного числа
- if (arr[hash_value] != nullptr) // Если подходящий список не пустой
- {
- Node* pointer = arr[hash_value]; // Начинаем с первого в списке узла
- while (pointer != nullptr) // Пока узел не пустой
- {
- if (pointer->key == key) // Если у узла искомый номер счёта в банке
- {
- pointer->state = false; // Выключаем данный узел, но не удаляем до изменения размеров
- node_amount -= 1;
- }
- pointer = pointer->next; // Двигаемся дальше по списку
- }
- }
- string path = "table.txt";
- fstream inputFile;
- ofstream outputFile;
- inputFile.open(path);
- outputFile.open("newtable.txt");
- string k, comp, fio;
- while (!inputFile.eof()) {
- getline(inputFile, k, ' ');
- getline(inputFile, comp, ' ');
- getline(inputFile, fio, ' ');
- if (k == "") { break; }
- if (key != stoi(k)) {
- outputFile << k << " " << comp << " " << fio << " ";
- }
- }
- outputFile.close();
- inputFile.close();
- remove("table.txt");
- rename("newtable.txt", "table.txt");
- }
- int hash(int key)
- {
- return (key % table_size); // Остаток от деления на размер таблицы
- }
- int search(int key)
- {
- int hash_value = hash(key); // Считаем хеш от переданного числа
- Node* pointer = arr[hash_value]; // Начинаем с первого узла в списке под нужным индексом
- while (pointer != nullptr) // Пока узел не пустой
- {
- if (pointer->key == key) // Если у узла искомый номер счёта в банке
- return 1;
- pointer = pointer->next; // Двигаемся дальше по списку
- }
- return 0;
- }
- void display()
- {
- for (int i = 0; i < table_size; ++i)
- {
- Node* pointer = arr[i]; // Начинаем с первого узла в списке под нужным индексом
- while (pointer != nullptr) // Пока узел не пустой
- {
- if (pointer->state == true) // Если узел включён
- cout << "Индекс: " << i << " Номер счёта: " << pointer->key << " Компания: " << pointer->company << " Фамилия: " << pointer->fam << "\n";
- pointer = pointer->next; // Двигаемся дальше по списку
- }
- }
- }
- };
- int main()
- {
- setlocale(0, "");
- HashTable hashT;
- hashT.addAll();
- hashT.display();
- hashT.deleteItem(1000000);
- hashT.display();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement