Advertisement
evcamels

EBAL C++ DVA RAZA

Dec 5th, 2021
703
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.59 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <iostream>
  5. using namespace std;
  6. #define CAPACITY 50000 // размер хеш таблицы
  7.  
  8. unsigned long hash_function(char* str) {
  9.     unsigned long i = 0;
  10.     for (int j=0; str[j]; j++)
  11.         i += str[j];
  12.     return i % CAPACITY;
  13. }
  14.  
  15. typedef struct Ht_item Ht_item;
  16.  
  17. // определение элементов хеш-таблицы
  18. struct Ht_item {
  19.     char* key;
  20.     char* value;
  21. };
  22.  
  23.  
  24. typedef struct LinkedList LinkedList;
  25.  
  26. // определеине связного списка
  27. struct LinkedList {
  28.     Ht_item* item;
  29.     LinkedList* next;
  30. };
  31.  
  32.  
  33. typedef struct HashTable HashTable;
  34.  
  35. // определение хеш таблицы
  36. struct HashTable {
  37.     // содержание массива указателей
  38.     // на элементы
  39.     Ht_item** items;
  40.     LinkedList** overflow_buckets;
  41.     int size;
  42.     int count;
  43. };
  44.  
  45.  
  46. static LinkedList* allocate_list () {
  47.     // выделение памяти для указателя списка
  48.     LinkedList* list = (LinkedList*) calloc (1, sizeof(LinkedList));
  49.     return list;
  50. }
  51.  
  52. static LinkedList* linkedlist_insert(LinkedList* list, Ht_item* item) {
  53.     // вставляем элемент в связный список
  54.     if (!list) {
  55.         LinkedList* head = allocate_list();
  56.         head->item = item;
  57.         head->next = NULL;
  58.         list = head;
  59.         return list;
  60.     }
  61.    
  62.     else if (list->next == NULL) {
  63.         LinkedList* node = allocate_list();
  64.         node->item = item;
  65.         node->next = NULL;
  66.         list->next = node;
  67.         return list;
  68.     }
  69.  
  70.     LinkedList* temp = list;
  71.     while (temp->next) {
  72.         temp = temp->next;
  73.     }
  74.    
  75.     LinkedList* node = allocate_list();
  76.     node->item = item;
  77.     node->next = NULL;
  78.     temp->next = node;
  79.    
  80.     return list;
  81. }
  82.  
  83. static Ht_item* linkedlist_remove(LinkedList* list) {
  84.     // удаление хеда связного списка
  85.     if (!list)
  86.         return NULL;
  87.     if (!list->next)
  88.         return NULL;
  89.     LinkedList* node = list->next;
  90.     LinkedList* temp = list;
  91.     temp->next = NULL;
  92.     list = node;
  93.     Ht_item* it = NULL;
  94.     memcpy(temp->item, it, sizeof(Ht_item));
  95.     free(temp->item->key);
  96.     free(temp->item->value);
  97.     free(temp->item);
  98.     free(temp);
  99.     return it;
  100. }
  101.  
  102. static void free_linkedlist(LinkedList* list) {
  103.     LinkedList* temp = list;
  104.     if (!list)
  105.         return;
  106.     while (list) {
  107.         temp = list;
  108.         list = list->next;
  109.         free(temp->item->key);
  110.         free(temp->item->value);
  111.         free(temp->item);
  112.         free(temp);
  113.     }
  114. }
  115.  
  116. static LinkedList** create_overflow_buckets(HashTable* table) {
  117.     // создание переполнения массива связных списков
  118.     LinkedList** buckets = (LinkedList**) calloc (table->size, sizeof(LinkedList*));
  119.     for (int i=0; i<table->size; i++)
  120.         buckets[i] = NULL;
  121.     return buckets;
  122. }
  123.  
  124. static void free_overflow_buckets(HashTable* table) {
  125.     // очищение всех списков массивов переполнения
  126.     LinkedList** buckets = table->overflow_buckets;
  127.     for (int i=0; i<table->size; i++)
  128.         free_linkedlist(buckets[i]);
  129.     free(buckets);
  130. }
  131.  
  132.  
  133. Ht_item* create_item(char* key, char* value) {
  134.     // создание указателя на новую хеш-таблицу
  135.     Ht_item* item = (Ht_item*) malloc (sizeof(Ht_item));
  136.     item->key = (char*) calloc (strlen(key) + 1, sizeof(char));
  137.     item->value = (char*) calloc (strlen(value) + 1, sizeof(char));
  138.    
  139.     strcpy(item->key, key);
  140.     strcpy(item->value, value);
  141.  
  142.     return item;
  143. }
  144.  
  145. HashTable* create_table(int size) {
  146.     // создание новой хеш-таблицы
  147.     HashTable* table = (HashTable*) malloc (sizeof(HashTable));
  148.     table->size = size;
  149.     table->count = 0;
  150.     table->items = (Ht_item**) calloc (table->size, sizeof(Ht_item*));
  151.     for (int i=0; i<table->size; i++)
  152.         table->items[i] = NULL;
  153.     table->overflow_buckets = create_overflow_buckets(table);
  154.  
  155.     return table;
  156. }
  157.  
  158. void free_item(Ht_item* item) {
  159.     // очищение эелементов
  160.     free(item->key);
  161.     free(item->value);
  162.     free(item);
  163. }
  164.  
  165. void free_hashtable(HashTable* table) {
  166.     // очищение таблицы
  167.     for (int i=0; i<table->size; i++) {
  168.         Ht_item* item = table->items[i];
  169.         if (item != NULL)
  170.             free_item(item);
  171.     }
  172.  
  173.     free_overflow_buckets(table);
  174.     free(table->items);
  175.     free(table);
  176. }
  177.  
  178. void handle_collision(HashTable* table, unsigned long index, Ht_item* item) {
  179.     LinkedList* head = table->overflow_buckets[index];
  180.  
  181.     if (head == NULL) {
  182.         // создаем список
  183.         head = allocate_list();
  184.         head->item = item;
  185.         table->overflow_buckets[index] = head;
  186.         return;
  187.     }
  188.     else {
  189.         // вставляем в список
  190.         table->overflow_buckets[index] = linkedlist_insert(head, item);
  191.         return;
  192.     }
  193.  }
  194.  
  195. void ht_insert(HashTable* table, char* key, char* value) {
  196.     // создаем элемент
  197.     Ht_item* item = create_item(key, value);
  198.  
  199.     // вычисляем индекс
  200.     int index = hash_function(key);
  201.  
  202.     Ht_item* current_item = table->items[index];
  203.    
  204.     if (current_item == NULL) {
  205.         // ключ не существует
  206.         if (table->count == table->size) {
  207.             // хеш-таблица переполнена
  208.             printf("Insert Error: Hash Table is full\n");
  209.             // удалить созданный элемент
  210.             free_item(item);
  211.             return;
  212.         }
  213.        
  214.         // вставить напрямую
  215.         table->items[index] = item;
  216.         table->count++;
  217.     }
  218.  
  219.     else {
  220.             // Сценарий 1: нам нужно обновить только value
  221.             if (strcmp(current_item->key, key) == 0) {
  222.                 free(table->items[index]->value);
  223.                 table->items[index]->value = (char*) calloc (strlen(value) + 1, sizeof(char));
  224.                 strcpy(table->items[index]->value, value);
  225.                 free_item(item);
  226.                 return;
  227.             }
  228.    
  229.         else {
  230.             // Сценарий 2: коллизия
  231.             handle_collision(table, index, item);
  232.             return;
  233.         }
  234.     }
  235. }
  236.  
  237. char* ht_search(HashTable* table, char* key) {
  238.     // Searches the key in the hashtable
  239.     // and returns NULL if it doesn't exist
  240.     int index = hash_function(key);
  241.     Ht_item* item = table->items[index];
  242.     LinkedList* head = table->overflow_buckets[index];
  243.  
  244.     // Ensure that we move to items which are not NULL
  245.     while (item != NULL) {
  246.         if (strcmp(item->key, key) == 0)
  247.             return item->value;
  248.         if (head == NULL)
  249.             return NULL;
  250.         item = head->item;
  251.         head = head->next;
  252.     }
  253.     return NULL;
  254. }
  255.  
  256. void ht_delete(HashTable* table, char* key) {
  257.     // удаление элементов из таблицы
  258.     unsigned long index = hash_function(key);
  259.     Ht_item* item = table->items[index];
  260.     LinkedList* head = table->overflow_buckets[index];
  261.  
  262.     if (item == NULL) {
  263.         // не существует
  264.         return;
  265.     }
  266.     else {
  267.         if (head == NULL && strcmp(item->key, key) == 0) {
  268.             // нет цепочки коллизии. удалить элемент
  269.             // и установить индекс таблицы на ноль
  270.             table->items[index] = NULL;
  271.             free_item(item);
  272.             table->count--;
  273.             return;
  274.         }
  275.         else if (head != NULL) {
  276.             // цепочка коллизий существует
  277.             if (strcmp(item->key, key) == 0) {
  278.                 // удалить этот элемент и установить заголовок списка
  279.                 // как новый элемент
  280.                
  281.                 free_item(item);
  282.                 LinkedList* node = head;
  283.                 head = head->next;
  284.                 node->next = NULL;
  285.                 table->items[index] = create_item(node->item->key, node->item->value);
  286.                 free_linkedlist(node);
  287.                 table->overflow_buckets[index] = head;
  288.                 return;
  289.             }
  290.  
  291.             LinkedList* curr = head;
  292.             LinkedList* prev = NULL;
  293.            
  294.             while (curr) {
  295.                 if (strcmp(curr->item->key, key) == 0) {
  296.                     if (prev == NULL) {
  297.                         // первый элемент цеполчки. удалить цепочку
  298.                         free_linkedlist(head);
  299.                         table->overflow_buckets[index] = NULL;
  300.                         return;
  301.                     }
  302.                     else {
  303.                         // в цепочке
  304.                         prev->next = curr->next;
  305.                         curr->next = NULL;
  306.                         free_linkedlist(curr);
  307.                         table->overflow_buckets[index] = head;
  308.                         return;
  309.                     }
  310.                 }
  311.                 curr = curr->next;
  312.                 prev = curr;
  313.             }
  314.  
  315.         }
  316.     }
  317.  
  318. }
  319.  
  320. void print_search(HashTable* table, char* key) {
  321.     char* val;
  322.     if ((val = ht_search(table, key)) == NULL) {
  323.         printf("%s does not exist\n", key);
  324.         return;
  325.     }
  326.     else {
  327.         printf("Key:%s, Value:%s\n", key, val);
  328.     }
  329. }
  330.  
  331. void print_hashtable(HashTable* table) {
  332.     printf("\n-------------------\n");
  333.     for (int i=0; i<table->size; i++) {
  334.         if (table->items[i]) {
  335.             printf("Index:%d, Key:%s, Value:%s", i, table->items[i]->key, table->items[i]->value);
  336.             if (table->overflow_buckets[i]) {
  337.                 printf(" => Overflow Bucket => ");
  338.                 LinkedList* head = table->overflow_buckets[i];
  339.                 while (head) {
  340.                     printf("Key:%s, Value:%s ", head->item->key, head->item->value);
  341.                     head = head->next;
  342.                 }
  343.             }
  344.             printf("\n");
  345.         }
  346.     }
  347.     printf("-------------------\n");
  348. }
  349.  
  350.  
  351. int main() {
  352.     char key[256],value[256];
  353.     int n;
  354.     cout << "Введите количество элементов таблицы: ";
  355.     cin >> n;
  356.     cin.ignore();
  357.     HashTable* ht = create_table(CAPACITY);
  358.     for(int i=0;i<n;i++){
  359.         cout << "Введите ключ: ";
  360.         cin.getline(key,256);
  361.         cout << "Введите значение: ";
  362.         cin.getline(value,256);
  363.         ht_insert(ht, key, value);
  364.         print_search(ht, key);
  365.         print_search(ht, value);
  366.     }
  367.    
  368.    
  369.     /*ht_insert(ht, "1", "First address");
  370.     ht_insert(ht, "2", "Second address");
  371.     ht_insert(ht, "Hel", "Third address");
  372.     ht_insert(ht, "Cau", "Fourth address");
  373.     print_search(ht, "1");
  374.     print_search(ht, "2");
  375.     print_search(ht, "3");
  376.     print_search(ht, "Hel");
  377.     print_search(ht, "Cau"); // коллизия!*/
  378.    
  379.    
  380.     print_hashtable(ht);
  381.     ht_delete(ht, key);
  382.     ht_delete(ht, value);
  383.     print_hashtable(ht);
  384.     free_hashtable(ht);
  385.     return 0;
  386. }
  387.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement