Instituto de Computación. Facultad de Ingeniería. Universidad de la República Solución Parcial de Programación 2 11 de Mayo 2004 Ejercicio 1.a) Dada una lista de enteros con la siguiente definición: TYPE LInt = POINTER TO NodoLista; NodoLista = RECORD Info : INTEGER; Sig : LInt; END; Este ejercicio consiste en la implementación de un procedimiento iterativo, el cual recibe una lista de enteros LInt y elimina los valores negativos de esta. (* Procedimiento encargado de eliminar los valores negativos de listaEnt *) PROCEDURE NoNegativos(VAR listaEnt : LInt); VAR lAux, lDelete : LInt; BEGIN IF (listaEnt <> NIL) THEN (* Se utiliza un puntero auxiliar para recorrer la lista *) lAux := listaEnt; (* Se controla siempre contra el segundo elemento *) WHILE (lAux <> NIL) AND (lAux^.Sig <> NIL) DO IF (lAux^.Sig^.Info < 0) THEN (* Se ajusta la estructura de la lista*) lDelete := lAux^.Sig; lAux^.Sig := lAux^.Sig^.Sig; (* Se libera la memoria de la celda eliminada *) DISPOSE(lDelete) ELSE lAux := lAux^.Sig (* Se avanza el puntero auxiliar a la siguiente celda *) END; END; (* Caso inicial de que el primer elemento sea negativo *) IF (listaEnt^.Info < 0) THEN lDelete := listaEnt; listaEnt := listaEnt^.Sig; DISPOSE(lDelete) END END END NoNegativos; Página 1 de 5 Ejercicio 1.b) Utilizando la definición de lista LInt se pide escribir una función iterativa, tal que dadas dos listas ordenadas de enteros, la misma debe resolver la intersección de estas, dando como resultado una lista ordenada. (* Función que retorna la interesección de las listas l1 y l2 *) (* Precondición: l1 y l2 están ordenadas y no tienen elementos repetidos *) PROCEDURE Interseccion(l1 : LInt; l2 : LInt) : LInt; (* Punteros auxiliares: lRes contiene una referencia a la lista resultado y lMov es usado para recorrer la lista resultado creando las celdas. l1 y l2 son usados para recorrer las listas. *) VAR lRes, lMov : LInt; BEGIN lRes := NIL; (* Si alguna de las dos listas es NIL entonces no hay más elementos de intersección. *) WHILE (l1 <> NIL) AND (l2 <> NIL) DO IF (l1^.Info = l2^.Info) THEN IF (lRes = NIL) THEN (* Primer elemento de la lista resultado *) NEW(lRes); lRes^.Info := l1^.Info; lRes^.Sig := NIL; lMov := lRes ELSE NEW(lMov^.Sig); lMov^.Sig^.Info := l1^.Info; lMov^.Sig^.Sig := NIL lMov := lMov^.Sig; END; l1 := l1^.Sig; l2 := l2^.Sig ELSIF (l1^.Info < l2^.Info) THEN l1 := l1^.Sig ELSE l2 := l2^.Sig END END; RETURN lRes END Interseccion; Página 2 de 5 Ejercicio 2.a) Dada la siguiente definición extendida de árbol binario de búsqueda en modula 2: TYPE ABB = POINTER TO ABBNode; ABBNode = RECORD Dato : INTEGER; CantSubIzq : CARDINAL; Izq : ABB; Der : ABB; END; La cual almacena en cada nodo la cantidad de hijos izquierdos + 1, se pide la implementación de un procedimiento recursivo que inserte un elemento en dicho árbol manteniendo consistente la estructura del mismo: (* Procedimiento que inserta el elemento k en el ABB t, manteniendo consistente la información de la cantidad de hijos izquierdos. Asumimos que el elemento a insertar no pertenece al árbol. *) PROCEDURE Insertar(VAR t : ABB; k : INTEGER); BEGIN (* Paso Base encargado de crear un nodo *) IF (t = NIL) THEN NEW(t); t^.Dato := k; t^.CantSubIzq := 1; t^.Izq := NIL; t^.Der := NIL ELSE IF (k < t^.Dato) THEN (* Al desplazarme a la izquierda incremento la cantidad de hijos izquierdos del nodo corriente *) t^.CantSubIzq := t^.CantSubIzq + 1; Insertar(t^.Izq, k) ELSE Insertar(t^.Der, k) END END END Insertar; Página 3 de 5 Ejercicio 2.b) Usando la definición anterior de ABB, se pide la construcción de una función tal que dado un árbol del tipo ABB y un natural k, retorne el k-ésimo elemento menor del árbol: (* Función que retorna el k ésimo elemento menor de t. Asumimos que el árbol no tiene elementos repetidos. *) PROCEDURE KMenor(t : ABB; k : CARDINAL) : ABB; (* Se utiliza el propio t para recorrer el árbol *) BEGIN IF (k = 0) THEN RETURN NIL ELSE WHILE (t <> NIL) AND (k <> t^.CantSubIzq) DO IF (k < t^.CantSubIzq) THEN t := t^.Izq ELSE k := k - t^.CantSubIzq; t := t^.Der END END; RETURN t END END KMenor; Página 4 de 5 Ejercicio 3. Dado un conjunto de primitivas sobre lista de naturales y lista de pares de naturales, se pide la construcción de una función tal que dada una lista de naturales retorne una lista de pares de naturales, correspondiente al producto cartesiano de los elementos de la lista de entrada. Para esto se definen las siguientes rutinas recursivas auxiliares: (* Función que retorna la concatenación en una nueva lista de l y l2. *) PROCEDURE AppendLP(l : LParNat; l2 : LParNat): LParNat; BEGIN IF EmptyLP(l) THEN RETURN l2 ELSIF EmptyLP(l2) THEN RETURN l ELSE RETURN ConsLP(HeadLP(l),AppendLP(TailLP(l),l2)) END END Concat; (* Función que retorna una lista de pares, resultado de combinar el natural x con todos los elementos de l. *) PROCEDURE Combinar(x : CARDINAL; l : LNat): LParNat; BEGIN IF Empty(l) THEN RETURN ConsLP(CrearPar(x,x),NullLP()) ELSE RETURN ConsLP(CrearPar(x,Head(l)), ConsLP(CrearPar(Head(l),x), Combinar(x,Tail(l)))) END END Combinar; (* Función que retorna el producto cartesiano de los elementos de l *) PROCEDURE ProdCart(l : LNat):LParNat; BEGIN IF Empty(l) THEN RETURN NullLP() ELSE RETURN AppendLP(Combinar(Head(l),Tail(l)),ProdCart(Tail(l))) END END ProdCart; In.Co. - Instituto de Computación Página 5 de 5