Advertisement
m4ly

LinkedList

May 17th, 2014
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.31 KB | None | 0 0
  1. /*
  2.  
  3. Potrzebny plik: D:\db.txt z danymi np:
  4. Frederik|Doane|2
  5. Kate|Wank|6
  6. Law|Harasymiak|3
  7. Fairy|Pannone|1
  8. Ripley|Loster|8
  9. Trenna|Jacob|7
  10. Evin|Nicholls|5
  11. Abbie|Backman|4
  12. Tybalt|Fargo|10
  13. Becka|Nitabach|9
  14.  
  15. */
  16. #include <stdlib.h> // dla NULL
  17. #include <stdio.h> // dla printf
  18. #include <stdbool.h> // dla bool oraz false i true
  19. #include <string.h> // dla memcpy, memset i strcmp
  20. #include <stdarg.h> //dla va_list, va_arg, va_start|_end
  21. #include "Windows.h" // dla milliseconds_now()
  22.  
  23. void remove_tail(struct sNode **head);
  24. void remove_head(struct sNode **head);
  25.  
  26. enum SinglyLinkedListPushMethod { PUSH_FRONT = 0, PUSH_BACK = 1 };
  27. enum PersonFilterOptions { PERSON = 0, NAME = 1, SURNAME = 2, AGE = 3 };
  28. enum StringCompareStyle { CASE_SENSITIVE = 0, CASE_INSENSITIVE = 1 };
  29. /*
  30. Struktura reprezentująca osobę
  31. */
  32. struct sPerson
  33. {
  34.     char *name;
  35.     char *surname;
  36.     unsigned short int age;
  37. };
  38.  
  39. /*
  40. Struktura reprezentująca węzeł w liście jednokierunkowej
  41. */
  42. struct sNode
  43. {
  44.     struct sPerson *person;
  45.     struct sNode *next;
  46. };
  47.  
  48. // Nie dotykać
  49. const size_t SIZE_T_UINT = sizeof(unsigned short int);
  50. const size_t SIZE_T_CHAR = sizeof(char);
  51. const size_t SIZE_T_NODE = sizeof(struct sNode);
  52. const size_t SIZE_T_PERSON = sizeof(struct sPerson);
  53.  
  54.  
  55. void error_alloc_person(struct sPerson **person, const char *msg)
  56. {
  57.     free(*person);
  58.     fprintf(stderr, "struct person* memory allocation error: %s\n", msg);
  59.     *person = NULL;
  60.     getchar();
  61.     exit(EXIT_FAILURE);
  62. }
  63.  
  64. void error_alloc_char(char **c, const char *msg)
  65. {
  66.     free(*c);
  67.     fprintf(stderr, "char* memory allocation error: %s\n", msg);
  68.     *c = NULL;
  69.     getchar();
  70.     exit(EXIT_FAILURE);
  71. }
  72.  
  73. void error_alloc_node(struct sNode **node, const char *msg)
  74. {
  75.     free(*node);
  76.     fprintf(stderr, "struct node* memory allocation error: %s", msg);
  77.     *node = NULL;
  78.     getchar();
  79.     exit(EXIT_FAILURE);
  80. }
  81.  
  82. /*
  83. Zwraca ilość pamięci zajmowaną przez pola w strukturze osoba
  84. */
  85. size_t person_mem_size(struct sPerson *person)
  86. {
  87.     // ilosc * wielkosc typu
  88.     // char* zajmuje de facto o jeden więcej bajt - dla znaku końca stringu czyli NULL -> '\0'
  89.     // ponieważ mamy 2 stringi mamy dwa ekstra znaki '\0' do dodania stąd: (2 * SIZE_T_CHAR)
  90.     return ((strlen(person->name) * SIZE_T_CHAR) + (strlen(person->surname) * SIZE_T_CHAR) + SIZE_T_UINT + (2 * SIZE_T_CHAR));
  91. }
  92.  
  93. struct sPerson *alloc_person(char *imie, char *nazwisko, unsigned int wiek)
  94. {
  95.     size_t name_real_size, surname_real_size;
  96.  
  97.     struct sPerson *new_person = (struct sPerson *)malloc(SIZE_T_PERSON);
  98.    
  99.     if (new_person == NULL)
  100.         error_alloc_person(&new_person, "new_person, alloc_person()");
  101.  
  102.     if (imie == NULL)
  103.         new_person->name = NULL;
  104.     else
  105.     {
  106.         name_real_size = ((SIZE_T_CHAR * strlen(imie)) + SIZE_T_CHAR);
  107.         new_person->name = (char *)malloc(name_real_size);
  108.    
  109.         if (!new_person->name)  
  110.             error_alloc_char(&new_person->name, "name, alloc_person()");
  111.        
  112.         memset(new_person->name, 0, name_real_size);
  113.         memcpy(new_person->name, imie, name_real_size - SIZE_T_CHAR);
  114.     }
  115.  
  116.     if (nazwisko == NULL)
  117.         new_person->surname = NULL;
  118.     else
  119.     {
  120.         surname_real_size = ((SIZE_T_CHAR * strlen(nazwisko)) + SIZE_T_CHAR);
  121.         new_person->surname = (char *)malloc(surname_real_size);
  122.        
  123.         if (!new_person->surname)
  124.             error_alloc_char(&new_person->surname, "surname, alloc_person()");
  125.        
  126.         memset(new_person->surname, 0, surname_real_size);
  127.         memcpy(new_person->surname, nazwisko, surname_real_size - SIZE_T_CHAR);
  128.     }
  129.  
  130.     new_person->age = wiek;
  131.  
  132.     return new_person;
  133. }
  134.  
  135. void cpy_person(struct sPerson **dest, const struct sPerson *source)
  136. {
  137.     *dest = alloc_person(source->name, source->surname, source->age);
  138. }
  139.  
  140. bool person_cmp(const struct sPerson *person1, const struct sPerson *person2)
  141. {
  142.     return ((strcmp(person1->name, person2->name) == 0) && (strcmp(person1->surname, person2->surname) == 0) && (person1->age == person2->age));
  143. }
  144.  
  145. void free_person(struct sPerson *person)
  146. {
  147.     free(person->name);
  148.     person->name = NULL;
  149.  
  150.     free(person->surname);
  151.     person->surname = NULL;
  152.  
  153.     person = NULL;
  154. }
  155.  
  156. void free_node(struct sNode *node)
  157. {
  158.     free_person(node->person);
  159.     free(node);
  160.     node = NULL;
  161. }
  162.  
  163. long long milliseconds_now()
  164. {
  165.     static LARGE_INTEGER s_frequency;
  166.     BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
  167.     if (s_use_qpc)
  168.     {
  169.         LARGE_INTEGER now;
  170.         QueryPerformanceCounter(&now);
  171.         return (1000LL * now.QuadPart) / s_frequency.QuadPart;
  172.     }
  173.     else
  174.     {
  175.         return GetTickCount();
  176.     }
  177. }
  178.  
  179. /*
  180. Dodaje osobę na początek listy jednokierunkowej
  181. Bez sortowania
  182. */
  183. void push_front(struct sNode **head, struct sPerson *person)
  184. {
  185.  
  186.     // Jeśli początek jest null to glowa = nowy element
  187.     if (*head == NULL)
  188.     {
  189.         *head = (struct sNode *)malloc(SIZE_T_NODE);
  190.         if (!*head) error_alloc_node(head, "head, insert_front()");
  191.  
  192.         (*head)->person = person;
  193.         (*head)->next = NULL;
  194.  
  195.     }
  196.     else
  197.     {
  198.         struct sNode *nowy = (struct sNode *)malloc(SIZE_T_NODE);
  199.         if (!nowy) error_alloc_node(&nowy, "nowy, insert_front()");
  200.  
  201.         nowy->person = person;
  202.         nowy->next = *head;
  203.         *head = nowy;
  204.     }
  205. }
  206.  
  207. /*
  208. Dodaje osobę na koniec listy jednokierunkowej
  209. Bez sortowania
  210. */
  211. void push_back(struct sNode **head, struct sPerson *person)
  212. {
  213.  
  214.     // Jeśli początek jest null to glowa = nowy element
  215.     if (*head == NULL)
  216.     {
  217.  
  218.         *head = (struct sNode *)malloc(SIZE_T_NODE);
  219.         if (!*head) error_alloc_node(head, "nowy, insert_back()");
  220.  
  221.         (*head)->person = person;
  222.         (*head)->next = NULL;
  223.     }
  224.     else
  225.     {
  226.         struct sNode *node = *head;
  227.         for (; node->next != NULL; node = node->next);
  228.  
  229.         node->next = (struct sNode *)malloc(SIZE_T_NODE);
  230.         if (!node->next) error_alloc_node(&node->next, "node->next, insert_back()");
  231.  
  232.         node->next->next = NULL;
  233.         node->next->person = person;
  234.     }
  235.  
  236. }
  237.  
  238. // Zwalania pamięć zare. przez listę jednokierunkową
  239. void destroy(struct sNode **head)
  240. {
  241.     struct sNode * tmp = NULL;
  242.     for (; tmp != NULL;)
  243.     {
  244.         tmp = (*head)->next;
  245.  
  246.         // Zwlania węzeł
  247.         free_node(*head);
  248.         *head = tmp;
  249.     }
  250.  
  251.     *head = NULL;
  252. }
  253.  
  254. void list(struct sNode *head)
  255. {
  256.     for (; head != NULL; head = head->next)
  257.         printf("%s %s %d | %p -> %p\n", head->person->name, head->person->surname, head->person->age, head, head->next);
  258. }
  259.  
  260. unsigned int size(struct sNode *head)
  261. {
  262.     unsigned int size = 0;
  263.     for (; head != NULL; head = head->next)
  264.         ++size;
  265.  
  266.     return size;
  267. }
  268.  
  269.  
  270. void split(const int ile)
  271. {
  272.  
  273. }
  274. /*
  275. Odwaraca listę. Ogon jest głową a głowa->next wskazuje na NULL`a
  276. */
  277. struct sNode *reverse(struct sNode **head)
  278. {
  279.     struct sNode* new_head = NULL;
  280.     while ((*head) != NULL)
  281.     {
  282.         struct sNode * next = (*head)->next;
  283.         (*head)->next = new_head;
  284.         new_head = *head;
  285.         *head = next;
  286.     }
  287.     return new_head;
  288. }
  289.  
  290. /*
  291. Łączy `n` ilość list. Zwraca nową listę w tym nowo przydzieloną pamięc dla każdej zmiennej dynamiczych w jej strukturze(sNode).
  292.  
  293. Przykład 1 push_back() - opcja wolniejsza z racji działania funkcji push_back()
  294. Dodajemy do siebie 5 list używjąc wywołania push_back():
  295.     NowaLista = join_multi(PUSH_BACK, 5, Lista1, Lista2, Lista3, Lista4, Lista5);
  296.  
  297. Przykład 2 push_front - opcja najszybsza z racji działa funkcji push_front()
  298. Dodajemy do siebie 5 list używjąc wywołania push_front()
  299.     NowaLista = join_multi(PUSH_FRONT, 5, Lista1, Lista2, Lista3, Lista4, Lista5 );
  300.  
  301. */
  302. struct sNode *join_multi(const enum SinglyLinkedListPushMethod push_method, const int number_of_sll, ...)
  303. {
  304.     struct sNode *new_ssl = NULL;
  305.     va_list vl;
  306.     int i;
  307.     va_start(vl, number_of_sll);
  308.     for (i = 0; i < number_of_sll; i++)
  309.     {
  310.         struct sNode *lista = va_arg(vl, struct sNode *);
  311.         switch (push_method)
  312.         {
  313.         case PUSH_BACK:
  314.         {
  315.                           for (; lista != NULL; lista = (lista)->next)
  316.                               push_back(&new_ssl, alloc_person((lista)->person->name, (lista)->person->surname, (lista)->person->age));
  317.         }
  318.             break;
  319.  
  320.         default:
  321.         case PUSH_FRONT:
  322.         {
  323.                            for (; lista != NULL; lista = (lista)->next)
  324.                                push_front(&new_ssl, alloc_person((lista)->person->name, (lista)->person->surname, (lista)->person->age));
  325.  
  326.         }
  327.             break;
  328.        
  329.         }
  330.     }
  331.     va_end(vl);
  332.     return new_ssl;
  333. }
  334.  
  335. /*
  336. Tworzy NOWĄ listę jednokierunkową
  337. */
  338. struct sNode * join_two(struct sNode *ssl1, struct sNode *ssl2)
  339. {
  340.     struct sNode *new_ssl = NULL;
  341.  
  342.     for (; ssl1 != NULL; ssl1 = ssl1->next)
  343.         push_back(&new_ssl, alloc_person((ssl1)->person->name, (ssl1)->person->surname, (ssl1)->person->age));
  344.  
  345.     for (; ssl2 != NULL; ssl2 = ssl2->next)
  346.         push_back(&new_ssl, alloc_person((ssl2)->person->name, (ssl2)->person->surname, (ssl2)->person->age));
  347.  
  348.     return new_ssl;
  349. }
  350.  
  351. void remove_by_person(struct sNode **head, struct sPerson *person)
  352. {
  353.     struct sNode* current = *head;
  354.     struct sNode* previous = NULL;
  355.  
  356.     for (; current != NULL; current = current->next)
  357.     {
  358.         if (person_cmp(current->person, person) == true)
  359.         {
  360.             if (previous == NULL)
  361.             {
  362.                 current = current->next;
  363.                 remove_head(head);
  364.             }
  365.             else
  366.             {
  367.                 previous->next = current->next;
  368.                 free_node(current);
  369.                 current = previous->next;
  370.             }
  371.         }
  372.         else
  373.             previous = current;
  374.     }
  375. }
  376. void remove_by_person_name(struct sNode **head, const char *name)
  377. {
  378.  
  379.     struct sNode* current = *head;
  380.     struct sNode* previous = NULL;
  381.  
  382.     for (; current != NULL; current = current->next)
  383.     {
  384.         if (strcmp(current->person->name, name) == 0)
  385.         {
  386.             if (previous == NULL)
  387.             {
  388.                 current = current->next;
  389.                 remove_head(head);
  390.             }
  391.             else
  392.             {
  393.                 previous->next = current->next;
  394.                 free_node(current);
  395.                 current = previous;
  396.             }
  397.         }
  398.         else
  399.             previous = current;
  400.     }
  401. }
  402. void remove_by_person_surname(struct sNode **head, const char *surname)
  403. {
  404.     struct sNode* current = *head;
  405.     struct sNode* previous = NULL;
  406.  
  407.     for (; current != NULL; current = current->next)
  408.     {
  409.         if (strcmp(current->person->surname, surname) == 0)
  410.         {
  411.             if (previous == NULL)
  412.             {
  413.                 current = current->next;
  414.                 remove_head(head);
  415.             }
  416.             else
  417.             {
  418.                 previous->next = current->next;
  419.                 free_node(current);
  420.                 current = previous;
  421.             }
  422.         }
  423.         else
  424.             previous = current;
  425.     }
  426. }
  427. void remove_by_person_age(struct sNode **head, const unsigned short int min_age, const unsigned short int  max_age)
  428. {
  429.     if (max_age < min_age || min_age > max_age)
  430.         return;
  431.  
  432.     struct sNode* current = *head;
  433.     struct sNode* previous = NULL;
  434.    
  435.     for (; current != NULL; current = current->next)
  436.     {
  437.         if (current->person->age >= min_age && current->person->age <= max_age)
  438.         {
  439.             if (previous == NULL)
  440.             {
  441.                 current = current->next;
  442.                 remove_head(head);
  443.             }
  444.             else
  445.             {
  446.                 previous->next = current->next;
  447.                 free_node(current);
  448.                 current = previous;
  449.             }
  450.         }
  451.         else
  452.             previous = current;
  453.     }
  454.  
  455. }
  456.  
  457. struct sNode * search_by_person(struct sNode *head, struct sPerson *person)
  458. {
  459.     struct sNode *new_ssl = NULL;
  460.     for (; head != NULL; head = head->next)
  461.     {
  462.         if (person_cmp(head->person, person) == true)
  463.             push_front(&new_ssl, alloc_person(head->person->name, head->person->surname, head->person->age));
  464.     }
  465.  
  466.     return new_ssl;
  467. }
  468. struct sNode * search_by_person_name(struct sNode *head, const char *name)
  469. {
  470.     struct sNode *new_ssl = NULL;
  471.     for (; head != NULL; head = head->next)
  472.     {
  473.         if (strcmp(head->person->name, name) == 0)
  474.             push_front(&new_ssl, alloc_person(head->person->name, head->person->surname, head->person->age));
  475.     }
  476.  
  477.     return new_ssl;
  478.  
  479. }
  480. struct sNode * search_by_person_surname(struct sNode *head, const char *surname)
  481. {
  482.     struct sNode *new_ssl = NULL;
  483.     for (; head != NULL; head = head->next)
  484.     {
  485.         if (strcmp(head->person->surname, surname) == 0)
  486.             push_front(&new_ssl, alloc_person(head->person->name, head->person->surname, head->person->age));
  487.     }
  488.  
  489.     return new_ssl;
  490.  
  491. }
  492. struct sNode * search_by_person_age(struct sNode *head, const unsigned short min_age, const unsigned short max_age)
  493. {
  494.     if (max_age < min_age || min_age > max_age)
  495.         return NULL;
  496.  
  497.     struct sNode *new_ssl = NULL;
  498.     for (; head != NULL; head = head->next)
  499.     {
  500.         if (head->person->age >= min_age && head->person->age <= max_age)
  501.             push_front(&new_ssl, alloc_person(head->person->name, head->person->surname, head->person->age));
  502.     }
  503.  
  504.     return new_ssl;
  505.  
  506. }
  507.  
  508.  
  509. struct sNode * diff(struct sNode *head1, struct sNode *head2)
  510. {
  511.     struct sNode *new_ssl = NULL;
  512.  
  513.  
  514.     if (head2 == NULL)
  515.         return NULL;
  516.  
  517.     while (head1 != NULL)
  518.     {
  519.         if (!(person_cmp((head1)->person, head2->person)))
  520.             push_front(&new_ssl, head2->person);
  521.         else
  522.         {
  523.             while ((head2 != NULL) && (person_cmp(head2->person, (head1)->person) == false))
  524.             {
  525.                 push_front(&new_ssl, head2->person);
  526.                 head2 = head2->next;
  527.             }
  528.  
  529.         }
  530.  
  531.         head1 = head1->next;
  532.     }
  533.     return new_ssl;
  534. }
  535.  
  536.  
  537. void remove_by_persons_va_list(struct sNode **head, unsigned int number_of_persons, ...)
  538. {
  539.  
  540. }
  541.  
  542. struct sNode * filter_by_persons_names_va_list(struct sNode **head, unsigned int number_of_names, ...)
  543. {
  544.     struct sNode *new_ssl = NULL;
  545.  
  546.     va_list vl;
  547.     unsigned int i;
  548.     va_start(vl, number_of_names);
  549.     for (i = 0; i < number_of_names; i++)
  550.     {
  551.         char *name = va_arg(vl, char *);
  552.         push_front(&new_ssl, alloc_person(name, NULL, 0));
  553.        
  554.     }
  555.     va_end(vl);
  556.  
  557.  
  558.     return NULL;
  559. }
  560.  
  561. void remove_by_persons_surnames_va_list(struct sNode **head, unsigned int number_of_surnames, ...)
  562. {
  563.  
  564. }
  565.  
  566. void remove_by_persons_ages_va_list(struct sNode **head, unsigned int number_of_ages, ...)
  567. {
  568.     bool only_one = false;
  569.     if (number_of_ages == 0)
  570.         return;
  571.  
  572.     if (number_of_ages == 1)
  573.         only_one = true;
  574.  
  575.  
  576.  
  577. }
  578.  
  579. void sort_by_person_name()
  580. {
  581.  
  582. }
  583.  
  584. void sort_by_person_surname()
  585. {
  586.  
  587. }
  588.  
  589. void bubble_sort_by_person_age(struct sNode **head)
  590. {
  591.     struct sNode *tmp = *head;
  592.     struct sNode *next = NULL;
  593.     struct sNode *prev = NULL;
  594. }
  595.  
  596. void rotate(struct sNode **head)
  597. {
  598.  
  599.     struct sNode *nastepny = NULL;
  600.     struct sNode *aktualny = NULL;
  601.  
  602.     aktualny = *head;
  603.  
  604.     // lista musi miec conajmniej dwa wezly
  605.     if (aktualny == NULL || aktualny->next == NULL)
  606.         exit(EXIT_FAILURE);
  607.  
  608.     while (aktualny->next != NULL)
  609.     {
  610.         nastepny = aktualny->next;
  611.  
  612.     aktualny = nastepny;
  613.     aktualny->next = nastepny->next;
  614.     (aktualny)->next = aktualny;
  615.  
  616.     aktualny = aktualny->next;
  617. }
  618.         int z = 9;
  619.  
  620.  
  621.  
  622.    
  623.  
  624.  
  625.  
  626.     /*for (; glowa->next != NULL; glowa = glowa->next)
  627.     {
  628.        
  629.         nastepny = glowa->next; //node1
  630.         glowa->next = nastepny->next; //node2
  631.         glowa = nastepny;
  632.                                
  633.     }*/
  634. }
  635.  
  636. void remove_tail(struct sNode **head)
  637. {
  638.     struct sNode *one_before_last = *head;
  639.     for (; one_before_last->next->next != NULL; one_before_last = one_before_last->next);
  640.  
  641.     struct sNode *last = one_before_last->next;
  642.     one_before_last->next = NULL;
  643.  
  644.     free_person(last->person);
  645.     free(last);
  646.     last = NULL;
  647.  
  648. }
  649.  
  650. void remove_head(struct sNode **head)
  651. {
  652.     // copy addr of second in list
  653.     struct sNode *tmp = (*head)->next;
  654.     free_person((*head)->person);
  655.     free(*head);
  656.     *head = tmp;
  657.  
  658. }
  659.  
  660. size_t list_mem_size(struct sNode *head)
  661. {
  662.     size_t sum = 0;
  663.     struct sNode *current = head;
  664.     int count_nodes = 0;
  665.  
  666.     while (current != NULL)
  667.     {
  668.         // zwraca ilosc pamięci zarezw. przez samego Node: czyli wielkosc wskaźnika next* + wielkosc wskaźnika person*
  669.         sum += sizeof(current);
  670.  
  671.         // zwraca ilosc pamieci zarez. przez osobe
  672.         sum += person_mem_size(current->person);
  673.  
  674.         // Node sam z siebie też jest wskaźnikiem - musimy sumować ich całkowitą liczbę i dodać przy return
  675.         count_nodes++;
  676.  
  677.         current = current->next;
  678.  
  679.     }
  680.  
  681.     return (sum + (count_nodes * SIZE_T_NODE));
  682. }
  683.  
  684.  
  685.  
  686. unsigned int load_from_csv(const char *filename, struct sNode **head)
  687. {
  688.     unsigned int size = 0;
  689.     FILE *fh = NULL;
  690.     char buffer[BUFSIZ];
  691.  
  692.     errno_t err = fopen_s(&fh, filename, "r");
  693.     if (err == 0)
  694.     {
  695.         while (fgets(buffer, sizeof(buffer), fh))
  696.         {
  697.             char *next = NULL;
  698.  
  699.             char *imie = strtok_s(buffer, "|", &next);
  700.             char *nazwisko = strtok_s(NULL, "|", &next);
  701.             char *tmp_age = strtok_s(NULL, "|", &next);
  702.             unsigned  int age = (unsigned  int)strtoul(tmp_age, NULL, 0);
  703.            
  704.             push_back(head, alloc_person(imie, nazwisko, age));
  705.             ++size;
  706.         }
  707.     }
  708.     else
  709.     {
  710.  
  711.     }
  712.  
  713.     fclose(fh);
  714.  
  715.     return size;
  716.  
  717. }
  718.  
  719.  
  720. int main(void)
  721. {
  722.     struct sNode *List1 = NULL;
  723.     unsigned int size = 0;
  724.     long long start;
  725.     int i;
  726.     start = milliseconds_now();
  727.     size = load_from_csv("D:\\db.txt", &List1);
  728.     rotate(&List1);
  729.     printf("[Load] Time taken: %lld [ms], Size = %i;\n", (milliseconds_now() - start), size);
  730.  
  731.     list(List1);
  732.  
  733.    
  734.     printf("po\n");
  735.     list(List1);
  736.  
  737.     start = milliseconds_now();
  738.     destroy(&List1);
  739.     printf("[Destroy] Time taken: %lld [ms], Size = %i\n", (milliseconds_now() - start), size);
  740.     getchar();
  741.     return 0;
  742. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement