Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _POSIX_C_SOURCE 200809L
- #include "abb.h"
- #include "pila.h"
- #include <stdbool.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- typedef struct nodo{
- struct nodo* izq;
- struct nodo* der;
- void* dato;
- char* clave;
- }nodo_t;
- struct abb{
- struct nodo* raiz;
- abb_destruir_dato_t destruir_dato;
- abb_comparar_clave_t cmp;
- size_t cantidad;
- };
- void destruir(abb_t* arbol, nodo_t* nodo);
- void borrar_nodo(nodo_t* nodo);
- void* averiguar_caso(abb_t* arbol, nodo_t* padre, nodo_t* hijo);
- void* ver_caso_3(abb_t* arbol, nodo_t* padre, nodo_t* hijo, nodo_t* reemplazante);
- void* ver_caso_2(abb_t* arbol, nodo_t* padre, nodo_t* hijo);
- void* ver_caso_1(abb_t* arbol, nodo_t* padre, nodo_t* hijo);
- void* borrar(abb_t* arbol, nodo_t* nodo, const char* clave);
- void* buscar(const abb_t* arbol, nodo_t* nodo, const char* clave);
- bool guardar(abb_t* arbol, nodo_t* raiz, nodo_t* nodo, bool es_guardar);
- nodo_t* crear_nodo(const char* clave, void* dato){
- nodo_t* nodo = malloc(sizeof(nodo_t));
- nodo->izq = NULL;
- nodo->der = NULL;
- nodo->dato = dato;
- nodo->clave = strdup(clave);
- return nodo;
- }
- abb_t* abb_crear(abb_comparar_clave_t cmp, abb_destruir_dato_t destruir_dato){
- abb_t* arbol = malloc(sizeof(abb_t));
- if (destruir_dato) arbol->destruir_dato = destruir_dato;
- else arbol->destruir_dato = NULL;
- if (cmp) arbol->cmp = cmp;
- else return false;
- arbol->cantidad = 0;
- arbol->raiz = NULL;
- return arbol;
- }
- size_t abb_cantidad(abb_t *arbol){
- return arbol->cantidad;
- }
- bool abb_pertenece(const abb_t *arbol, const char *clave){
- nodo_t* aux = buscar(arbol, arbol->raiz, clave);
- if ((aux) && arbol->cmp(aux->clave, clave) == 0){
- return true;
- }
- return false;
- }
- void* buscar(const abb_t* arbol, nodo_t* nodo, const char* clave){
- if (!nodo) return NULL;
- if (arbol->cmp(nodo->clave, clave) > 0) return buscar(arbol, nodo->izq, clave);
- else if (arbol->cmp(nodo->clave, clave) < 0) return buscar(arbol, nodo->der, clave);
- return nodo;
- }
- void* abb_obtener(const abb_t *arbol, const char *clave){
- if (!abb_pertenece(arbol, clave)) return NULL;
- nodo_t* aux = buscar(arbol, arbol->raiz, clave);
- if (!aux) return NULL;
- return aux->dato;
- }
- bool abb_guardar(abb_t *arbol, const char *clave, void *dato){
- nodo_t* nodo = crear_nodo(clave, dato);
- if (!nodo) return false;
- bool pertenece = abb_pertenece(arbol, nodo->clave);
- if(!pertenece) arbol->cantidad++;
- return guardar(arbol, arbol->raiz, nodo, pertenece);
- }
- bool guardar(abb_t* arbol, nodo_t* raiz, nodo_t* nodo, bool es_guardar){
- if (!arbol->raiz){
- arbol->raiz = nodo;
- return true;
- }
- if (arbol->cmp(raiz->clave, nodo->clave) > 0){
- if (raiz->izq == NULL){
- raiz->izq = nodo;
- return true;
- }
- return guardar(arbol, raiz->izq, nodo, es_guardar);
- }
- else if (arbol->cmp(raiz->clave, nodo->clave) < 0){
- if (raiz->der == NULL){
- raiz->der = nodo;
- return true;
- }
- return guardar(arbol, raiz->der, nodo, es_guardar);
- }
- else if (es_guardar){
- if(arbol->destruir_dato) arbol->destruir_dato(raiz->dato);
- raiz->dato = nodo->dato;
- borrar_nodo(nodo);
- return true;
- }
- return true;
- }
- void *abb_borrar(abb_t *arbol, const char *clave){
- if (!abb_pertenece(arbol, clave)) return NULL;
- void* aux = borrar(arbol, arbol->raiz, clave);
- arbol->cantidad--;
- return aux;
- }
- void* borrar(abb_t* arbol, nodo_t* nodo, const char* clave){
- void* aux = NULL;
- if (arbol->cmp(arbol->raiz->clave, clave) == 0){
- aux = averiguar_caso(arbol, NULL, nodo);
- return aux;
- }
- if (arbol->cmp(nodo->clave, clave) > 0){
- if (arbol->cmp(nodo->izq->clave, clave) == 0){
- aux = averiguar_caso(arbol, nodo, nodo->izq);
- return aux;
- }
- return borrar(arbol, nodo->izq, clave);
- }
- else if (arbol->cmp(nodo->clave, clave) < 0){
- if (arbol->cmp(nodo->der->clave, clave) == 0){
- aux = averiguar_caso(arbol, nodo, nodo->der);
- return aux;
- }
- return borrar(arbol, nodo->der, clave);
- }
- return aux;
- }
- void* averiguar_caso(abb_t* arbol, nodo_t* padre, nodo_t* hijo){
- void* aux;
- if (hijo->izq == NULL && hijo->der == NULL){
- if (padre == NULL){
- aux = ver_caso_1(arbol, NULL, hijo);
- return aux;
- }
- aux = ver_caso_1(arbol, padre, hijo);
- return aux;
- }
- else if (hijo->izq == NULL || hijo->der == NULL){
- aux = ver_caso_2(arbol, padre, hijo);
- return aux;
- }
- else {
- nodo_t* reemplazante = hijo->der;
- aux = ver_caso_3(arbol, padre, hijo, reemplazante);
- }
- return aux;
- }
- void* ver_caso_3(abb_t* arbol, nodo_t* padre, nodo_t* hijo, nodo_t* reemplazante){
- if (reemplazante->izq == NULL){
- char* clave_aux = reemplazante->clave;
- void* dato_aux = reemplazante->dato;
- if (reemplazante->der){
- if (arbol->cmp(hijo->der->clave, reemplazante->clave) == 0) hijo->der = reemplazante->der;
- else padre->izq = reemplazante->der;
- }
- else if (arbol->cmp(hijo->der->clave, reemplazante->clave) == 0) hijo->der = NULL;
- else padre->izq = NULL;
- free(hijo->clave);
- hijo->clave = strdup(clave_aux);
- borrar_nodo(reemplazante);
- void* aux = hijo->dato;
- hijo->dato = dato_aux;
- return aux; //Tener en cuenta si hace falta usar Free en clave aux
- }
- return ver_caso_3(arbol, reemplazante, hijo, reemplazante->izq);
- }
- void* ver_caso_2(abb_t* arbol, nodo_t* padre, nodo_t* hijo){
- if (hijo->izq == NULL){
- if (padre == NULL){
- arbol->raiz = hijo->der;
- }else{
- if (arbol->cmp(padre->clave,hijo->clave) > 0) padre->izq = hijo->der;
- else padre->der = hijo->der;
- }
- }
- if (hijo->der == NULL){
- if (padre == NULL){
- arbol->raiz = hijo->izq;
- }else{
- if (arbol->cmp(padre->clave,hijo->clave) > 0) padre->izq = hijo->izq;
- else padre->der = hijo->izq;
- }
- }
- void* aux = hijo->dato;
- borrar_nodo(hijo);
- return aux;
- }
- void* ver_caso_1(abb_t* arbol,nodo_t* padre, nodo_t* hijo){
- void* aux = hijo->dato;
- if (padre == NULL) arbol->raiz = NULL;
- else if (arbol->cmp(padre->clave,hijo->clave) > 0) padre->izq = NULL;
- else padre->der = NULL;
- borrar_nodo(hijo);
- return aux;
- }
- void borrar_nodo(nodo_t* nodo){
- free(nodo->clave);
- free(nodo);
- }
- void abb_destruir(abb_t *arbol){
- destruir(arbol, arbol->raiz);
- free(arbol);
- }
- void destruir(abb_t* arbol, nodo_t* nodo){
- if (nodo){
- destruir(arbol, nodo->izq);
- if (arbol->destruir_dato) arbol->destruir_dato(nodo->dato);
- destruir(arbol, nodo->der);
- borrar_nodo(nodo);
- }
- }
- /////////////////////// Iterador Interno //////////////////////////
- bool in_order(bool aux, nodo_t* nodo, bool visitar(const char*, void*, void*), void* extra){
- if (!nodo) return aux;
- if (!in_order(aux, nodo->izq, visitar, extra)){
- aux = false;
- return aux;
- }
- if (!visitar(nodo->clave, nodo->dato, extra)){
- aux = false;
- return aux;
- }
- return in_order(aux, nodo->der, visitar, extra);
- }
- void abb_in_order(abb_t *arbol, bool visitar(const char *, void *, void *), void *extra){
- bool aux = true;
- in_order(aux, arbol->raiz, visitar, extra);
- }
- //////////////////////////////////////////////////////////////////
- ////////////////////// Iterador Externo /////////////////////////
- ////////////////////////////////////////////////////////////////
- struct abb_iter{
- abb_t* arbol;
- nodo_t* nodo;
- pila_t* pila;
- };
- void inicializar0avanzar_iter_abb(nodo_t* nodo, abb_iter_t* iter){
- if (!nodo) return;
- pila_apilar(iter->pila, nodo->clave);
- inicializar0avanzar_iter_abb(nodo->izq, iter);
- }
- abb_iter_t* abb_iter_in_crear(const abb_t *arbol){
- abb_iter_t* iter = malloc(sizeof(abb_iter_t));
- if (!iter) return NULL;
- iter->pila = pila_crear();
- if (!iter->pila) return NULL;
- iter->arbol =(abb_t*)arbol;
- iter->nodo = arbol->raiz;
- inicializar0avanzar_iter_abb(iter->nodo, iter);
- return iter;
- }
- void* buscar_iter(nodo_t* nodo, abb_iter_t* iter, char* clave){
- if (!nodo) return NULL;
- if (iter->arbol->cmp(nodo->clave, clave) > 0) return buscar_iter(nodo->izq, iter, clave);
- else if (iter->arbol->cmp(nodo->clave, clave) < 0) return buscar_iter(nodo->der, iter, clave);
- else return nodo;
- }
- bool abb_iter_in_avanzar(abb_iter_t *iter){
- if (abb_iter_in_al_final(iter)) return false;
- char* clave = (char*)pila_desapilar(iter->pila);
- iter->nodo = buscar_iter(iter->arbol->raiz, iter, clave);
- if (iter->nodo->der) inicializar0avanzar_iter_abb(iter->nodo->der, iter);
- return true;
- }
- const char *abb_iter_in_ver_actual(const abb_iter_t *iter){
- return (const char*)pila_ver_tope(iter->pila);
- }
- bool abb_iter_in_al_final(const abb_iter_t *iter){
- return pila_esta_vacia(iter->pila);
- }
- void abb_iter_in_destruir(abb_iter_t* iter){
- pila_destruir(iter->pila);
- free(iter);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement