#include #include #include #include "CircularDoublyLinkedList.h" #include "utils.h" /* * Functie care trebuie apelata pentru alocarea si initializarea unei liste. * (Setare valori initiale pentru campurile specifice structurii LinkedList). */ doubly_linked_list_t* dll_create(unsigned int data_size) { doubly_linked_list_t *list = malloc(sizeof(doubly_linked_list_t)); DIE(list == NULL, "Malloc failed\n"); list->head = NULL; list->data_size = data_size; list->size = 0; return list; } /* * Functia intoarce un pointer la nodul de pe pozitia n din lista. * Pozitiile din lista sunt indexate incepand cu 0 (i.e. primul nod din lista se * afla pe pozitia n=0). Daca n >= nr_noduri, atunci se intoarce nodul de pe * pozitia rezultata daca am "cicla" (posibil de mai multe ori) pe lista si am * trece de la ultimul nod, inapoi la primul si am continua de acolo. Cum putem * afla pozitia dorita fara sa simulam intreaga parcurgere? Daca n < 0, eroare. */ dll_node_t* dll_get_nth_node(doubly_linked_list_t* list, unsigned int n) { if (n < 0) { fprintf(stderr, "Error\n"); exit(-1); } if (list == NULL) exit(-1); if (n >= list->size) n = n % list->size; dll_node_t *curr; curr = list->head; while (n > 0) { curr = curr->next; n--; } return curr; } /* * Pe baza datelor trimise prin pointerul new_data, se creeaza un nou nod care e * adaugat pe pozitia n a listei reprezentata de pointerul list. Pozitiile din * lista sunt indexate incepand cu 0 (i.e. primul nod din lista se afla pe * pozitia n=0). Cand indexam pozitiile nu "ciclam" pe lista circulara ca la * get, ci consideram nodurile in ordinea de la head la ultimul (adica acel nod * care pointeaza la head ca nod urmator in lista). Daca n >= nr_noduri, atunci * adaugam nodul nou la finalul listei. Daca n < 0, eroare. */ void dll_add_nth_node(doubly_linked_list_t* list, unsigned int n, const void* data) { if (n < 0) { fprintf(stderr, "Error\n"); return; } if (list == NULL) return; dll_node_t *new; new = malloc(sizeof(dll_node_t)); DIE(new == NULL, "Malloc failed\n"); new->data = malloc(list->data_size); DIE(new == NULL, "Malloc failed\n"); memcpy(new->data, data, list->data_size); if (list->size == 0) { list->head = new; new->next = new; new->prev = new; list->size++; return; } dll_node_t *last; if (n > list->size) n = list->size; if (n == 0) { last = list->head->prev; new->next = list->head; new->prev = last; list->head->prev = new; list->head = new; list->size++; return; } dll_node_t *curr = list->head; while (n > 1) { curr = curr->next; n--; } new->next = curr->next; new->prev = curr; curr->next = new; curr->prev = new; list->size++; } /* * Elimina nodul de pe pozitia n din lista al carei pointer este trimis ca * parametru. Pozitiile din lista se indexeaza de la 0 (i.e. primul nod din * lista se afla pe pozitia n=0). Functia intoarce un pointer spre acest nod * proaspat eliminat din lista. Daca n >= nr_noduri - 1, se elimina nodul de la * finalul listei. Daca n < 0, eroare. Este responsabilitatea apelantului sa * elibereze memoria acestui nod. */ dll_node_t* dll_remove_nth_node(doubly_linked_list_t* list, unsigned int n) { if (n < 0) { fprintf(stderr, "Error\n"); return NULL; } if (list == NULL) return NULL; if (list->head == NULL) return NULL; if (n == 0) { dll_node_t *first, *last; first = list->head; last = first->prev; list->head = first->next; list->head->prev = first->prev; last->next = list->head; list->size--; return first; } if (n >= list->size - 1) n = list->size - 1; dll_node_t *prev, *curr; prev = list->head; curr = list->head->next; while (n > 1) { prev = curr; curr = curr->next; n--; } prev->next = curr->next; curr->next->prev = prev; list->size--; return curr; } /* * Functia intoarce numarul de noduri din lista al carei pointer este trimis ca * parametru. */ unsigned int dll_get_size(doubly_linked_list_t* list) { if (list == NULL) exit(-1); return list->size; } /* * Procedura elibereaza memoria folosita de toate nodurile din lista, iar la * sfarsit, elibereaza memoria folosita de structura lista. */ void dll_free(doubly_linked_list_t** pp_list) { if ((*pp_list)->size == 0) { free(*pp_list); *pp_list = NULL; return; } unsigned int tmp; tmp = (*pp_list)->size; dll_node_t *node; node = (*pp_list)->head; while (tmp > 0) { dll_node_t *node1 = node->next; free(node->data); free(node); node = node1; tmp--; } free(*pp_list); *pp_list = NULL; } /* * Atentie! Aceasta functie poate fi apelata doar pe liste ale caror noduri STIM * ca stocheaza int-uri. Functia afiseaza toate valorile int stocate in nodurile * din lista separate printr-un spatiu, incepand de la primul nod din lista. */ void dll_print_int_list(doubly_linked_list_t* list) { if (list == NULL) return; dll_node_t *pos = list->head; unsigned int tmp = list->size; while (tmp > 0) { printf("%d ", *((int *)pos->data)); pos = pos->next; tmp--; } printf("\n"); } /* * Atentie! Aceasta functie poate fi apelata doar pe liste ale caror noduri STIM * ca stocheaza string-uri. Functia afiseaza toate string-urile stocate in * nodurile din lista separate printr-un spatiu, incepand de la primul nod din * lista. */ void dll_print_string_list(doubly_linked_list_t* list) { if (list == NULL) return; dll_node_t *pos = list->head; unsigned int tmp = list->size; while (tmp > 0) { printf("%s ", (char *)pos->data); pos = pos->next; tmp--; } printf("\n"); } /* * Atentie! Aceasta functie poate fi apelata doar pe liste ale caror noduri STIM * ca stocheaza int-uri. Functia afiseaza o singura data toate valorile int * stocate in nodurile din lista, separate printr-un spatiu, incepand de la * nodul dat ca parametru si continuand la stanga in lista dublu inlantuita * circulara, pana cand sunt afisate valorile tuturor nodurilor. */ void dll_print_ints_left_circular(dll_node_t* start) { dll_node_t *pointer = start->prev; printf("%d ", *((int *)start->data)); while (pointer != start) { printf("%d ", *((int *)pointer->data)); pointer = pointer->prev; } printf("\n"); } /* * Atentie! Aceasta functie poate fi apelata doar pe liste ale caror noduri STIM * ca stocheaza int-uri. Functia afiseaza o singura data toate valorile int * stocate in nodurile din lista, separate printr-un spatiu, incepand de la * nodul dat ca parametru si continuand la dreapta in lista dublu inlantuita * circulara, pana cand sunt afisate valorile tuturor nodurilor. */ void dll_print_ints_right_circular(dll_node_t* start) { dll_node_t *pointer = start->prev; printf("%s ", (char *)start->data); while (pointer != start) { printf("%s ", (char *)start->data); pointer = pointer->next; } printf("\n"); }