Está en la página 1de 9

Pontificia Universidad Javeriana

Departamento de Ingeniería de Sistemas


Estructuras de Datos, 2023-10
Parcial 2 - 19 de abril de 2023

Reglas y recomendaciones
Durante el parcial, deben observarse las siguientes reglas:

1. El parcial se debe desarrollar en el computador, escribiendo las respuestas en los campos designados
dentro del cuestionario de BrightSpace.

2. Archivos adicionales se aceptarán sólo en el caso del diseño, de acuerdo a las instrucciones que
se encuentran en el enunciado del parcial. Guarde regularmente su trabajo (para evitar posibles
pérdidas de información), con los nombres de archivo
par2_apellido1_apellido2_nombre1_nombre2.txt (para el diseño de los TADs) y
par2_apellido1_apellido2_nombre1_nombre2_dis.pdf (para el diagrama de relación entre TADs)
Tenga en cuenta que los nombres y apellidos van todos en minúsculas, los espacios se reemplazan
por guiones bajos y no se utilizan ni tildes ni ’ñ’. Estos archivos deben enviarse únicamente dentro
de la pregunta correspondiente en el cuestionario de BrightSpace.

3. El parcial tiene una duración de dos horas, contadas a partir del inicio normal de la clase. El
cuestionario en BrightSpace está programado para cerrarse al terminar las dos horas, por lo que
no enviarlo dentro de ese lapso de tiempo se considerará como parcial no presentado y tendrá una
calificación de 0.0.

4. El parcial es estrictamente individual y se debe desarrollar únicamente en la sala de computadores


del día.

5. Se recomienda no utilizar compiladores, intérpretes de lenguajes de programación o entornos de


desarrollo de cualquier tipo.

6. Puede utilizar sus apuntes, libros, e Internet para obtener la información que necesite para el parcial.
Puede utilizar también herramientas de inteligencia artificial (tipo ChatGPT), bajo su propio riesgo
y corroborando la información obtenida.

7. Sin embargo, está absolutamente prohibido comunicarse con cualquier otro ser humano para obtener
información sobre el parcial, a través de cualquier medio (conversación directa, Teams, Skype, Zoom,
Gtalk, Whatsapp, etcétera). También está totalmente prohibido copiar o transcribir texto o código
de enunciados y respuestas de parciales anteriores, o de diseños e implementaciones que no sean
propias.

8. Los celulares deben permanecer apagados, y no se debe enviar ni recibir ningún mensaje de texto.

9. La única excepción a lo anterior son los profesores y monitores de la asignatura, quienes sólo respon-
derán consultas respecto a la claridad de las preguntas del parcial y no responderán consultas sobre
la materia.

10. Si el estudiante incumple con cualquiera de las reglas, será evaluado con nota 0.0

11. Recuerde que diseñar no implica implementar.


1 (18%) Selección múltiple con única respuesta (3 preguntas)
1.1 Se puede garantizar que la complejidad de las operaciones de inserción y elimi-
nación en cualquier montículo es:
1. Siempre O(log n).

2. Mínimo O(1), máximo O(log n).

3. Mínimo O(1), máximo O(n).

4. Siempre O(n/2).

1.2 El montículo con representación en arreglo [0 1 5 2 8 10 6 4 3], corresponde a


un:
1. Montículo máximo.

2. Montículo promedio.

3. Montículo mediana.

4. Montículo mínimo.

1.3 Para evaluar una expresión aritmética escrita en notación posfija, usando una
pila, es necesario:
1. Procesar la expresión de izquierda a derecha, y al extraer de la pila, sacar primero el operando
derecho y luego el izquierdo.

2. Procesar la expresión de derecha a izquierda, y al extraer de la pila, sacar primero el operando


derecho y luego el izquierdo.

3. Procesar la expresión de izquierda a derecha, y al extraer de la pila, sacar primero el operando


izquierdo y luego el derecho.

4. Procesar la expresión de derecha a izquierda, y al extraer de la pila, sacar primero el operando


izquierdo y luego el derecho.

2 (14%) Falso o verdadero (2 preguntas)


2.1 La estructura de un árbol binario ordenado se puede regenerar a partir del
recorrido en inorden del árbol.
Falso, se puede regenerar a partir del recorrido en preorden del árbol.

2.2 El ordenamiento de los elementos o claves dentro de estructuras como set o map
en la STL se realiza internamente con un árbol Rojo-Negro.
Verdadero.
3 (68%) Diseño e Implementación de TADs
Uno de los posibles usos que puede dársele a un árbol en un contexto particular es un árbol de clasificación,
en donde diferentes instancias de algunas clases (tipos) de elementos se ubican de acuerdo a características
particulares en un espacio de características, y el recorrido dentro del árbol permite la clasificación de
nuevos elementos de acuerdo a estas características. Las características suelen especificarse como un
vector de n valores (n dimensiones), y la clase (tipo) a la que pertenece el elemento suele acompañar
este vector (sin considerarla una característica o dimensión). Un ejemplo de árbol de clasificación puede
apreciarse a continuación:

Figure 1: Ejemplo de árbol de clasificación para tres tipos diferentes de flor Iris, a par-
tir de los valores de dos características diferentes (longitud y ancho del pétalo). Tomado de
http://www.ams.org/publicoutreach/feature-column/fc-2014-12

Una empresa distribuidora de verduras, llamada Venta Verduras, se encarga de repartir diferentes
clases de verduras (como tomates, pepinos, pimentones, cebollas, etc.) en las tiendas de varios barrios
de Bogotá. Estas verduras pueden caracterizarse básicamente por dos valores: su peso (en gramos) y su
color (el cual está codificado en una escala numérica del 0 al 15). La clase de verdura suele especificarse
con una cadena de caracteres: “tomate”, “pepino”, “cebolla”. En algunos raros casos, no es fácil reconocer
el nombre o etiqueta de una verdura. Para ayudar a la empresa, uno de sus empleados ha considerado
utilizar un árbol de clasificación. De esta forma, la información de las verduras conocidas se puede ubicar
en el árbol, de acuerdo a sus características de peso y color, y para una nueva verdura que no se pueda
reconocer, se usa el árbol de clasificación con la información de sus características para intentar asignarle
la etiqueta más adecuada.
Sin embargo, este empleado no tiene idea de cómo implementar esta brillante idea, y requiere su ayuda
para generar un sistema que permita clasificar estas verduras desconocidas. En una primera versión, se
ha identificado que este sistema debe llegar a proveer las siguientes operaciones:
1. Inicializar el sistema con ejemplos. Dada una lista de verduras con características conocidas (peso y
color de cada una, junto con su respectiva clase), el sistema debe construir el árbol de clasificación,
tomando cada verdura de ejemplo y ubicándola adecuadamente dentro del árbol, de forma que se
facilite después la clasificación de nuevas verduras. La ubicación de cada verdura de ejemplo en el
árbol se hace únicamente de acuerdo a sus características básicas (peso y color), pero debe mantenerse
como atributo adicional su respectiva clase, para facilitar posteriormente el etiquetado de verduras
desconocidas.
2. Clasificar una nueva verdura. Dadas las características básicas (peso y color) de una nueva verdura,
el sistema debe recorrer el árbol de clasificación buscando aquella verdura que coincida en términos
de estas características, con lo cual puede retornarse la clase o etiqueta de esa verdura. Si no existe en
el árbol una verdura que coincida exactamente, se debe generar una sugerencia de etiqueta, tomando
la más cercana a la verdura de entrada.

Se le pide entonces diseñar e implementar (en C++) la primera versión del sistema de clasificación del
verduras, que permita responder algorítmicamente a las operaciones descritas anteriormente.

3.1 (18%) Diseño


Diseñe el sistema y el (los) TAD(s) solicitado(s). Utilice la plantilla de especificación de TADs vista en
clase para el diseño. Recuerde que diseñar es un proceso previo a la implementación, por lo que no debería
contener ninguna referencia a lenguajes de programación (es decir, si escribe encabezados o código fuente,
el punto no será evaluado y tendrá una calificación de cero). Para simplicidad del diseño, no es necesario
incluir los métodos obtener y fijar (get/set) del estado de cada TAD.

Tipo de dato Punto, definido con: entero g, entero c.

TAD Verdura
Datos mínimos:
- caract, Punto, representa las características de la verdura (peso y color).
- clase, cadena de caracteres, representa la clase o tipo de verdura.
Operaciones:
- obtenerCaract(), retorna las características de la verdura.
- obtenerClase(), retorna la clase de la verdura.
- fijarCaract(npunto), cambia las características actuales de la verdura de acuerdo
a lo almacenado en npunto.
- fijarClase(nclase), cambia la clase actual de la verdura a nclase.

TAD Nodo
Datos mínimos:
- dato, Verdura, representa la información a almacenar en el nodo.
- hijoSupIzq, apuntador a Nodo, representa la conexión al hijo superior-izquierdo
del nodo.
- hijoSupDer, apuntador a Nodo, representa la conexión al hijo superior-derecho del
nodo.
- hijoInfIzq, apuntador a Nodo, representa la conexión al hijo inferior-izquierdo
del nodo.
- hijoInfDer, apuntador a Nodo, representa la conexión al hijo inferior-derecho del
nodo.
Operaciones:
- obtenerDato(), retorna el dato del nodo.
- obtenerHijoSupIzq(), retorna la conexión actual al hijo superior-izquierdo.
- obtenerHijoSupDer(), retorna la conexión actual al hijo superior-derecho.
- obtenerHijoInfIzq(), retorna la conexión actual al hijo inferior-izquierdo.
- obtenerHijoInfDer(), retorna la conexión actual al hijo inferior-derecho.
- fijarDato(ndato), cambia el dato actual por ndato.
- fijarHijoSupIzq(nhijoSI), cambia la conexión al hijo superior-izquierdo por
nhijoSI.
- fijarHijoSupDer(nhijoSD), cambia la conexión al hijo superior-derecho por
nhijoSD.
- fijarHijoInfIzq(nhijoII), cambia la conexión al hijo inferior-izquierdo por
nhijoII.
- fijarHijoInfDer(nhijoID), cambia la conexión al hijo inferior-derecho por
nhijoID.
- esHoja(), informa si el nodo tiene o no conexiones a sus hijos.

TAD Arbol
Datos mínimos:
- raíz, apuntador al Nodo, representa en nodo raíz o inicial del árbol.
Operaciones:
- obtenerRaiz(), retorna el apuntador al nodo raíz del árbol.
- fijarRaiz(nraiz), cambia la raíz actual del árbol por nraiz.
- esVacio(), informa si el árbol está vacío o no.
- insertar(ndato), ingresa el dato ndato dentro del árbol de acuerdo a las reglas
de un quadtree: se compara en cada nivel con respecto los valores en cada
dimensión, para escoger uno de los 4 hijos para avanzar, y al encontrar un espacio
vacío, allí es donde se inserta.
- buscarMasCercano(ndato), identifica y retorna el nodo del árbol más cercano al dado
por ndato.

TAD VentaVerduras
Datos mínimos:
- clasArbol, Arbol, representa el árbol de clasificación que almacena las verduras.
Operaciones:
- obtenerClasArbol(), retorna el árbol de clasificación del sistema.
- fijarClasArbol(narbol), cambia el árbol de clasificación actual del sistema por
narbol.
- IniciarSistema(vejemplos), utiliza los ejemplos dados en el contenedor vejemplos
para construir el árbol de clasificación y almacenar todas las verduras conocidas,
de acuerdo a sus características básicas y a la estructura del árbol seleccionado.
- ClasificarVerdura(vpeso,vcolor), utiliza las características dadas de una verdura
específica para localizar el ejemplo más cercano en el árbol y así utilizar su
clase para etiquetar la verdura desconocida.

3.2 (7%) Diagrama de relación


El diseño incluye el diagrama de relación entre TADs, cuando se definen dos o más TADs en el punto
anterior. En ese caso, adjúntelo en formato PDF, JPG o PNG como parte de su entrega.

Verdura Nodo Arbol


-caract -dato -raiz
-clase -hijoSupIzq
1 1 1 1 +fijarRaiz
+fijarCaract -hijoSupDer
-hijoInfIzq +obtenerRaiz
+fijarClase
+obtenerCaract -hijoInfDer
1
+obtenerClase +fijarDato
+fijarHijoSupIzq 1
+fijarHijoSupDer
+fijarHijoInfIzq VentaVerduras
+fijarHijoInfDer -clasArbol
+obtenerDato
+obtenerHijoSupIzq +fijarClasArbol
+obtenerHijoSupDer +obtenerClasArbol
+obtenerHijoInfIzq +IniciarSistema
+obtenerHijoInfDer +ClasificarVerdura
3.3 (24%) Operación 1: Inicializar el sistema
Dado el (los) TAD(s) ya diseñado(s), escriba la implementación en C++ del algoritmo que permite ini-
cializar el sistema, al poblar el árbol de clasificación con una lista de ejemplos conocidos. La imple-
mentación deberá tener en cuenta:

• la definición apropiada de los prototipos de los métodos/funciones (i.e. recibir/retornar los datos
suficientes y necesarios para su correcta ejecución),

• el NO uso de salidas/entradas por pantalla/teclado (i.e. paso/retorno correcto de valores y/o obje-
tos),

• el correcto uso del diseño definido en el punto anterior, y

• la escritura de todo el código que pueda llegar a necesitar que no esté incluido en la STL.

// Pasos a seguir:
// - Recorrer la lista de Verdura.
// - Para cada verdura, llamar a la función insertar del árbol.
// - En la función insertar del árbol:
// - utilizar comparaciones de mayor que o menor que en cada dimensión del punto
// para avanzar en el hijo respectivo.
// - al llegar al final de la ruta (cuando ya no se pueda avanzar más de acuerdo
// a las comparaciones), crear un nuevo nodo con la verdura y conectarlo como
// el correspondiente hijo para insertarlo en el árbol.
// - Retornar el árbol con todas las verduras del contenedor.

Arbol<Verdura> VentaVerduras::IniciarSistema( std::list<Verdura> vejemplos ) {


bool insertado;
std::list<Verdura>::iterator it;
for (it = vejemplos.begin(); it != vejemplos.end(); it++) {
insertado = clasArbol.insertar(*it);
}

return clasArbol;
}

bool Arbol::insertar (Verdura n_dato) {


bool res = false;

if (raiz == NULL) {
raiz = new Nodo;
raiz->fijarDato(n_dato);
res = true;
} else {
Nodo *p = raiz;
Nodo *pp = NULL;
bool duplicado = false;

while (p != NULL) {
pp = p;
Punto bus = n_dato.obtenerCaract();
Punto act = p->obtenerDato().obtenerCaract();

if (bus == act) {
duplicado = true;
break;
} else {
if (bus.g < act.g && bus.c >= act.c) {
p = p->obtenerHijoSupIzq();
} else if (bus.g >= act.g && bus.c >= act.c) {
p = p->obtenerHijoSupDer();
} else if (bus.g < act.g && bus.c < act.c) {
p = p->obtenerHijoInfIzq();
} else if (bus.g >= act.g && bus.c < act.c) {
p = p->obtenerHijoInfDer();
}
}
}

if (!duplicado) {
Nodo *n = new Nodo;

if (n != NULL) {
n->fijarDato(n_dato);
Punto nue = n_dato.obtenerCaract();
Punto pad = pp->obtenerDato().obtenerCaract();

if (nue.g < pad.g && nue.c >= pad.c) {


pp->fijarHijoSupIzq();
} else if (nue.g >= pad.g && nue.c >= pad.c) {
pp->fijarHijoSupDer();
} else if (nue.g < pad.g && nue.c < pad.c) {
pp->fijarHijoInfIzq();
} else if (nue.g >= pad.g && nue.c < pad.c) {
pp->fijarHijoInfDer();
}

res = true;
}
}
}

return res;
}

3.4 (19%) Operación 2: Clasificar una verdura


Dado el (los) TAD(s) ya diseñado(s), escriba la implementación en C++ del algoritmo que permite tomar
las características de una nueva verdura y asignarle una etiqueta o clase de acuerdo a la información en el
árbol de clasificación. Así como en el punto anterior, la implementación deberá tener en cuenta:

• la definición apropiada de los prototipos de los métodos/funciones (i.e. recibir/retornar los datos
suficientes y necesarios para su correcta ejecución),

• el NO uso de salidas/entradas por pantalla/teclado (i.e. paso/retorno correcto de valores y/o obje-
tos),

• el correcto uso del diseño definido en el punto anterior, y

• la escritura de todo el código que pueda llegar a necesitar que no esté incluido en la STL.

// Pasos a seguir:
// - Construir una nueva verdura con los datos dados pero sin clase asociada.
// - Llamar a la función buscar del árbol con la nueva verdura.
// - En la función buscar del árbol:
// - avanzar sobre el árbol de acuerdo a los valores de las dimensiones.
// - si se llega a un nodo que coincide exactamente con las características,
// retornar la clase de ese nodo.
// - si se llega a un nodo que no coincide exactamente con las características,
// pero que ya no permite avanzar más de acuerdo a los valores de las dimensiones,
// se utiliza ese nodo como el más cercano, y se retorna la clase de ese nodo.

std::string VentaVerduras::ClasificarVerdura ( unsigned int vpeso, unsigned short vcolor ) {


Verdura n_verdura;
Punto n_caract;
n_caract.g = vpeso;
n_caract.c = vcolor;
n_verdura.fijarCaract(n_caract);
n_verdura.fijarClase(“”);

Nodo *nn = clasArbol.buscarMasCercano(n_verdura);

if (nn != NULL) {
return nn->obtenerDato().obtenerClase();
} else {
return “”;
}
}

Nodo* Arbol::buscarMasCercano (Verdura n_dato) {


Nodo *p = raiz;
Nodo *pp = NULL;
Punto bus = n_dato.obtenerCaract();

while (p != NULL) {
pp = p;
Punto act = p->obtenerDato().obtenerCaract();

if (bus == act) {
break;
} else {
if (bus.g < act.g && bus.c >= act.c) {
p = p->obtenerHijoSupIzq();
} else if (bus.g >= act.g && bus.c >= act.c) {
p = p->obtenerHijoSupDer();
} else if (bus.g < act.g && bus.c < act.c) {
p = p->obtenerHijoInfIzq();
} else if (bus.g >= act.g && bus.c < act.c) {
p = p->obtenerHijoInfDer();
}
}
}

if (p != NULL) {
return p;
} else {
return pp;
}
}

También podría gustarte