/*********** DOCTORIAL DE LA LLISTA GENERICA KKEP *****************/ /********************************************************************\ * Aqui teniu el doctorial de la llista generica total!!! * * * * NOTA: En contra del que sovint he insinuat que faria, no l'he * * copiada de cap vostra. Es bastant diferent, crec. Conte totes * * les barbaritats que us demanavem i algunes floritures mes. A * * mes a mes, he afegit d'ultima hora algunes cosetes boniques * * que he vist en les vostres practiques. Com totes les llibreries * * del Share, aquesta tambe es de domini public pero aneu amb cura * * si les feu servir per practiques. * * * * Millores implementades: * * - Totes les funcions del node llista es fan servir com si * * fossin les funcions de la llibreria standard, stdlib: * * * strcmp, strcpy, malloc, free i strcat. * * - Permet diversos tipus d'insercions, segons el que passa * * quan colisionin dos claus iguals: * * * La nova es postposa a la vella * * * La nova s'anteposa a la vella * * * La nova no s'insereixi * * * La nova sustituexi la vella * * * La nova modifiqui la vella * * - Permet operacio simultanea amb finestra i per valor a * * la mateixa llista sense que un destorbi a l'altre. * * - Permet dos tipus de consultes, segons es retorni * * * Una copia de l'element a una altre zona de memoria * * * Un punter al mateix element de la llista * * - Permet definir a la vegada: * * * Mes d'una llista * * * de les diferents classes a dalt mencionades * * * i contenint diferents tipus d'elements * * - Funcio aplica: Resol la majoria de les vostres floritures. * * - Funcio acomula: Permet obtindre un resultat de tipus * * generic calculat a partir de tots els elements de la * * llista. * * * * Limitacions: * * - Per mantenir la consistencia de l'ordenacio, no es aconse. * * llable inserir per finestra indiscriminadament si fem * * quelcom per valor o un llista_posiciona_finestra. * * - Per evitar core dumped's, s'aconsella initcialitzar la * * finestra sempre que s'esborri per valor. * * * * Be, i ara... qui s'atreveix a: * * - Fer-la doblement encadenada. * * - Fer-la circular. * * - Fer-la multi-finestra. * * * \********************************************************************/ COM ES DEFINEIXEN LES FUNCIONS QUE ES FAN SERVIR: - int xcmp (const char *v1, const char*v2): Defineix l'ordre que tindra la nostra llista. De fet esta definida, com l'strcmp, per tres casos. Si v1 es menor que v2 retorna int<0 Si v1 es major que v2 retorna int>0 Si v1 es equivalent a v2 definim altres tres casos: | Si no es permeten claus repetides retorna 0 | Si es posposen els elements repetits, retorna int<0 | Si s'anteposen els elements repetits, retorna int>0 - void* xalloc (void): Agafa memoria i inicialitza un nou element. Retorna un punter a aquest nou element. - void* xcpy (void *v1, const void *v2): Modifica v1 per que sigui equivalent a v2. Es retorna un punter a v1 modificat. - void xfree (void *v): Donat un element v, xfree fa el que s'ha de fer per alliberar la memoria que ocupa. - void* xcat (void *v1, const void *v2): Determina el que s'ha de fer quan es troba dos elements que en aplicar-li xcmp retorna 0, es a dir, tenen una clau equivalent i no permetem que hi hagi dos igual a la llista. COM PODEM GENERAR ELS DIFERENTS TIPUS D'INSERCIO: * Si la clau ja existeix, la nova modifica la vella: La funcio xcat fa servir el nou element per modificar l'element que ja estava inserit. * Si la clau ja existeix, la nova no s'insereix: La funcio de xcat nomes ha de retornar el punter al element que ja era a la llista. No modifica res. * Si la clau ja existeix, la nova sustituex la vella: La funcio de xcat posa a dins de l'element que ja era a la llista el contingut del nou element i retorna el mateix punter al antic element. Seria equivalent a la funcio xcopy. * Si la clau ja existeix, la nova es postposa a la vella: Fem que donat dos elements iguals, xcomp retorna un numero negatiu com si la nova fos menor. * Si la clau ja existeix, la nova s'anteposa a la vella: Fem que donat dos elements iguals, xcomp retorna un numero positiu com si la nova fos major. COM PODEM TREBALLAR AMB FINESTRES: * Les uniques funcions que modifiquen la finestra son llista_primer, llista_seguent i llista_posiciona. * A mes tenim les funcions analogues al funcionament per valor: llista_consulta_finestra, llista_fes_copia_finestra, llista_esborra_finestra i llista_afegeix_finestra. * Hem de comprovar quan calgui el valor retornat per la funcio llista_fi. Si el valor que retorna es diferent de zero, les uniques operacions que es poden fer amb la finestra es llista_primer i llista posiciona. * Podem fer consultes per valor sense modificar la finestra. * Si feu servir ordenacio, aneu amb compte quan inseriu per finestra podeu desordenar la llista. * Per no correr riscos, en esborrar per valor quan treballem amb finestra feu un llista_primer!! Es l'unica cosa que pot fer trontollar el funcionament dual. DE QUINS TIPUS DE CONSULTA DISPOSEM: * llista_consulta: Retorna un punter al element de la llista. Qualsevol modificacio que fem en aquest punter, es fara realment en l'element inserit. Si esborrem l'element de la llista ja no s'hi podra accedir. La busqueda es realitza comparant amb un element que es pasa com a parametre. * llista_fes_copia: Deixa a la variable, l'adreca de la qual es pasa com a parametre, una copia de l'element consultat. D'aquesta manera no afecten les modificacions de un i de altre. La busqueda tambe es realitza comparant amb un altre element que se li passa com a parametre. * llista_consulta_finestra i llista_fes_copia_finestra: Retorna el mateix que les anteriors pero, en comptes de fer una busqueda, la consulta la fan a la finestra. MARAVILLES DE LA FUNCIO APLICA: * Si volem fer una modificacio en tota la llista nomes cal que fem: llista_aplica (llista1,funcio_que_apliquem); La funcio_que_apliquem rep un void* a l'element a processar i retorna un void* a l'element una vegada processat. * Si la funcio_que_volem_aplicar, no es del tipus void* f(void*) farem una funcio, que si que s'hi ajusti, que converteixi els parametres d'entrada als que necesitem, cridi a funcio_que_volem_aplicar i converteixi el que retorni a punter al element modificat. * Exemple: Tenim una llista de enters i volem fer una funcio que ens la visualitzi. -Tenim feta ja la funcio: void visualitza_enter (int); -Farem la funcio per adaptar els parametres: void* visualitza_enter2 (void *v) { visualitza_enter ( *((int *)v) ); return (v); } -Per visualitzar tota la llista: aplica (l,visualitza_enter2); GLORIES DE LA FUNCIO ACOMULA: - Aquesta funcio ens estalvia fer servir variables globals per calcular quelcom de tots els elements de la llista com passaria si fem un sumatori de una llista de enters amb la funcio aplica. - Ara el que es modifica no es l'element si no que es una variable de la qual passem com a parametre l'adreca. COM MILLORARLA FENT-LA CIRCULAR - No em vull preocupar pero si a algu se li ocurreix i ho fa, sera molt ben rebuda. - Es podria millorar l'eficiencia de la busqueda mirant l'ultim element abans de tot. COM MILLORARLA FENT-LA DOBLEMENT ENCADENADA - Hauries de afegir un camp 'ant' al tipus_node que apunti a l'anterior que les funcions de insercio i esborrat haurien de mantenir. - Hauries de afegir una funcio llista_anterior que faci retrocedir la finestra o punt d'interes. - S'hauria de afegir una funcio llista_es_inici, la funcio complementaria a llista_fi. COM MILLORAR-LA FENT-LA MULTIFINESTRA - Es podria modificar el camp act per un punter a punters a node que sera un vector de finestres. - Caldria afegir-li al llista_crea un parametre amb el nombre de finestres que volem. - Dins del llista_crea, reservem amb el malloc l'espai pel vector de finestres. - Totes les operacions amb finestra han de tenir un parametre mes que indiqui en nombre de finestra que fem servir.