list.h
Código
#ifndef LIST_H_INCLUDED #define LIST_H_INCLUDED /** \autor Ortega Avila Miguel Angel (BlackZeroX). * * \website http://infrnagelux.sytes.net/ * \copileft El presente código se da de manera gratuita sin ningún derecho a venta. * \note muchas de las funciones aqui presentadas "inútiles" como: * list_before() * list_after() * list_getlist() * Note que esta ultima solo esta activa mientras este declarada la macro. * * http://foro.elhacker.net/programacion_cc/srcc99_para_que_dejen_de_preguntar_por_las_listas-t380839.0.html * */ #include <stdbool.h> #include <stdlib.h> #include <stddef.h> #include <stdint.h> #ifndef LIST_INTEGRAL_RELATIONSHIP /** \brief Al declarar LIST_INTEGRAL_RELATIONSHIP se reduce considerablemente la velocidad * en el proceso list_sort() debido a que se actualizan TODOS los miembros list de la estructura * struct list_item de cada elemento; De igual manera aumenta la seguridad de no eliminar o hacer * operaciones indebidas entre elementos. * */ ///#define LIST_INTEGRAL_RELATIONSHIP /**< Comentar/descomentar */ #endif #define LIST_SIZE_ITEM sizeof(struct list_item) struct list; typedef void* list_value_t; ///typedef uintptr_t list_value_t; typedef struct list* list_t; /** \brief Definición callback que se encarga de crear un duplicado de un elemento de lista. * \param item: Valor a duplicar. * * \return Retorna el elemento list_value_t duplicado del parámetro value. * */ typedef list_value_t (*list_callback_clone_item) (const list_value_t value); /** \brief Definición de callback que se encarga de destruir la memoria asignada al list_value_t. * * \param item: Puntero a la estructura que se le pretende liberar su valor asignado debe liberarse solo el miembro value. * */ typedef void(*list_callback_release_item) (const list_value_t value); /** \brief Definición de callback que se encarga comparar dos list_value_t. * * \param value1: list_value_t que se comparara con value2. * \param value2: list_value_t que se comparara con value1. * \return Retorna el resultado de la comparación. * LIST_CMP_LESS_THAT: Si value1 < value2. * LIST_CMP_EQUAL: Si value1 == value2. * LIST_CMP_GREATER_THAT: Si value1 > value2. * */ typedef enum list_cmp(*list_callback_compare_item) (const list_value_t value1, const list_value_t value2); enum list_cmp { LIST_CMP_EQUAL = 1, /**< */ LIST_CMP_LESS_THAT = 2, /**< */ LIST_CMP_GREATER_THAT = 4 /**< */ }; enum list_sort { LIST_SORT_ASC, /**< */ LIST_SORT_DESC /**< */ }; struct list_item { list_value_t value; /**< Valor del item actual. */ struct list_item *prev; /**< Apuntador al item derecho. */ struct list_item *next; /**< Apuntador al item izquierdo. */ #ifdef LIST_INTEGRAL_RELATIONSHIP list_t list; /**< Apuntador a los datos generales de la lista. */ #endif }; struct list { /**< Estructura que guarda la información generalizada de una lista de datos */ struct list_item *first; /**< Primer elemento agregado a la lista */ struct list_item *last; /**< Ultimo elemento agregado a la lista */ #ifdef LIST_INTEGRAL_RELATIONSHIP size_t size; /**< Cantidad de elementos */ #endif list_callback_clone_item clone_item; /**< Puntero a la función callback que realiza las acciones CLONE, RELEASE y COMPARE */ list_callback_release_item release_item; /**< Puntero a la función callback que realiza las acciones CLONE, RELEASE y COMPARE */ list_callback_compare_item compare_item; /**< Puntero a la función callback que realiza las acciones CLONE, RELEASE y COMPARE */ }; /** \brief Obtiene el item siguiente al inicado. * * \param item: Item pivote en la lista. * \return Retorna el struct list_item * siguiente al indicado; NULL si no hay ningun item. * */ struct list_item* list_after(struct list_item *item); /** \brief Crea una nueva lista de elementos list_value_t. * * \param clone_item: Apuntador a la función callback que retornara la copia del valor a asignar. * \param release_item: Apuntador a la función callback que liberara la copia del valor duplicado en el list_callback_clone_item. * \param clone_item: Apuntador a un proceso callback que se encarga de comparar los struct list_item *. * \return Retorna la nueva cola de datos queue_t que deberá ser destruida con list_release(). * */ list_t list_allocator(list_callback_clone_item clone_item, list_callback_release_item release_item, list_callback_compare_item compare_item); /** \brief Agrega n cantidad de elementos repetidos (value) a la lista, reemplazando los existentes. * * \param list: Lista en la que se agregara value n veces. * \param n: Cantidad de valores a agregar a la lista. * \param value: Valor a agregar n veces a la lista. * \return Retorna el primer elemento agregado; NULL si no se a agregado ningun elemento. * */ struct list_item* list_assign(list_t list, size_t n, list_value_t value); /** \brief Obtiene el ultimo elemento de una lista. * * \param list: Lista de la cual se obtendrá el ultimo elemento struct list_item *. * \return Devuelve el ultimo struct list_item * de la lista. * */ struct list_item* list_back(list_t list); /** \brief Obtiene el item anterior al inicado. * * \param item: Item pivote en la lista. * \return Retorna el struct list_item * anterior al indicado; NULL si no hay ningun item. * */ struct list_item* list_before(struct list_item *item); /** \brief Obtiene el primer elemento de una lista. * * \param list: Lista de la cual se obtendrá su primer elemento struct list_item *. * \return Devuelve el primer struct list_item * de la lista. * */ struct list_item* list_begin(list_t list); /** \brief Remueve/Libera TODOS los elementos de la lista. * * \param list: Puntero a la struct list que se limpiara. * \return Retorna la cantidad de elementos removidos de la lista. * */ size_t list_clear(list_t list); /** \brief Función que clona por completo una lista. * * \param list: Lista que será clonada. * \return Retorna una nueva lista que deberá ser liberada con list_release(). * */ list_t list_clone(list_t list); /** \brief Copia los elementos de una lista a otra. * * \param list: Lista a la que pertenece el item pasado por el parámetro dst. * \param dst: Elemento pivote en donde se se ubicaran los elementos a copiar desde src. * \param src: Elemento pivote de una lista que se le clonaran sus elementos para agregarlos en la lista destino dst. * \param n: Cantidad máxima de elementos que copiaran. * \return Retorna la cantidad de elementos agregados en la lista dst. * */ size_t list_copy(list_t list, struct list_item *dst, struct list_item *src, size_t n); /** \brief Verifica si una lista esta vacia. * * \param list: Lista que se verificara. * \return Retorna: * true: si la lista esta vacia. * false: Si contiene por lo menos un elemento. * */ bool list_empty(list_t list); /** \brief Elimina un struct list_item * de su lista. * * \param list: Lista a la que pertenece el item. * \param item: Elemento que se eliminara/liberara de su lista. * */ void list_erase(list_t list, struct list_item *item); /** \brief Libera la memoria un struct list_item * NO RELACIONADA con una lista (miembro list debe ser igual a NULL). * * \param item: Elemento que se eliminara/liberara de su lista. * \param callback_release_value: Callback a la función que esta encargada de liberar la memoria del miembro value. * */ void list_release_item(struct list_item *item, list_callback_release_item callback_release_value); /** \brief Remueve la relación que tiene el elemento con su lista madre (Usar con cuidado). * * \param list: Lista a la que se le extraerá el elemento. * \param item: Elemento que se extraerá de su lista. * \return Retorno el valor pasado en el parámetro item si se extrajo correctamente, de lo contrario retorna NULL. * * * \code * void * list_release_item(struct list_item *item, * list_callback_release_item callback_release_value) { * if (!item) * return; * * if (callback_release_value) * callback_release_value(item->value); * #ifdef LIST_INTEGRAL_RELATIONSHIP * free(list_extract(NULL, item)); * #else * free(list_extract(NULL, item)); * #endif * } * \endcode * */ struct list_item* list_extract(list_t list, struct list_item *item); /** \brief Busca un valor a partir de un pivote indicado dentro de una lista. * * \param list: Lista a la que pertenecen los elementos (incluye parámetro item). * \param item: Elemento pivote desde el cual se empezara a buscar el valor indicado en value. * si es NULL iniciara desde el inicio de la lista. * \param value: Valor a buscar en la lista a partir de el pivote indicado. * \return Retorna NULL si no se a encontrado dentro de la lista en caso * contrario retorna el elemento . * */ struct list_item* list_findnext(list_t list, struct list_item *item, list_value_t value); /** \brief Busca un valor a partir de un pivote indicado dentro de una lista. * * \param list: Lista a la que pertenecen los elementos. * \param item: Elemento pivote desde el cual se empezara a buscar el valor indicado en value, * si es NULL iniciara a buscar desde el final de la lista. * \param value: Valor a buscar en la lista antes de el pivote indicado. * \return Retorna NULL si no se a encontrado dentro de la lista en caso * contrario retorna el puntero al item. */ struct list_item* list_findprev(list_t list, struct list_item *item, list_value_t value); #ifdef LIST_INTEGRAL_RELATIONSHIP /** \brief Obtiene la lista a la cual pertenece un item. * * \param item: elemento a consultar. * \return Devuelve la lista a la cual pertenece dicho item; NULL si no pertenece a ninguna lista. * */ list_t list_getlist(struct list_item *item); #endif /** \brief Mezcla dos listas generando una nueva lista que deberá ser liberada con list_release(). * * \param list1: Los elementos de esta lista se agregaran al inicio. * \param list2: Los elementos de esta lista se agregaran al seguidos de los de list1. * \return Retorna una nueva lista que contendrán las copias de las dos listas espesificadas. * */ list_t list_join(list_t list1, list_t list2); /** \brief Agrega un valor al final de la lista. * * \param list: lista a la cual se le agregara un elemento nuevo. * \param value: Valor a agregar a la lista. * \return Retorna el puntero al item en la lista, NULL si fallo. * */ struct list_item* list_pushback(list_t list, list_value_t value); /** \brief Agrega un elemento struct list_item al final de la lista (No crea un duplicado del elemento). * * \param list: lista a la cual se le agregara un elemento nuevo. * \param item: Puntero al elemento struct list_item a relacionar con la lista. * \return Retorna el puntero al item en la lista (el retorno es igual a el parámetro item), NULL si fallo. * */ struct list_item* list_pushback_item (list_t list, struct list_item *item); /** \brief Agrega un valor al inicio de la lista. * * \param list: Lista a la cual se le agregara un elemento nuevo. * \param value: Valor a agregar a la lista. * \return Retorna el puntero al item en la lista. * */ struct list_item* list_pushfront(list_t list, list_value_t value); /** \brief Agrega un elemento struct list_item al inicio de la lista (No crea un duplicado del elemento). * * \param list: lista a la cual se le agregara un elemento nuevo. * \param item: Puntero al elemento struct list_item a relacionar con la lista. * \return Retorna el puntero al item en la lista (el retorno es igual a el parámetro item), NULL si fallo. * */ struct list_item* list_pushfront_item (list_t list, struct list_item *item); /** \brief Agrega un valor en la lista después de un elemento indicado como pivote. * * \param list: lista en la que se agregara. * \param pivot: Elemento pivote que esta dentro de una lista, si el valor es NULL value se agregara al final de la lista. * \param value: Valor a agregar a la lista después del pivote. * \return Retorna el puntero al item en la lista, NULL si fallo. * */ struct list_item* list_pushnext(list_t list, struct list_item *pivot, list_value_t value); /** \brief Agrega un elemento struct list_item después de un elemento indicado como pivote (No crea un duplicado del elemento). * * \param list: lista en la que se agregara. * \param pivot: Elemento pivote que esta dentro de una lista, si el valor es NULL itemnew se agregara al final de la lista. * \param itemnew: Puntero al elemento struct list_item a relacionar con la lista. * \return Retorna el puntero al item en la lista (el retorno es igual a el parámetro itemnew), NULL si fallo. * */ struct list_item* list_pushnext_item(list_t list, struct list_item *pivot, struct list_item *itemnew); /** \brief Agrega un elemento en la lista antes de un elemento indicado. * * \param list: lista en la que se agregara. * \param pivot: Elemento pivote que esta dentro de una lista, si el valor es NULL value se agregara al final de la lista. * \param value: Valor a agregar a la lista antes del pivote. * \return Retorna el puntero al item en la lista, NULL si fallo. * */ struct list_item* list_pushprev(list_t list, struct list_item *pivot, list_value_t value); /** \brief Agrega un elemento struct list_item antes de un elemento indicado como pivote (No crea un duplicado del elemento). * * \param list: lista en la que se agregara. * \param pivot: Elemento pivote que esta dentro de una lista, si el valor es NULL itemnew se agregara al final de la lista. * \param itemnew: Puntero al elemento struct list_item a relacionar con la lista. * \return Retorna el puntero al item en la lista (el retorno es igual a el parámetro itemnew), NULL si fallo. * */ struct list_item* list_pushprev_item(list_t list, struct list_item *pivot, struct list_item *itemnew); /** \brief Destruye una lista, los elementos también son liberados. * * \param list: Puntero a la struct list a destruir. */ void list_release(list_t list); /** \brief Obtiene la cantidad de elementos en la lista. * * \param list: Lista de la cual se retornaran la cantidad de elementos almacenados en ella. * \return Retorna la cantidad de elementos en la lista. * */ size_t list_size(list_t list); /** \brief Intercambia los elementos de cada lista. * * \param list1: Lista involucrada que se cambiaran los elementos con list2. * \param list2: Lista involucrada que se cambiaran los elementos con list1. * \return Retorna TRUE si no hubo errores y FALSE si no se puedo intercambiar los elementos. * */ void list_swap(list_t list1, list_t list2); #endif // LIST_H_INCLUDED
list.c
Código
#include "include/List.h" /** \brief callback predeterminado que se encarga de crear un duplicado del queue_value_t para el stack_item_t. * * \param value: queue_value_t que se asignara. * \return Debe retornarse el queue_value_t a asignar al stack_item_t que se esta creando. * */ list_value_t list_callback_clone_item_default(const list_value_t value) { return value; } /** \brief callback predeterminado que se encarga de destruir la memoria asignada al stack_item_t. * * \param value: queue_value_t que se liberara. * */ void list_callback_release_item_default(const list_value_t value) { /// none code } /** \brief callback predeterminado que se encarga comparar dos list_value_t. * * \param value1: se comparara con value2. * \param value2: se comparara con value1. * \return Retorna el resultado de la comparación. * LIST_CMP_LESS_THAT: Si value1 < value2. * LIST_CMP_EQUAL: Si value1 == value2. * LIST_CMP_GREATER_THAT: Si value1 > value2. * */ enum list_cmp list_callback_compare_item_default(const list_value_t value1, const list_value_t value2) { if (value1 > value2) { return LIST_CMP_GREATER_THAT; } else if (value1 < value2) { return LIST_CMP_LESS_THAT; } return LIST_CMP_EQUAL; } struct list_item* list_after(struct list_item *item) { return item ? item->next : NULL; } list_t list_allocator(list_callback_clone_item clone_item, list_callback_release_item release_item, list_callback_compare_item compare_item) { list->first = list->last = NULL; #ifdef LIST_INTEGRAL_RELATIONSHIP list->size = 0; #endif //LIST_INTEGRAL_RELATIONSHIP list->clone_item = clone_item ? clone_item : list_callback_clone_item_default; list->release_item = release_item ? release_item : list_callback_release_item_default; list->compare_item = compare_item ? compare_item : list_callback_compare_item_default; return list; } void list_allocator_array(list_t *array, size_t n, list_callback_clone_item clone_item, list_callback_release_item release_item, list_callback_compare_item compare_item) { for (register size_t i = 0; i < n; ++i) array[i] = list_allocator(clone_item, release_item, compare_item); } struct list_item* list_assign(list_t list, size_t n, list_value_t value) { struct list_item *ret = NULL; if (!list) return NULL; list_clear(list); ret = (n > 0) ? list_pushback(list, value) : NULL; for (register size_t i = 1; i < n; i++) list_pushback(list, value); return ret; } struct list_item* list_back(list_t list) { return list ? list->last : NULL; } struct list_item* list_before(struct list_item *item) { return item ? item->prev : NULL; } struct list_item* list_begin(list_t list) { return list ? list->first : NULL; } size_t list_clear(list_t list) { struct list_item *item = NULL; size_t ret = 0; while((item = list->first) != NULL) { list_erase(list, item); ++ret; } return ret; } list_t list_clone(list_t list) { list_t ret = NULL; struct list_item *item = NULL; if (!list) return NULL; ret = list_allocator(list->clone_item, list->release_item, list->compare_item); for (item = list_begin(list); item != NULL; item = list_after(item)) list_pushback(ret, item->value); return ret; } size_t list_copy(list_t list, struct list_item *dst, struct list_item *src, size_t n) { size_t ret = 0; if (!(dst && src)) return 0; #ifdef LIST_INTEGRAL_RELATIONSHIP if (!(dst->list && dst->list == list)) return 0; #endif //LIST_INTEGRAL_RELATIONSHIP while (n > 0 && src != NULL) { list_pushback(list, src->value); src = src->next; --n; ++ret; } return ret; } bool list_empty(list_t list) { return list && list->first && list->last ? true : false; } void list_erase(list_t list, struct list_item *item) { if (!(item && list)) return; #ifdef LIST_INTEGRAL_RELATIONSHIP else if (item->list != list) return; #endif //LIST_INTEGRAL_RELATIONSHIP if (list && list->release_item) list->release_item(item->value); } void list_release_item(struct list_item *item, list_callback_release_item callback_release_value) { if (!item) return; if (callback_release_value) callback_release_value(item->value); #ifdef LIST_INTEGRAL_RELATIONSHIP #else #endif // LIST_INTEGRAL_RELATIONSHIP } struct list_item* list_extract(list_t list, struct list_item *item) { if (!item) return NULL; #ifdef LIST_INTEGRAL_RELATIONSHIP else if (item->list != list) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP if (list) { if (list->first == item) list->first = item->next; if (list->last == item) list->last = item->prev; } else if (item->prev || item->next) { return NULL; } if (item->prev) item->prev->next = item->next; if (item->next) item->next->prev = item->prev; item->prev = NULL; item->next = NULL; #ifdef LIST_INTEGRAL_RELATIONSHIP --(list->size); item->list = NULL; #endif // LIST_INTEGRAL_RELATIONSHIP return item; } struct list_item* list_findnext(list_t list, struct list_item *item, list_value_t value) { if (!list) return NULL; else if (!list->compare_item) return NULL; if (!item) item = list->first; #ifdef LIST_INTEGRAL_RELATIONSHIP else if (item->list != list) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP struct list_item *now = item; do { if ((list->compare_item)(now->value, value) & LIST_CMP_EQUAL) return now; now = now->next; } while (now); return NULL; } struct list_item* list_findprev(list_t list, struct list_item *item, list_value_t value) { if (!list) return NULL; else if (!list->compare_item) return NULL; if (!item) item = list->last; #ifdef LIST_INTEGRAL_RELATIONSHIP else if (item->list != list) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP struct list_item *now = item; do { if ((list->compare_item)(now->value, value) & LIST_CMP_EQUAL) return now; now = now->prev; } while (now); return NULL; } #ifdef LIST_INTEGRAL_RELATIONSHIP list_t list_getlist(struct list_item *item) { if (!item) return NULL; return item->list; } #endif // LIST_INTEGRAL_RELATIONSHIP list_t list_join(list_t list1, list_t list2) { list_t list = list_clone(list1); struct list_item *item = NULL; for (item = list_begin(list2); item != NULL; item = list_after(item)) list_pushback(list, item->value); return list; } struct list_item* list_pushback(list_t list, list_value_t value) { struct list_item *itemnew = NULL; if (list && !list->clone_item) return NULL; #ifdef LIST_INTEGRAL_RELATIONSHIP itemnew->list = NULL; #endif if (list_pushback_item(list, itemnew) != itemnew) { return NULL; } itemnew->value = (list->clone_item)(value); return list->last; } struct list_item* list_pushback_item (list_t list, struct list_item *item) { #ifdef LIST_INTEGRAL_RELATIONSHIP if (!(list && item && !item->list)) return NULL; #else if (!(list && item)) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP if (!(list->first && list->last)) { list->first = item; item->prev = NULL; } else { list->last->next = item; item->prev = list->last; } item->next = NULL; #ifdef LIST_INTEGRAL_RELATIONSHIP ++(list->size); item->list = list; #endif // LIST_INTEGRAL_RELATIONSHIP list->last = item; return item; } struct list_item* list_pushfront(list_t list, list_value_t value) { struct list_item *itemnew = NULL; if (list || !list->clone_item) return NULL; #ifdef LIST_INTEGRAL_RELATIONSHIP itemnew->list = NULL; #endif // LIST_INTEGRAL_RELATIONSHIP if (list_pushfront_item(list, itemnew) != itemnew) { return NULL; } itemnew->value = (list->clone_item)(value); return list->first; } struct list_item* list_pushfront_item(list_t list, struct list_item *item) { #ifdef LIST_INTEGRAL_RELATIONSHIP if (!(list && item && !item->list)) return NULL; #else if (!(list && item)) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP if (!(list->first && list->last)) { list->last = item; item->next = NULL; } else { list->first->prev = item; item->next = list->first; } item->prev = NULL; #ifdef LIST_INTEGRAL_RELATIONSHIP ++(list->size); item->list = list; #endif // LIST_INTEGRAL_RELATIONSHIP list->first = item; return item; } struct list_item* list_pushnext(list_t list, struct list_item *pivot, list_value_t value) { if (!list) return NULL; if (!pivot) pivot = list->last; #ifdef LIST_INTEGRAL_RELATIONSHIP else if (pivot->list != list) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP if (list_pushnext_item(list, pivot, itemnew) != itemnew) { return NULL; } itemnew->value = (list->clone_item)(value); return itemnew; } struct list_item* list_pushnext_item(list_t list, struct list_item *pivot, struct list_item *itemnew) { if (!(list && itemnew)) return NULL; if (!pivot) pivot = list->last; #ifdef LIST_INTEGRAL_RELATIONSHIP else if (pivot->list != list) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP if (pivot) { if (!pivot->next) return list_pushback_item(list, itemnew); pivot->next->prev = itemnew; itemnew->next = pivot->next; pivot->next = itemnew; itemnew->prev = pivot; #ifdef LIST_INTEGRAL_RELATIONSHIP ++(itemnew->list->size); itemnew->list = pivot->list; #endif // LIST_INTEGRAL_RELATIONSHIP return itemnew; } else { return list_pushback_item(list, itemnew); } return NULL; } struct list_item* list_pushprev(list_t list, struct list_item *pivot, list_value_t value) { if (!list) return NULL; if (!pivot) pivot = list->first; #ifdef LIST_INTEGRAL_RELATIONSHIP else if (pivot->list != list) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP if (list_pushprev_item(list, pivot, itemnew) != itemnew) { return NULL; } itemnew->value = (list->clone_item)(value); return itemnew; } struct list_item* list_pushprev_item(list_t list, struct list_item *pivot, struct list_item *itemnew) { if (!(list && itemnew)) return NULL; if (!pivot) pivot = list->first; #ifdef LIST_INTEGRAL_RELATIONSHIP else if (pivot->list != list) return NULL; #endif // LIST_INTEGRAL_RELATIONSHIP if (pivot) { if (!pivot->prev) return list_pushfront_item(list,itemnew); pivot->prev->next = itemnew; itemnew->prev = pivot->prev; pivot->prev = itemnew; itemnew->next = pivot; #ifdef LIST_INTEGRAL_RELATIONSHIP itemnew->list = pivot->list; ++(itemnew->list->size); #endif // LIST_INTEGRAL_RELATIONSHIP return itemnew; } else { return list_pushfront_item(list,itemnew); } return NULL; } void list_release(list_t list) { list_clear(list); } void list_release_array(list_t *array, size_t n) { for (register size_t i = 0; i < n; ++i) list_release(array[i]); } size_t list_size(list_t list) { #ifdef LIST_INTEGRAL_RELATIONSHIP return list ? list->size : 0; #else size_t ret = 0; struct list_item *item = list ? list->first : NULL; while (item) { ++ret; item = item->next; } return ret; #endif // LIST_INTEGRAL_RELATIONSHIP } void list_swap(list_t list1, list_t list2) { if (!(list1 && list2)) return; struct list tmp = *list2; *list2 = *list1; *list1 = tmp; #ifdef LIST_INTEGRAL_RELATIONSHIP for (struct list_item *item = list_begin(list1); item != NULL; item = list_after(item)) item->list = list1; for (struct list_item *item = list_begin(list2); item != NULL; item = list_after(item)) item->list = list2; #endif // LIST_INTEGRAL_RELATIONSHIP }
Dulces Lunas!¡.