- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #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");
- }