Listas Implemente la función List*SumaProducto(List *A,List*B) que recibe dos listas A y B, con las cuales realiza operaciones de producto y suma cuyos resultados van a formar parte de una tercera lista a retornar. Ejemplo sean las listas A y B A: B: Operaciones a realizar: Nodo 1: 2*3 + 2*0 + 2*2 + 2*1 + 2*4= 20 Nodo 2: + 3*0 + 3*2 + 3*1 + 3*4= 21 Nodo 3: + 1*2 + 1*1 + 1*4= 7 Nodo 4: 2*1 + 2*4= 10 Nodo 5: 4*4= 16 Resultado de SumaProducto: C: Nota: Asuma que A y B son de iguales dimensiones Solución: Note que el problema ya nos dice el prototipo de la función el cual no lo podemos variar: List*SumaProducto(List*A,List*B); Observe también que ya posee las referencias a las dos listas A y B, sobre las cuales vamos a trabajar. Recuerde también que cada elemento de la lista almacena un entero. Nuestro objetivo es generar una nueva lista, la lista C, en donde cada elemento de esta estará en función de dos listas iniciales, la lista A y la lista B. El problema explica claramente como serán generados los nuevos elementos, el cual detallaremos a continuación: El primer elemento de la lista A (2) se multiplica por el primer elemento de la lista B (3), también para los elementos restantes(0,2,1,4),sumamos cada uno de estos resultados y así obtenemos el valor del primer elemento de la lista C (20) Luego el segundo elemento de la lista A (3) se multiplica por el segundo elemento de la Lista B (0), y también por los siguientes (2,1,4), se suma cada uno de estos resultados y así obtenemos el valor del segundo elemento en la lista C (21). Hacemos esto hasta el final de las listas. Recordar que A y B son del mismo tamaño. Es importante tener bien claro como se generan los números para así poder implementar un algoritmo que resuelva el problema. En el código que vera a continuación podrá ver mas claramente en que consiste la solución Código: List *sumaProducto(List *A,List *B){ List *C=listNew(); NodeList *iterator=NULL; NodeList *viajero=NULL; NodeList *tmp=NULL; int x,y; viajero=listGetHeader(B);//también podemos haber declarado viajero= B->header for(iterator=listGetHeader(A);iterator!=NULL;iterator=nodeListGetNext(iterator)){ int cont=0;//esta variable almacenara el valor del nuevo elemento de C //en cada iteraccion debe ser cero ya que en cada iteración guardaremos un nuevo valor for(tmp=viajero;tmp!=NULL;tmp=nodeListGetNext(tmp)){ x=integerGet(nodeListGetCont(iterator)); y=integerGet(nodeListGetCont(tmp));
cont=x*y+cont;//guarda el valor que se almacenara en la lista C } viajero=nodeListGetNext(viajero); listAddNode(C,nodeListNew(integerNew(cont))); } return C;
} Con la referencia al primer elemento de A, iteramos la lista B, generamos el valor que se almacenara en C y lo agregamos a dicha lista. Tome en cuenta la linea de código viajero=nodeListGetNext(viajero). Al tomar el segundo elemento de A, volveremos a iterar la lista B, pero ya no desde el primer elemento de A sino desde el segundo, nuevamente generamos el valor que se almacera en C y lo agregamos a la lista. En la siguiente iteración, tomamos el tercer elemento de A, volveremos a iterar la lista B, pero ya no desde el segundo sino desde el tercero nuevamente generamos el valor que se almacera en C y lo agregamos a la lista. Hacemos esto hasta el final de la lista A.
Implemente una función listaInterceccion que dadas dos listas que representan dos conjuntos de elementos del mismo tipo, generar otra lista intersección que contenga los elementos en común que tienen estas dos listas. List *listInterseccion(List *L,List *M,cmpfn comparar){ NodeList *iterator=NULL, *traveler=NULL; Generic a; List *C=listNew(); for(iterator=listGetHeader(L);iterator!=NULL;iterator=nodeListGetNext(iterator)){ for(traveler=listGetHeader(M);traveler!=NULL;traveler=nodeListGetNext(traveler)){ if(comparar(iterator->cont,traveler->cont)==0){ a=nodeListGetCont(traveler); listAddNode(C,nodeListNew(a)); } } } return C; } Implemente la función listaRemoverRepetidos que dada una lista remueva los elementos repetidos de ella. Cree un programa que genere una lista de enteros repetidos y pruebe la función que ha implementado void listaRemoverRepetidos(List *L,cmpfn fn){ NodeList *iterator=NULL,*tmp=NULL,*traveler=NULL; for(iterator=listGetHeader(L);iterator!=NULL;iterator=nodeListGetNext(iterator)){ for(traveler=nodeListGetNext(iterator);traveler!=NULL;traveler=nodeListGetNext(traveler)) { if(fn(nodeListGetCont(iterator),nodeListGetCont(traveler))==0){ tmp=traveler->next; listRemoveNode(L,traveler);
traveler->next=tmp; } }
}
}
int main() { List *A=listNew(); int i=0; //Creamos una lista de enteros con nodos repetidos para probar la funcion que hemos implementado for(i=0;i<10;i++){ listAddNode(A,nodeListNew(integerNew(i))); listAddNode(A,nodeListNew(integerNew(i))); } printf("Lista:\n"); listPrint(A,(void*)integerPrint); printf("\nLista removida:\n"); listaRemoverRepetidos(A,integerCmp); listPrint(A,(void*)integerPrint); return (EXIT_SUCCESS);
} Escriba una función buscaLista que recursivamente busque un valor en una lista ligada. La función debe devolver un apuntador hacia el valor, si es que si lo encuentra; de lo contrario, debe devolver NULL. NodeList*buscarEnLista(NodeList*header,NodeList*buscado,cmpfn comparar){ NodeList*encontrado=NULL; if(header==NULL){ return NULL; } if(comparar(header->cont,buscado->cont)==0){ encontrado=header; return encontrado; }else{ encontrado=buscarEnLista(header->next,buscado,comparar); } return encontrado; } Implemente la función ListConcat que, dadas dos listas, concatene los elementos de la segunda a la primera. void
ListConcat(List*A,List*B){ NodeList*it=NULL; for(it=listGetHeader(B);it!=NULL;it=nodeListGetNext(it)){//Empezamos a iterar la lista B desde el principio listAddNode(A,nodeListNew(it->cont));//Agregamos el contenido de it a un nuevo nodo, que se añadira a la lista A
} }
Implementar dos funciones complementarias a las listas: a) Insertar ordenadamente los elementos de una lista (no está ordenada) en otra lista (que ya está ordenada), la lista final no debe tener elementos repetidos. b) Dada una lista generar otra lista con los elementos repetidos. a) Para resolver este problema debemos tener en cuenta lo siguiente. - En un principio tendremos dos listas, la Lista A que no esta ordenada, y la Lista B que ya posee un orden en especial. Observe que usted no sabe que tipo de dato se encuentra dentro de las listas, ni tampoco el tipo de ordenamiento. Entonces nuestra función debe estar en la capacidad de ordenar cualquier lista que contenga cualquier TDA, es decir la función debe ser lo mas genérica posible. Para esto usaremos una funcion CallBack (cmpfn compare). compare(a,b) retornara cero si a y b son iguales, 1 si a>b, y -1 si acont,compare);//busca el elemento que almacena it en la lista B if(newNode==NULL){ //si el elemento buscado no se encuentra procedemos a insertar en donde corresponda newNode=nodeListNew(it->cont); //newNode es el nodo a insertar if(compare(newNode->cont,min->cont)==-1){ //inserción al principio de la Lista B nodeListSetNext(newNode,min);
B->header=newNode; }else{ if(compare(newNode->cont,max->cont)==1){ //inserción al final de la Lista B nodeListSetNext(max,newNode); B->last=newNode; }else{ while(min!=NULL){ //inserción en el medio de la Lista B //buscamos la posición correcta para insertar min=min->next; if(compare(newNode->cont,min->cont)==-1){ prev=listGetPrevious(B,min); // Recuerde que la función listGetPrevious nos retorna un puntero al elemento previo de la variable min nodeListSetNext(newNode,min); nodeListSetNext(prev,newNode); break; } } } } } } } No olvide definir la función de comparación que se ajuste al tipo de dato que almacenan las listas. Supongamos que estos son enteros, entonces tendremos. int compare(Generic a,Generic b){ int x=integerGet(a); int y=integerGet(b); if(x==y)return 0; if(x>y)return 1; return -1; } Antes de seguir con el siguiente literal. Piense en el siguiente problema. Suponga que las listas almacenan el tipo de dato CuentaBancaria , y se desea que el tipo de ordenamiento sea con respecto al saldo de cada cuenta bancaria. Recuerde que asumimos también que el orden seria de menor a mayor. Ademas se le proporciona la siguiente información: typedef struct CuentaBancaria{ int ID; char propietario[20]; double saldo; }CuentaBancaria; CuentaBancaria*cuentaBancariaGet(Generic a);//permite recuperar la cuenta bancaria almacenada en una variable Generic ¿Que haría falta implementar para resolver el problema? La respuesta es sencilla, solo tendríamos que plantear una función que compare cuentas bancarias. int compare(Generic a,Generic b){ CuetaBancaria c1=cuentaBancariaGet(a); CuentaBancaria c2=cuentaBancariaGet(b); if(c1->saldo==c2->saldo)return 0; if(c1->saldo>c2->saldo)return 1; return -1; } b) Antes de pensar en la implementación primero definamos el prototipo de la función. Esta vez el problema nos dice implícitamente cual sera el modelo de la función. Primero que recibiremos una
variable lista como parámetro a la cual le vamos a invertir sus elementos. Segundo nuestra función debe devolver otra lista. Entonces tendremos: List*invertirLista(List*L); La implementación consiste en remover el ultimo elemento de la lista enviada por parámetro, agregarla en la lista nueva, hacer esto hasta que la lista inicial este vacía. Al final retornamos la lista invertida. List *invertiLista(List *L){ NodeList *iterator; List *invertida=listNew(); NodeList *tmp; while(!listIsEmpty(L)){ iterator=listGetLast(L); tmp=listRemoveLast(L); listAddNode(invertida,tmp); } return invertida; } Sea el TDA: typedef struct { List* l_ordenada; Orden orden; }PriorityQueue; Donde Orden es un tipo de datos enumeración cuyos valores son ASC Y DES, que representa el tipo de ordenamiento de los elementos en la cola y l_ordenada representa una lista ordena. Implemente el comportamiento: priorityQueueEnqueue(PriorityQueue *Q,NodeList *newNode,fnCmp compare) El cual inserta un nuevo nodo en la ubicación que le corresponde de acuerdo al tipo de ordenamiento de la cola. El parámetro compare representa una funciona de CallBack que recibe dos parámetros que son los contenidos de los nodos a comparar y retorna 0 si son iguales, -1 si el primero es menor que el segundo y 1 si el primero es mayor que el segundo. Tenga en cuenta lo siguiente: Cuando la lista esta vacía, simplemente insertamos el nodo como único elemento de la lista. El procedimiento debe estar en función del tipo de ordenamiento de la cola. Sabemos que la función compare retorna 1 si el primer elemento es mayor que el segundo, orden descendente(DES). Compare retorna -1 si el primer elemento es menor que el segundo, orden ascendente(ASC). Existen tres tipos de inserciones, al inicio de la lista, en medio de la lista, y al final de la lista. Inicio de la lista: Sabemos que el primer elemento de la lista sera el mayor en un orden descendente. Si el nuevo nodo es mayor que el mayor de todos los elementos ya ingresados, entonces el nuevo nodo se inserta al inicio, caso similar ocurre en el orden ascendente. En el medio de la lista: Comparamos cada elemento de la lista con el nuevo nodo, de esta forma encontraremos la posición exacta en donde insertar. Final de la lista: Si no se inserto al inicio, ni en el medio, agregamos el nuevo nodo al final de la lista. El siguiente código resuelve el problema, léalo detenidamente y pruebe que este funciona como debería. Código: typedef enum orden{ ASC, DES } Orden; int orden(Orden orden) { if (orden == 0) {//si el orden es ASC retornamos -1
}
return -1; }else{//si el orden es DES retornamos 1 return 1; }
void priorityQueueEnQueue(PriorityQueue *Q, NodeList *newNode, cmpfn compare) { NodeList* it, * tmp; List *L=Q->l_ordenada; if (listIsEmpty(Q->l_ordenada)) { listAddNode(Q->l_ordenada, newNode); return; } it = listGetHeader(L); if (compare(newNode->cont, it->cont) == orden(Q->orden)) { listAddFirst(L, newNode);//insertar al principio de la lista return; } for (it = listGetHeader(L); it != NULL; it = it->next) { if (compare(newNode->cont, it->cont) == orden(Q->orden)) { tmp = listGetPrevious(Q->l_ordenada, it); listAddNext(Q->l_ordenada, tmp, newNode);//inserta en el medio return; } } listAddNode(Q->l_ordenada, newNode);//inserta al final return; }
Implemente la función List_RemoveLastOcurrence (o Lista_RemoverUltimaOcurrencia) que, dada una lista con posibles elementos repetidos, remueva el último nodo que contiene a un elemento indicado. Como ejemplo ilustrativo, considere la siguiente lista de Personas: L
L
List_RemoveLastOcurrence (L,
, …)
Observe que el problema le da la facilidad de escoger los parametros y el tipo de dato de retorno. Usaremos una funcion callBack para facilitar el trabajo, podemos definir el prototipo de la funcion de la siguiente forma: void List_RemoveLastOcurrence(List*L,NodeList*element,cmpfn comparable); Recuerde que comparable(a,b) devuelve 0 si a es igual a b, 1 si a>b y -1 si a
void List_RemoveLastOcurrence(List*L,NodeList*element,cmpfn comparable){ NodeList*iterator=NULL; NodeList*tmp=NULL; for(iterator=listGetHeader(L);iterator!=NULL;iterator=nodeListGetNext(iterator){ if(comparable(element->cont,iterator->cont==0){ tmp=iterator;//tmp almacenara la ultima ocurrencia de element } } if(tmp==NULL){//si tmp nunca entro al condicional definido dentro del ciclo for entonces quiere decir que element no se encuentra en la lista printf(“No se ha encontrado element en la lista”); return; }else{// el paso final es remover element de la lista L iterator=listGetPrevious(L,tmp); iterator->next=tmp->next; tmp->next=NULL; tmp=NULL; return; } }