Advertisement
Vladislav_Bezruk

Biographical guide

Dec 8th, 2021 (edited)
331
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.59 KB | None | 0 0
  1. #include <iostream>
  2. #include <time.h>
  3. #include <conio.h>
  4.  
  5. using namespace std;
  6.  
  7. //кількість клієнтів хеш-таблиці
  8. #define CLIENTS_COUNT   10
  9.  
  10. //розмір хеш таблиці
  11. #define HASHTABLE_SIZE  10
  12.  
  13. //початок адреси клієнта (потрібно для ідентифікації адреси)
  14. #define ADDRESS_IND     '$'
  15.  
  16. //повідомлення при відсутності запису у хеш-таблиці
  17. #define NO_RECORD       "None"
  18.  
  19. //типи даних
  20. #define PHONE_TYPE      string
  21. #define SURNAME_TYPE    string
  22. #define DATA_TYPE       string
  23.  
  24. //з'єднання між клієнтами
  25. const int connections[CLIENTS_COUNT][3] = {
  26.     {9, 1, -1}, //з'єднання першого клієнта
  27.     {0, 2, -1}, //з'єднання другого клієнта
  28.     {1, 3, -1}, //з'єднання i-го клієнта
  29.     {2, 4, -1},
  30.     {3, 5, -1},
  31.     {4, 6, -1},
  32.     {5, 7, -1},
  33.     {6, 8, -1},
  34.     {7, 9, -1},
  35.     {8, 0, -1}
  36. };
  37.  
  38. //структура елемента звичайної хеш-таблиці
  39. template <typename keyType, typename dataType> struct HashTableNode {
  40.     keyType key; //ключ
  41.     dataType data; //значення
  42.     HashTableNode* next = NULL;  //адреса на наступний елемент
  43.    
  44.     HashTableNode(keyType _key, dataType _data) : key(_key), data(_data) {}
  45. };
  46.  
  47. //клас звичайної хеш-таблиці
  48. template <typename keyType, typename dataType> class HashTable {
  49.     private:
  50.         //хеш-таблиця
  51.         HashTableNode<keyType, dataType>* hashTable[HASHTABLE_SIZE];
  52.        
  53.         //кількість записів у хеш-таблиці
  54.         int recordsCount;
  55.    
  56.         //хеш-функція
  57.         int hash(keyType key) {
  58.             int sum = 0;
  59.            
  60.             for (int i = 0; i < key.length(); i++)
  61.                 sum += key[i];
  62.                
  63.             return sum % HASHTABLE_SIZE;
  64.         }
  65.    
  66.     public:
  67.         HashTable() {
  68.             recordsCount = 0;
  69.            
  70.             for (int i = 0; i < HASHTABLE_SIZE; i++)
  71.                 hashTable[i] = NULL;
  72.         }
  73.        
  74.         //функція занесення інформації у хеш-таблицю
  75.         void push(keyType key, dataType data) {
  76.             recordsCount++;
  77.            
  78.             //визначаємо індекс у хеш-таблиці через хеш-функцію
  79.             int hashIndex = hash(key);
  80.            
  81.             HashTableNode<keyType, dataType>* newHashNode = new HashTableNode<keyType, dataType>(key, data);
  82.            
  83.             HashTableNode<keyType, dataType>* hashNode = hashTable[hashIndex];
  84.  
  85.             //шукаємо останній елемент у комірці хеш-таблиці
  86.             if (hashNode == NULL) {
  87.                 hashTable[hashIndex] = newHashNode;
  88.             } else {
  89.                 while (hashNode->next) {
  90.                     hashNode = hashNode->next;
  91.                 }
  92.                 //додаємо у кінець комірки новий елемент
  93.                 hashNode->next = newHashNode;
  94.             }
  95.         }
  96.        
  97.         //функція для отримання даних за ключем
  98.         dataType get(keyType key) {
  99.             //визначаємо індекс у хеш-таблиці через хеш-функцію
  100.             int hashIndex = hash(key);
  101.            
  102.             HashTableNode<keyType, dataType>* hashNode = hashTable[hashIndex];
  103.            
  104.             //знаходимо елемент хеш-таблиці, доки не знайшли елемент з заданим ключем
  105.             while (hashNode) {
  106.                 if (hashNode->key == key) {
  107.                     //повертаємо знайдене значення
  108.                     return hashNode->data;
  109.                 }
  110.                 hashNode = hashNode->next;
  111.             }
  112.             return NO_RECORD;
  113.         }
  114.        
  115.         //функція для видалення елемента з хеш-таблиці
  116.         void pop(keyType key) {
  117.             //визначаємо індекс у хеш-таблиці через хеш-функцію
  118.             int hashIndex = hash(key);
  119.            
  120.             HashTableNode<keyType, dataType>* hashNode = hashTable[hashIndex];
  121.             HashTableNode<keyType, dataType>* preHashNode;
  122.            
  123.             //продовжуємо пошуки, доки не знайшли елемент із заданим ключем
  124.             while (hashNode) {
  125.                 //якщо знайшли елемент , то видаляємо його
  126.                 if (hashNode->key == key) {
  127.                     recordsCount--;
  128.                     if (hashNode->next == NULL) {
  129.                         if (hashTable[hashIndex]->key == key) {
  130.                             hashTable[hashIndex] = NULL;
  131.                         } else {
  132.                             (*preHashNode).next = NULL;
  133.                         }
  134.                     } else {
  135.                         *hashNode = *hashNode->next;
  136.                     }
  137.                     return;
  138.                 }
  139.                 preHashNode = hashNode;
  140.                 hashNode = hashNode->next;
  141.             }
  142.         }
  143.        
  144.         //функція для знаходження кількості записів у хеш-таблиці
  145.         int getRecordsCount() {return recordsCount;}
  146.        
  147.         //функція для отримання усіх ключів хеш-таблицю
  148.         keyType* getKeys() {
  149.             //якщо немає записів, то повертаємо NULL
  150.             if (recordsCount == 0) return NULL;
  151.            
  152.             keyType* keys = new keyType[recordsCount];
  153.             HashTableNode<keyType, dataType>* hashNode;
  154.            
  155.             //рухаємось по усім коміркам хеш-таблиці
  156.             for (int i = 0, k = 0; i < HASHTABLE_SIZE; i++) {
  157.                 hashNode = hashTable[i];
  158.                
  159.                 //доки не дійшли до кінця комірки
  160.                 while (hashNode != NULL) {
  161.                     //записуємо ключі у масив
  162.                     keys[k++] = hashNode->key;
  163.                     hashNode = hashNode->next;
  164.                 }
  165.             }  
  166.             return keys;
  167.         }
  168. };
  169.  
  170. //клас розподіленої хеш-таблиці
  171. template <typename keyType, typename dataType> class DHashTable {
  172.     private:
  173.         //клієнти хеш таблиці
  174.         HashTable<keyType, dataType> clients[CLIENTS_COUNT];
  175.        
  176.     public:
  177.         //функція для занесення даних у хеш-таблицю клієнта з адресою clientId
  178.         void push(int clientId, keyType key, dataType data) {
  179.             //якщо дані не були занесені, то заносимо
  180.             if (clients[clientId].get(key) == NO_RECORD) {
  181.                 clients[clientId].push(key, data);
  182.                
  183.                 int i = 0;
  184.                
  185.                 //заносимо дані до всіх приєднаних клієнтів і вказуємо адресу даних як адресу даного клієнта
  186.                 while (connections[clientId][i] != -1) {
  187.                     int newClientId = connections[clientId][i++];
  188.                     dataType newData = ADDRESS_IND + to_string(clientId);
  189.                    
  190.                     push(newClientId, key, newData);
  191.                 }  
  192.             }
  193.         }
  194.        
  195.         //фукнція для отримання даних із хеш-таблиці клієнта з адресою clientId
  196.         dataType get(int clientId, keyType key) {
  197.             //отримуємо дані
  198.             dataType data = clients[clientId].get(key);
  199.            
  200.             //якщо отримані дані це адреса, то знаходимо дані вже за новою адресою
  201.             if (data[0] == ADDRESS_IND) {
  202.                 int newClientId = 0;
  203.                
  204.                 //перетворюємо адресу із string в int
  205.                 for (int i = data.length() - 1, s = 1; i > 0; i--, s *= 10) {
  206.                     newClientId += (data[i] - '0') * s;
  207.                 }  
  208.                 //знаходимо дані за новою адресою
  209.                 return get(newClientId, key);
  210.             }
  211.             //якщо дані виявились не адресою, то повертаємо їх і припиняємо пошук
  212.             return data;
  213.         }
  214.        
  215.         //функція для видалення запису із хеш-таблиці клієнта із адресою clientId
  216.         void pop(int clientId, keyType key) {
  217.             //якщо такий запис існує
  218.             if (clients[clientId].get(key) != NO_RECORD) {
  219.                 //видаляємо його
  220.                 clients[clientId].pop(key);
  221.                
  222.                 int i = 0;
  223.                
  224.                 //повідомляємо всім з'єднаним клієнтам про видалення даних
  225.                 while (connections[clientId][i] != -1) {
  226.                     int newClientId = connections[clientId][i++];
  227.                    
  228.                     pop(newClientId, key);
  229.                 }      
  230.             }
  231.         }
  232.        
  233.         //функція для отримання всіх ключів у розподіленій хеш-таблиці
  234.         keyType* getKeys() {return clients[0].getKeys();}
  235.        
  236.         //функція для отримання кількості записів у розподіленій хеш-таблиці
  237.         int getRecordsCount() {return clients[0].getRecordsCount();}
  238. };
  239.  
  240. int main() {
  241.     srand(time(NULL));
  242.    
  243.     DHashTable<PHONE_TYPE, SURNAME_TYPE> surnameTable;
  244.     DHashTable<SURNAME_TYPE, DATA_TYPE> dataTable;
  245.    
  246.     while (1) {
  247.         int clientId = rand() % CLIENTS_COUNT;
  248.        
  249.         system("CLS");
  250.        
  251.         cout << "###Biographical guide###" << endl << endl;
  252.        
  253.         cout << "Records in guide: " << dataTable.getRecordsCount() << endl << endl;
  254.        
  255.         if (dataTable.getRecordsCount()) {
  256.             cout << "Records:" << endl;
  257.            
  258.             SURNAME_TYPE* surnames = dataTable.getKeys();
  259.             PHONE_TYPE* phones = surnameTable.getKeys();
  260.            
  261.             for (int i = 0; i < dataTable.getRecordsCount(); i++) {
  262.                 PHONE_TYPE phone;
  263.                    
  264.                 for (int j = 0; j < dataTable.getRecordsCount(); j++)
  265.                     if (surnameTable.get(clientId, phones[j]) == surnames[i])
  266.                         phone = phones[j];
  267.                
  268.                 cout << surnames[i] << " : " << phone << endl;
  269.             }
  270.             cout << endl;
  271.         }
  272.        
  273.         cout << "Commands:" << endl;
  274.         cout << "Add new record -> add" << endl;
  275.         cout << "Remove record -> pop" << endl;
  276.         cout << "Find record -> get" << endl << endl;
  277.        
  278.         string command, key;
  279.         PHONE_TYPE phone;
  280.         SURNAME_TYPE surname;
  281.         DATA_TYPE data;
  282.        
  283.         cout << "Enter command: ";
  284.         cin >> command;
  285.        
  286.         if (command == "add") {
  287.             cout << endl << "Enter surname: " << endl;;
  288.             cin >> surname;
  289.            
  290.             cout << endl << "Enter phone: " << endl;;
  291.             cin >> phone;
  292.            
  293.             cout << endl << "Enter info about person: " << endl;
  294.             cin.ignore();
  295.             getline(cin, data);
  296.            
  297.             surnameTable.push(clientId, phone, surname);
  298.             dataTable.push(clientId, surname, data);
  299.            
  300.         } else if (command == "pop") {
  301.             cout << endl << "Enter surname or phone: " << endl;;
  302.             cin >> key;
  303.            
  304.             if (surnameTable.get(clientId, key) != NO_RECORD) {
  305.                 dataTable.pop(clientId, surnameTable.get(clientId, key));
  306.                 surnameTable.pop(clientId, key);
  307.             } else if (dataTable.get(clientId, key) != NO_RECORD) {
  308.                 PHONE_TYPE phone;
  309.                 PHONE_TYPE* phones = surnameTable.getKeys();
  310.                    
  311.                 for (int j = 0; j < dataTable.getRecordsCount(); j++)
  312.                     if (surnameTable.get(clientId, phones[j]) == key)
  313.                         phone = phones[j];
  314.            
  315.                 surnameTable.pop(clientId, phone);
  316.                 dataTable.pop(clientId, key);
  317.             }
  318.            
  319.         } else if (command == "get") {
  320.             cout << endl << "Enter surname or phone: " << endl;;
  321.             cin >> key;
  322.            
  323.             if (surnameTable.get(clientId, key) != NO_RECORD) {
  324.                 cout << endl << "Surname:" << endl;
  325.                 cout << surnameTable.get(clientId, key) << endl;
  326.                 cout << endl << "Info:" << endl;
  327.                 cout << dataTable.get(clientId, surnameTable.get(clientId, key)) << endl;
  328.             } else if (dataTable.get(clientId, key) != NO_RECORD) {
  329.                 cout << endl << "Phone:" << endl;
  330.                
  331.                 PHONE_TYPE phone;
  332.                 PHONE_TYPE* phones = surnameTable.getKeys();
  333.                    
  334.                 for (int j = 0; j < dataTable.getRecordsCount(); j++)
  335.                     if (surnameTable.get(clientId, phones[j]) == key)
  336.                         phone = phones[j];
  337.                
  338.                 cout << phone << endl;
  339.                 cout << endl << "Info:" << endl;
  340.                 cout << dataTable.get(clientId, key) << endl;
  341.             }
  342.         } else {
  343.             cout << endl << "Error!" << endl;
  344.         }
  345.         cout << endl << "Press key to continue" << endl;
  346.         _getch();
  347.     }
  348.  
  349.     return 0;
  350. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement