Advertisement
Guest User

Untitled

a guest
Dec 9th, 2019
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.52 KB | None | 0 0
  1. /** Jest to przykład bardzo prostej listy jednokierunkowej w języku
  2.  * Ansi C. Aby nie komplikować przykładu jako typ przechowywany
  3.  * zastosowano proste wartości typu INT w prawdziwych zastosowaniach należy
  4.  * przygotować odpowiednio wersje generyczne umożliwiające przechowywanie
  5.  * różnych typów danych co w języku C możliwe jest jedynie za pomocą jedynego
  6.  * typu generycznego void*
  7.  */
  8.  
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12.  
  13.  
  14.  /** Podstawowa struktura przechowująca pojedynczy węzeł listy
  15.   *     w zmiennej int val przechowywana jest właściwa dana
  16.   *     natomiast wskaźnik next będący tego samego typu jak struktura
  17.   *     pokazuje na następny element na liście.
  18.   *     Dodatkowa instrukcja typedef node_t umożlwia w języku ANSI C utworzenie typu pochodnego
  19.   *     struct node, tak aby za każdym razem nie trzeba było pisać struct node
  20.   *     Dodatkowe informacje na temat samych struktur możemy znaleźć tutaj:
  21.   * https://pl.wikibooks.org/wiki/C/Typy_z%C5%82o%C5%BCone
  22.   *
  23.   */
  24. typedef struct node {
  25.     int val;
  26.     struct node* next;
  27. } node_t;
  28.  
  29.  
  30. /* create_node tworzy nowy element listy na stercie i zwraca wskaźnik do tego elementu
  31.  * W przypadku gdy funkcja malloc nie powiedzie zzwraca NULL co oznacza to ze nie możemy zaalokować pamięci
  32.  * i zwracana jest wartość NULL.
  33.  * Utworzenie nowego węzła polega na zaalokowaniu pamięci dla tego węzła a następnie w
  34.  * zaalokowanej pamięci przechowującej strukturę do pola val wpisywana jest wartość
  35.  * do przechowania, natomiast pole -> next ustawiane jest na NULL ponieważ to jest
  36.  * ostatni element na liście.
  37.  * Więcej informacji na temat alokowania pamięci na stercie za pomocą funkcji malloc
  38.  * możemy znaleźć tutaj:
  39.  * https://pl.wikibooks.org/wiki/C/malloc
  40.  */
  41. node_t* create_node(int val)
  42. {
  43.     node_t* head = NULL;
  44.     head = malloc(sizeof(node_t));
  45.     if (head == NULL) {
  46.         return NULL;
  47.     }
  48.  
  49.     head->val = val;
  50.     head->next = NULL;
  51. }
  52.  
  53.  
  54. /** Funkcja print_list przechodzi przez wszystkie elementy listy
  55.  * oraz wypisuje zawartość wszystkich elementów. Jest to zatem operacja która
  56.  * w skrypcie została nazwana przejsciem przez liste.
  57.  * Funkcja rozpoczyna działanie od przypisania wskażnikowi na bieżący element
  58.  * current głowy listy a następnie przejście za pomocą instrukcji while przez wszystkie elementy listy.
  59.  * Instrukcja warunkowa while sprawdza czy wartość logiczna w wyrażeniu jest prawdziwa, jeśli nie jest prawdziwa
  60.  * to kończy działanie. Natomiast jeśli jest prawdziwa to wykonuje instrukcje znajdującą się za while, a następnie
  61.  * przechodzi kolejny raz do sprawdzenia warunku i cykl zaczyna się od początku, aż do momentu
  62.  * gdy wyrażenie będzie fałszywe.  W przypadku przechodzeniu przez wszystkie elementy listy instrukcję wykonujemy do czasu
  63.  * gdy zmienna current przyjmie wartość NULL co oznacza że dotarliśmy do ostatniego elementu listy.
  64.  * Więcej na temat instrukcji sterujących możemy znaleźć tutaj.
  65.  * https://pl.wikibooks.org/wiki/C/Instrukcje_steruj%C4%85ce#while
  66.  *
  67.  */
  68. void print_list(node_t* head)
  69. {
  70.     node_t* current = head;
  71.  
  72.     while (current != NULL) {
  73.         printf("%d\n", current->val);
  74.         current = current->next;
  75.     }
  76. }
  77.  
  78. /** Przy liście jednokierunkowej wstawienie elementu na ostatnią pozycję wymaga przejścia przez wszystkie
  79.  * elementy tej listy aż do końca a następnie doczepienie na końcu nowego elementu.
  80.  * Przejście przez wszystkie elementy realizowane jest przez pętlę while, gdzie po dotarciu do ostatniego elementu,
  81.  * do zmiennej current->next wskazującej na ostatni element, wpisywany jest adres nowego obszaru pamięci dla nowo utworzonego
  82.  * węzła, co powoduje zamazanie poprzednio znajdującej się wartości NULL.
  83.  * Następnie do nowego węzła przypisywana jest wartość val a na zakończenie wskaźnik wskaźnik next nowego węzła ustawiany jest na NULL
  84.  * co jest znacznikiem ostatniego elementu na liście. */
  85.  
  86. void insert_end(node_t* head, int val)
  87. {
  88.     node_t* current = head;
  89.     while (current->next != NULL) {
  90.         current = current->next;
  91.     }
  92.  
  93.     /* now we can add a new variable */
  94.     current->next = malloc(sizeof(node_t));
  95.     current->next->val = val;
  96.     current->next->next = NULL;
  97. }
  98.  
  99.  
  100. /** Funkcja dopisuje nowy element na początku listy,
  101.  * nie musimy przechodzić przez wszystkie elementy.
  102.  * Funkcja przyjmuje wskaźnik do wskaźnika na listę (co umożliwia zwrócenie wartości z funkcji)
  103.  * Napierw za pomocą funkcji malloc alokowany jest nowwy węzeł, następnie do tego węzła wpisywana jest wartość
  104.  * a do pola next wpisywany jest wskaźnik na węzęł stanowiący poprzednio pierwszy element.
  105.  * Następnie wskaźnik do początku listy zmieniany jest na nowo zaalokowany węzeł. Tym sposobem nowo utworzony węzeł
  106.  * staje się pierwszy natomiast poprzednia głowa listy doczepiana jest za pierwszym elementem.
  107.  */
  108. void insert_begin(node_t** head, int val)
  109. {
  110.     node_t* new_node;
  111.     new_node = malloc(sizeof(node_t));
  112.     new_node->val = val;
  113.     new_node->next = *head;
  114.     *head = new_node;
  115. }
  116.  
  117.  
  118. /** Usunięcie pierwszego elementu na liscie jest badzo podobne, jednak wymaga sprawdzenia kilku
  119.  * warunkow. Na początek sprawdzamy czy wskaźnik na głowe listy nie jest nullem co oznacza że znajujemy się
  120.  *  w ostatnim węźle i nie ma nic do usunicia.
  121.  *  Następnie , wzkaźnikowi na następny węzęł (next_node) przypisujemy wartośc drugiego węzła od głowy.
  122.  *  ,a pamięc przechowującą aktualną głowę usuwamy. Następnie do wkaźnika na początek listy *head przypisujemy
  123.  *  wartość zmiennej new_node. W ten sposób drugi element staje się nową głową listy.
  124.  */
  125. int remove_first(node_t** head)
  126. {
  127.     int retval = -1;
  128.     node_t* next_node = NULL;
  129.  
  130.     if (*head == NULL) {
  131.         return -1;
  132.     }
  133.  
  134.     next_node = (*head)->next;
  135.     retval = (*head)->val;
  136.     free(*head);
  137.     *head = next_node;
  138.  
  139.     return retval;
  140. }
  141.  
  142.  
  143. /** W przypadku usunięcia ostatniego elementu listy , sytuacja jest podobna do poprzedniego przypadku jednak
  144.  * mamy dodatkowe warunki
  145.  * jeśli jest to jedyny element na liście to usuwamy go, jeśli elementów jest więcej to przechodzimy
  146.  * do końca listy, a następnie usuwamy ostati element.
  147.  */
  148. int remove_last(node_t* head) {
  149.     int retval = 0;
  150.     /* Jeśli jest to jedyny element na liście to usuwamy go */
  151.     if (head->next == NULL) {
  152.         retval = head->val;
  153.         free(head);
  154.         return retval;
  155.     }
  156.  
  157.     /* Jeśli jest więcej elementów przechodzimy przez wszystkie węzły aż do końca */
  158.     node_t* current = head;
  159.     while (current->next->next != NULL) {
  160.         current = current->next;
  161.     }
  162.  
  163.     /* Aktualnie jesteśmy na końcu listy więc możemy usunąć węzeł końcowy a wskaźnikowi
  164.      * na następny przypisać wartość NULL */
  165.     retval = current->next->val;
  166.     free(current->next);
  167.     current->next = NULL;
  168.     return retval;
  169.  
  170. }
  171.  
  172. int remove_by_index(node_t** head, int n);
  173. int remove_by_val(node_t** head, int n);
  174.  
  175. int main() {
  176.     //! Wskaźnik do głowy listy
  177.     node_t* list;
  178.     list = create_node(1);
  179.     insert_end(list, 2);
  180.     insert_end(list, 3);
  181.     insert_end(list, 4);
  182.     insert_end(list, 5);
  183.     insert_end(list, 6);
  184.     print_list(list);
  185.     remove_by_index(&list, 0);
  186.     printf("------------------\n");
  187.     print_list(list);
  188.     printf("------------------\n");
  189.     remove_by_val(&list, 5);
  190.     print_list(list);
  191.  
  192.  
  193.     // Usuń pierwszy i ostatni element
  194.     //remove_first(&list);
  195.     //remove_last(list);
  196.     // Wypisz wszystkie elemnty na liście teraz lista zawiera wartości od 2 do 5
  197.     // usunieto pierwszy element z początku i końca listy
  198.  
  199. }
  200.  
  201. int remove_by_index(node_t** head, int n) {
  202.     int retval = -1;
  203.  
  204.     node_t* currentHead = *head;
  205.     node_t* tmp_node = NULL;
  206.  
  207.     if (*head == NULL)
  208.         return -1;
  209.  
  210.     if (n == 0)
  211.         return remove_first(head);
  212.  
  213.     for (int i = 0; i < n - 1; i++) {
  214.         if (currentHead->next == NULL) {
  215.             return -1;
  216.         }
  217.         currentHead = currentHead->next;
  218.     }
  219.  
  220.     tmp_node = currentHead->next;
  221.     retval = tmp_node->val;
  222.     currentHead->next = tmp_node->next;
  223.     free(tmp_node);
  224.  
  225.     return retval;
  226. }
  227.  
  228. int remove_by_val(node_t** head, int n) {
  229.     int retval = -1;
  230.     int tmp = 0;
  231.     node_t* currentHead = *head;
  232.     node_t* tmp_node = NULL;
  233.  
  234.     while (currentHead != NULL) {
  235.         tmp = currentHead->val;
  236.  
  237.         if (tmp == n && currentHead->next != NULL) {
  238.             tmp_node = currentHead->next;
  239.             currentHead->next = currentHead->next->next;
  240.             free(tmp_node);
  241.             return retval;
  242.         }
  243.  
  244.         if (tmp == n && currentHead->next == NULL) {
  245.             remove_last(*head);
  246.             return retval;
  247.         }
  248.  
  249.         if (currentHead->next == NULL) {
  250.             printf("nie ma takiej wartosci na liscie");
  251.             return retval;
  252.         }
  253.         currentHead = currentHead->next;
  254.     }
  255. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement