Advertisement
Toxotsist

Цепное хеширование

Nov 3rd, 2021
659
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.18 KB | None | 0 0
  1. #include "iostream"
  2. #include "fstream"
  3. #include "string"
  4. using namespace std;
  5.  
  6. class HashTable
  7. {
  8. private:
  9.     const int start_size = 10; // Начальная длина таблицы
  10.     const double rehash_coefficient = 0.75; // Пороговый коэффициент нагрузки
  11.     double current_coefficient = 0.0; // Коэффициент нагрузки в данный момент
  12.     int table_size; // Длина таблицы
  13.     int node_amount; // Количество записей с ключами
  14.  
  15.     struct Node // Счёт в банке
  16.     {
  17.         int key; // Номер
  18.         string company; //
  19.         string fam; // Адрес владельца счёта
  20.         bool state; // Состояние, true - заполнено данными, false - удалено и ждёт освобождения памяти
  21.         Node* next; // Указатель на следующий узел
  22.     };
  23.     Node** arr; // Основной массив хеш-таблицы
  24. public:
  25.     HashTable()
  26.     {
  27.         table_size = start_size;
  28.         node_amount = 0;
  29.         arr = new Node * [table_size]; // Инициализация основного массива хеш-таблицы
  30.         for (int i = 0; i < table_size; ++i)
  31.             arr[i] = nullptr; // Заполняем таблицу нулевыми указателями
  32.     }
  33.     ~HashTable()
  34.     {
  35.         for (int i = 0; i < table_size; ++i) // Цикл для удаления всех узлов в списках поочерёдно
  36.             if (arr[i])
  37.             {
  38.                 Node* pointer = arr[i]; // Указатель на первый узел списка с индексом i в хеш таблице
  39.                 Node* del_buf = arr[i]; // Буфер для записи удаляемых узлов до указателя
  40.                 while (pointer != nullptr) // Пока узел существует
  41.                 {
  42.                     pointer = pointer->next; // Двигаем указатель на текущий узел дальше
  43.                     delete del_buf; // Освобождаем память, выделенную прошлому узлу
  44.                     del_buf = pointer; // Копирум адрес памяти текущего узла в буфер удаления
  45.                 }
  46.                 delete pointer; // Освобождаем память, выделенную для последнего в списке узла
  47.             }
  48.         delete[] arr; // Освобождаем память, выделенную для массива списков
  49.     }
  50.  
  51.     void resize()
  52.     {
  53.         int previous_size = table_size; // Запоминаем размер прошлой таблицы
  54.         table_size *= 2; // Удваиваем текущий размер таблицы
  55.         node_amount = 0; // Обнуляем число узлов
  56.         Node** arr2 = new Node * [table_size]; // Инициализируем новый массив с новым размером
  57.         for (int i = 0; i < table_size; ++i)
  58.             arr2[i] = nullptr; // Заполняем новый массив нулевыми указателями
  59.         cout << "\n" << "Произошло удвоение таблицы, у неё теперь длина: " << table_size << "\n";
  60.         cout << "Идёт рехеширование таблицы:" << "\n";
  61.         swap(arr, arr2); // Меняем местами старый и новый массивы
  62.         for (int i = 0; i < previous_size; ++i)
  63.         {
  64.             Node* buf = arr2[i]; // Переменная для прохода по списку для данного индекса
  65.             while (buf != nullptr) // Пока узел существует
  66.             {
  67.                 if (buf->state == true) // Если узел включён
  68.                     insertItem(buf->key, buf->company, buf->fam); // Копирование узла с рехешированием в новый массив списков
  69.                 buf = buf->next; //Ход вперёд
  70.             }
  71.         }
  72.         for (int i = 0; i < previous_size; ++i) // Цикл повторяет все действия деструктора класса, но для прошлого массива
  73.             if (arr2[i])
  74.             {
  75.                 Node* pointer = arr2[i];
  76.                 Node* del_buf = arr2[i];
  77.                 while (pointer != nullptr)
  78.                 {
  79.                     pointer = pointer->next;
  80.                     delete del_buf;
  81.                     del_buf = pointer;
  82.                 }
  83.                 delete pointer;
  84.             }
  85.         delete[] arr2;
  86.     }
  87.  
  88.     void addAll() {
  89.         int value = 0;
  90.         string path = "table.txt";
  91.         ifstream file(path);
  92.         string output = "";
  93.         string output2 = "";
  94.         string output3 = "";
  95.         while (!file.eof()) {
  96.             getline(file, output, ' ');
  97.             getline(file, output2, ' ');
  98.             getline(file, output3, ' ');
  99.             if (output != "") value = stoi(output);
  100.             insertItem(value, output2, output3);
  101.         }
  102.     }
  103.  
  104.     void insertItem(int key, string company, string fam)
  105.     {
  106.         int hash_value = hash(key); // Считаем хеш от переданного номера счёта в банке
  107.         while (hash_value > table_size)
  108.             resize();
  109.         if (arr[hash_value] == nullptr) // Если в массиве по индексу находится нулевой указатель
  110.             arr[hash_value] = new Node{ key, company, fam, true, nullptr }; // Добавляем новый узел с переданными ему параметрами
  111.         else
  112.         {
  113.             Node* prev_pointer = arr[hash_value]; // Буфер для хранения прошлого узла в списке
  114.             Node* pointer = arr[hash_value]; // Текущий узел в списке
  115.             while (pointer != nullptr)
  116.             {
  117.                 pointer = pointer->next; // Двигаем узел дальше
  118.                 if (pointer == nullptr) // Нет узла на этом месте
  119.                 {
  120.                 }
  121.                 else
  122.                 {
  123.                     prev_pointer = prev_pointer->next; // Двигаем буфер дальше
  124.                 }
  125.             }
  126.             pointer = new Node{ key, company, fam, true, nullptr }; // Добавляем новый узел с переданными ему параметрами
  127.             prev_pointer->next = pointer; // Создаём связь между текущим и предыдущим узлом
  128.         }
  129.         node_amount += 1;
  130.         current_coefficient = (double)node_amount / table_size; // Подсчитываем текущий коэффициент
  131.         cout << "Добавлен элемент с индексом: " << hash_value << "\n";
  132.         //cout << "N " << node_amount << " M " << table_size << "\n";
  133.         //cout << "Текущий коэффициент " << current_coefficient << "\n";
  134.         if (current_coefficient >= rehash_coefficient)
  135.         {
  136.             cout << "\n" << "Таблица до увеличения" << "\n";
  137.             display();
  138.             resize();
  139.             cout << "\n" << "Таблица после увеличения" << "\n";
  140.             display();
  141.         }
  142.     }
  143.  
  144.     void deleteItem(int key)
  145.     {
  146.         int hash_value = hash(key); // Считаем хеш от переданного числа
  147.         if (arr[hash_value] != nullptr) // Если подходящий список не пустой
  148.         {
  149.             Node* pointer = arr[hash_value]; // Начинаем с первого в списке узла
  150.             while (pointer != nullptr) // Пока узел не пустой
  151.             {
  152.                 if (pointer->key == key) // Если у узла искомый номер счёта в банке
  153.                 {
  154.                     pointer->state = false; // Выключаем данный узел, но не удаляем до изменения размеров
  155.                     node_amount -= 1;
  156.                 }
  157.                 pointer = pointer->next; // Двигаемся дальше по списку
  158.             }
  159.         }
  160.  
  161.         string path = "table.txt";
  162.         fstream inputFile;
  163.         ofstream outputFile;
  164.         inputFile.open(path);
  165.         outputFile.open("newtable.txt");
  166.         string k, comp, fio;
  167.         while (!inputFile.eof()) {
  168.             getline(inputFile, k, ' ');
  169.             getline(inputFile, comp, ' ');
  170.             getline(inputFile, fio, ' ');
  171.             if (k == "") { break; }
  172.             if (key != stoi(k)) {
  173.                 outputFile << k << " " << comp << " " << fio << " ";
  174.             }
  175.             }
  176.             outputFile.close();
  177.             inputFile.close();
  178.             remove("table.txt");
  179.             rename("newtable.txt", "table.txt");
  180.     }
  181.  
  182.     int hash(int key)
  183.     {
  184.         return (key % table_size); // Остаток от деления на размер таблицы
  185.     }
  186.  
  187.     int search(int key)
  188.     {
  189.         int hash_value = hash(key); // Считаем хеш от переданного числа
  190.         Node* pointer = arr[hash_value]; // Начинаем с первого узла в списке под нужным индексом
  191.         while (pointer != nullptr) // Пока узел не пустой
  192.         {
  193.             if (pointer->key == key) // Если у узла искомый номер счёта в банке
  194.                 return 1;
  195.             pointer = pointer->next; // Двигаемся дальше по списку
  196.         }
  197.         return 0;
  198.     }
  199.  
  200.     void display()
  201.     {
  202.         for (int i = 0; i < table_size; ++i)
  203.         {
  204.             Node* pointer = arr[i]; // Начинаем с первого узла в списке под нужным индексом
  205.             while (pointer != nullptr) // Пока узел не пустой
  206.             {
  207.                 if (pointer->state == true) // Если узел включён
  208.                     cout << "Индекс: " << i << " Номер счёта: " << pointer->key << " Компания: " << pointer->company << " Фамилия: " << pointer->fam << "\n";
  209.                 pointer = pointer->next; // Двигаемся дальше по списку
  210.             }
  211.         }
  212.     }
  213. };
  214.  
  215. int main()
  216. {
  217.     setlocale(0, "");
  218.     HashTable hashT;
  219.     hashT.addAll();
  220.     hashT.display();
  221.     hashT.deleteItem(1000000);
  222.     hashT.display();
  223.     return 0;
  224. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement