You are on page 1of 24

TUPLAS

Introducción a las Estructuras de Datos


Definición de nuevos tipos de datos
Manipulación de tuplas
Vectores de tuplas
Lectura/escritura de Tuplas desde teclado y fichero
Funciones y acciones que devuelven tuplas
Ejercicio completo
Ejercicios propuestos

Introducción a las Estructuras de Datos

Hasta ahora hemos centrado básicamente nuestro estudio en una forma adecuada de
algoritmizar problemas, o lo que es lo mismo, de encontrar algoritmos de solución para
ciertos problemas del mundo real. Para conseguirlo nos hemos basado en:

• Utilización eficiente de las estructuras de control básicas: asignación, secuencia,


alternativa e iteración
• Dividir el problema en subproblemas más fáciles de solucionar, construyendo
programas según un diseño descendente o top-down (diseño modular)
• Reutilización de algoritmos mediante la utilización de librerías de componentes ya
desarrollados y probados

Sin embargo, existe otro gran area de conocimiento que hemos tratado con poca
profundidad hasta ahora y es la de utilizar tipos de datos “avanzados”. En nuestro
estudio hemos introducido los tipos básicos (predefinidos) como el entero, el real, el
carácter, o el lógico, y con posterioridad hemos visto como agrupar datos del mismo
tipo (homogeneos) en “almacenes” como son las tablas1. A la vez hemos estudiado que
los datos pueden proceder del dispositivo de entrada estandar (el teclado) o bien pueden
proceder de un almacenamiento permanente en disco (un fichero2). Asimismo la
escritura de resultados puede realizarse en pantalla o bien en ficheros.

En programación existe una igualdad que debe intentar cumplirse:

PROGRAMA = ALGORITMO + ESTRUCTURAS DE DATOS

De tal forma que los programas desarrollados con estructuras de datos adecuadas,
resultan de mayor nivel y legibilidad, redundando esto en su costo de mantenimiento, de
actualización y de desarrollo.

Como estructuras de datos (EDs) se conoce a todo aquello que sirva para almacenar
de forma organizada distintas informaciones que se deban manipular en los algoritmos.
Existen distintos tipos de EDs como son las listas, colas, árboles, grafos, etc., que se
salen fuera de nuestros objetivos. Sin embargo vamos a estudiar como crear nuevos
1
Comúnmente en programación se llama vectores o arrays a las tablas unidimensionales, y matrices a las
bidimensionales. Además, los arrays de caracteres se denominan cadenas o strings.
2
Los ficheros que hemos estado utilizando han sido de texto (que contienen caracteres ASCII o de otro
código), pero también pueden utilizarse ficheros binarios, cuya manipulación es más eficiente y
compacta, pero que no pueden ser abiertos con un editor de texto.
tipos de datos a partir de los ya existentes, de forma que las nuevas variables de estos
nuevos tipos puedan contener información diversa (hetereogenea). A estos tipos de
datos los llamaremos estructuras, registros o tuplas.

Ejemplo: si queremos almacenar algunas de las distintas informaciones que


caracterizan a una persona, podremos crear una tupla que contenga un espacio para
almacenar su nombre, otro para su edad y otro para su teléfono (cada una de estas
informaciones se denomina campo, y cada uno será del tipo adecuado a los datos que
tenga que albergar):

Nombre: cadena Edad: entero Teléfono: cadena

Definición de nuevos tipos de datos

Definiremos en lenguaje algorítmico los nuevos tipos de datos dentro del párrafo
Utilizando, de forma que podremos utilizarlos en el fichero en el que se incluya3. Veamos
un ejemplo concreto:

Ejemplo: definición de un tipo de datos tupla para contener información relativa a una
persona. Al nuevo tipo lo llamamos persona.

Utilizando

Tipo
Persona=tupla
Nombre: cadena
Edad: entero
Telefono: cadena
ftupla
Ftipo

A partir de esta definición podemos crear variables de ese nuevo tipo, y por supuesto
podemos dar valores a sus campos, para lo que utilizaremos el operador de selección de
campo ( . ):

p, q: persona;

p.nombre:= ”pepe”
p.edad:= 23
p.telefono:= ”956662112”

Podemos asignar variables de tipo estructura directamente (por ejemplo, para dos
hermanos gemelos):

q:=p
q.nombre:= ”manolo”

Se pueden crear tipos aún más avanzados, a partir de los ya existentes:


3
Podemos hacerlo también de otra forma: crear un fichero independiente con los nuevos tipos de datos
que queramos utilizar en nuestra aplicación en incluir éste posteriormente en todos aquellos archivos en
los que se pretenda hacer uso de esos tipos.
Ejemplo: creación de un tipo tupla alumno, a partir del tipo persona (damos por hecho
que cualquier alumno es una persona, y además tiene otras características)

Tipo
Alumno=tupla
Datos: persona
Notas: tabla[50] de real
Curso: entero
ftupla
Ftipo

De esta forma, podemos definir variables de este nuevo tipo y darle valores:

x,y: alumno

x.curso:= 1
x.notas[0]:= 5.0
x.notas[1]:= 7.5
x.datos.nombre:= “carlos”

Manipulación de tuplas

Aparte de dar valores individuales a los campos de una variable de tipo estructura,
debemos estudiar por su importancia y amplia utilización la forma de crear tablas o
vectores de tuplas y como rellenar éstas con informaciones procedentes ya sea de
teclado o de fichero.

Creación de vectores de tuplas

De la misma manera que creabamos tablas de números reales o de enteros, es posible


crear variables que sean tablas de registros. Por ejemplo:

lista_amigos: tabla[100] de persona


lista_clase: tabla[400] de alumno

Con estas definiciones podemos hacer, por ejemplo, que “pepe” sea nuestro primer
amigo:

lista_amigos[0]:=p // ya que “pepe” era la variable persona p

O podemos rellenar individualmente algún campo de alguno de nuestros amigos:

lista_amigos[1].nombre:= “alfonso”

Evidentemente sobre los vectores de tuplas se pueden utilizar los mismos mecanismos
que sobre las tablas de enteros o reales que estabamos acostumbrados a manejar. Es
decir, se pueden atacar de la misma forma (con los mismos esquemas) problemas de
recorrido y de búsqueda. Veremos algunos ejemplos después del apartado siguiente.
Lectura/escritura de Tuplas desde teclado y fichero

Directamente vamos a escribir una acción para leer una serie de informaciones desde el
teclado y almacenar sus valores en un vector de registros. Como las tablas tienen una
longitud finita, debemos controlar no pasarnos del límite de valores definidos
(supongamos máximo4 100). Además el algoritmo devolverá el número de personas
introducidas en el vector, es decir que el vector no tiene porqué rellenarse de forma
completa. Como marca o persona final utilizaremos la persona cuyo nombre sea “fin”.

acción LeerTuplas (sal v:tabla[100] de persona, sal numero_personas: entero)


var
p: persona
i: entero
fvar
i:=0
leer(p)
mientras p.nombre < > “fin” y i < 100 // para no pasarnos del tamaño definido
v[i]:=p
i:=i+1
leer(p) // se puede leer( ) una estructura
fmientras
numero_personas:=i // devolvemos el número de personas que hay en el vector
facción

En realidad, no hay demasiadas cosas nuevas, ya que la manipulación de vectores


incompletos era un asunto que ya habíamos tratado con anterioridad. Ahora vamos a
escribir una acción que rellene el vector de tuplas con los datos contenidos en un fichero
de texto que tiene el formato siguiente:
Pepe 23 956662112
Carlos 24 956661221

accion LeerFicheroTuplas (ent nomfich: cadena, sal v:tabla[100] de persona,


sal numero_personas: entero)
var
p: persona; i: entero
f: fichero; e: lógico
fvar
AbrirFich(nomfich,”lectura”,f,e)
si (no e)
i:=0
mientras (no FinFich(f)) y i<100
LeerFich(f,p)
v[i]:=p
i:=i+1
fmientras
numero_personas:=i
sino
numero_personas:=-1 // para controlar desde el exterior el error
fsi
CerrarFich(f)
facción

4
Cuando utilicemos en nuestros programas vectores o matrices de cualquier tipo, es necesario que
tengamos en cuenta que las dimensiones por defecto de memoria reservada para cada programa no son
muy amplias con lo que el tamaño de las tablas no podrá rebasar un cierto valor dependiente de cada
compilador y de algunas opciones de éste.
Para escribir en un fichero un vector incompleto de tuplas podemos hacer un recorrido
del vector hasta el número de elementos que realmente contenga:

Acción EscribirFicheroTuplas (ent nomfich: cadena, ent v:tabla[100] de persona,


ent numero_personas: entero)
var
i: entero
f: fichero
e: lógico
fvar
AbrirFich(nomfich,”escritura”,f,e)
si e=FALSO
para i:=0 hasta numero_personas-1
EscribirFich(f,v[i])
fpara
fsi
CerrarFich(f)
facción

Ejemplo: recorrido de un vector de tuplas para encontrar la edad media de nuestros


amigos almacenados en una tabla.
función EdadMedia (ent lista_amigos:tabla[100] de persona,
ent numero_amigos: entero): real
var
I: entero
edad_med: real
fvar
edad_med:=0.0
para i:=0 hasta numero_amigos-1
edad_med:=edad_med+lista_amigos[i].edad
fpara
retorna (edad_med/(real)numero_amigos)
ffunción

Funciones y acciones que devuelven tuplas

Se pueden desarrollar componentes que devuelvan tuplas individualmente. Veamos un


ejemplo para encontrar el punto medio de un segmento definido por dos puntos P y Q.
Antes de nada deberemos definir un nuevo tipo punto:

Tipo
punto=tupla
x,y: real
ftupla
Ftipo

función PuntoMedio (ent p: punto, ent q: punto): punto


var
pm: punto
fvar
pm.x:= (p.x+q.x)/2.0
pm.y:= (p.y+q.y)/2.0
retorna pm;
ffunción
De esta forma hemos conseguido que una función pueda devolver más de un valor (en
este caso dos, ya que devolvemos una variable de tipo punto que contiene dos campos de
tipo real5). Como acción tendría la siguiente implementación:

acción PuntoMedio (ent p: punto, ent q: punto, sal pm: punto)


pm.x:= (p.x+q.x)/2.0
pm.y:= (p.y+q.y)/2.0
facción

Ejemplo: Buscar a qué amigo pertenece un teléfono que tenemos apuntado sin su
nombre correspondiente.

función BuscarAmigo (ent lista_amigos:tabla[100] de persona, ent numero_amigos: entero,


ent telefono_sin_nombre: cadena): persona
var
i: entero;
persona_nula: persona;
fvar
persona_nula:={“”,-1,””}
i:=0
mientras lista_amigos[i].telefono < > telefono_sin_nombre y i < numero_amigos
i: = i+1 // se hace un recorrido hasta encontrarlo o terminar
fmientras
si i < > numero_amigos
retorna lista_amigos[i] // una persona
sino
retorna persona_nula // para su control desde el exterior de esta función
fsi
ffunción

Ejercicio completo

Supongamos que tenemos un fichero de texto en el que se encuentran almacenadas las


informaciones relativas a una lista de personas, de tal forma que en cada fila del fichero
hay un registro completo. Queremos almacenar todos los registros en un vector, buscar
las personas que tengan una cierta edad (que se pedirá por teclado), y escribir esos
registros en otro fichero.

Definiendo
// definición de constantes
N=100

Utilizando
// definición de tipos
Tipo
Persona=tupla
Nombre: cadena
Edad: entero
Telefono: cadena
ftupla
Ftipo

5
Hasta ahora sólo habiamos estudiado funciones que devuelven un valor.
// prototipos de acciones y/o funciones

función LeerFicheroTuplas (ent nomfich: cadena, sal v:tabla[N] de persona): entero


función BuscaEdad (ent v:tabla[N] de persona, ent num:entero, ent edad:entero,
sal v_misma_edad:tabla[N] de persona): entero
acción EscribirFicheroTuplas (ent nomfich: cadena, ent v:tabla[N] de persona,
ent numero_personas: entero)

Acción Principal
var
nomfich1,nomfich2: cadena
lista, lista_misma_edad:tabla[N] de persona
edad,num_personas, num_edad: entero
fvar
leer(nomfich1)
num_personas:=LeerFicheroTuplas(nomfich1,lista)
si num_personas < > -1
leer(edad)
num_edad:=BuscaEdad(lista,num_personas,edad,lista_misma_edad)
leer(nomfich2)
EscribirFicheroTuplas(nomfich2,lista_misma_edad,num_edad)
sino
escribir(‘Error en la apertura del fichero de datos’)
fsi
escribir(‘Fin del programa’)
facción

función LeerFicheroTuplas (ent nomfich: cadena, sal v:tabla[100] de persona): entero


var
p: persona
i,num_personas: entero
f: fichero
e: lógico
fvar
AbrirFich(nomfich,”lectura”,f,e)
si (no e)
i:=0
mientras (no FinFich(f)) y i<100
LeerFich(f,p)
v[i]:=p
i:=i+1
fmientras
numero_personas:=i
sino
numero_personas:=-1 // para controlar desde el exterior el error
fsi
CerrarFich(f)
facción
acción EscribirFicheroTuplas (ent nomfich: cadena, ent v:tabla[100] de persona,
ent numero_personas: entero)
var
i: entero
f: fichero
e: lógico
fvar
AbrirFich(nomfich,”escritura”,f,e)
si e=FALSO
para i:=0 hasta numero_personas-1
EscribirFich(f,v[i])
fpara
fsi
CerrarFich(f)
facción

función BuscaEdad (ent v:tabla[N] de persona, ent num:entero, ent edad:entero,


sal v_misma_edad:tabla[N] de persona): entero
var
i,k: entero
fvar
para i:=0 hasta num-1
k:=0
si v[i].edad = edad
v_misma_edad[k]:=v[i]
k:=k+1
fsi
fpara
retorna k
ffunción

Ejercicios
1. Realizar un programa en L. Algorítmico y C que permita leer dos números reales que representan los
límites inferior y superior de un intervalo, un tercero que representa el número de puntos a considerar
(no mayor de 100), y a partir de estos datos de entrada, calcule las ordenadas de todas las abcisas
comprendidas entre el límite inferior y el superior sobre un círculo de radio r (que se deberá
introducir también como entrada por teclado) centrado en el origen.

• Se deberá diseñar un tipo nuevo que se llame ordenada


• Se deberá construir un algoritmo independiente para calcular y devolver las ordenadas de un
círculo y otro para encontrar un vector de ordenadas a partir de los límites del intervalo y el
número de puntos deseado (este segundo algoritmo deberá utilizar el primero)

2. Ejemplo de un programa que calcula las soluciones de una ecuación de 2º grado. (versión con
devolución de una estructura, tupla o registro)

Solución Lenguaje Algorítmico:

Utilizando
Tipo
raizdoble = tupla
sol1: real
sol2: real
ftupla
ftipo
función sol_ec_2grado(ent a, b, c: real): raizdoble
acción principal
var
a2, a1, a0: real
solucion: raizdoble
fvar
leer(a2, a1, a0)
solucion:=sol_ec_2grado(a2, a1, a0)
escribir(solucion)
facción

función sol_ec_2grado(ent a, b, c: real): raizdoble


var
r: raizdoble
fvar
r.sol1= (-b+raiz(b*b- 4.0*a*c)/(2.0*a)
r.sol2= (-b-raiz(b*b- 4.0*a*c)/(2.0*a)
retorna r;
facción

Lenguaje C

#include <stdio.h>
#include <math.h>

typedef struct{
float sol1;
float sol2;
}raizdoble;
raizdoble sol_ec_2grado(float a, float b, float c);

/************************************************************************/
/* Programa que calcula las soluciones de una ec. de 2 grado */
/* Funciones utilizadass: sol_ec_2_grado() */
/* Realizado por: Dpto LSI - Sección Algeciras */
/* Fecha de Creación: 31/03/1998 */
/* Revisión: --/--/-- (Por: ------) */
/************************************************************************/

void main(void)
{
char cad[15];
float a2, a1, a0;
raizdoble solucion;

printf ("\nIntroduzca coeficiente a2:");


gets(cad);
a2=atof(cad);

printf ("\nIntroduzca coeficiente a1:");


gets(cad);
a1=atof(cad);

printf ("\nIntroduzca coeficiente a0:");


gets(cad);
a0=atof(cad);

solucion=sol_ec_2grado(a2, a1, a0);


printf("\nLas soluciones son %f y %f", solucion.sol1, solucion.sol2);
}
/************************************************************************/
/* Función que calcula las raices de una ecuación de segundo grado */
/* Entradas: tres valores reales (coeficientes de la ec.) */
/* Salidas: una estructura de tipo raizdoble */
/* Funciones utilizadas: --- */
/* Realizado por: Dpto LSI - Sección Algeciras */
/* Fecha de Creación: 31/03/1998 */
/* Revisión: --/--/-- (Por: ------) */
/************************************************************************/
raizdoble sol_ec_2grado(float a, float b, float c)
{
raizdoble r;

r.sol1= (-b+sqrt(b*b- 4*a*c))/(2*a);


r.sol2= (-b-sqrt(b*b- 4*a*c))/(2*a);

return r;
}

3. Realizar un programa en L. Algorítmico y C que lea un conjunto de 10 números enteros (como


máximo) DESDE FICHERO (utilizando cadenas de caracteres y conversión a enteros) y calcule la
media y la varianza (utilizando un solo algoritmo). Se deberán realizar dos versiones de este
algoritmo, la primera que proporcione como salida dos valores reales independientes y la segunda
que proporcione una estructura que contenga los valores deseados.

4. Realizar un programa en L. Algorítmico y C que permita leer dos números reales que representan los
límites inferior y superior de un intervalo, un tercero que representa el número de puntos a considerar
(no mayor de 100), y a partir de estos datos de entrada, calcule las ordenadas de todas las abcisas
comprendidas entre el límite inferior y el superior sobre un círculo de radio r (que se deberá
introducir también como entrada por teclado) centrado en el origen, Y ESCRIBA ÉSTAS EN UN
FICHERO DE SALIDA DE DATOS.

• Se deberá diseñar un tipo nuevo que se llame ordenada


• Se deberá construir un algoritmo independiente para calcular y devolver las ordenadas de un
círculo y otro para encontrar un vector de ordenadas a partir de los límites del intervalo y el
número de puntos deseado (este segundo algoritmo deberá utilizar el primero)

5. Ejemplo de un programa que lee un vector de registros (de personas) desde un fichero, se almacenan
en un vector, se ordena por las edades de las personas y luego se escribe en un fichero de salida.
Lenguaje Algorítmico:

Utilizando

Tipo
persona = tupla
nombre: cadena
edad: entero
ftupla
ftipo

acción LeerFichero (ent nomfich: cadena; sal v:tabla [10] de persona;


sal numitems : entero);
acción EscribirFichero (ent nomfich: cadena; ent v:tabla [10] de persona;
ent numitems : entero);
acción OrdenarVector (ent numitems : entero; ent/sal v:tabla [10] de persona);

acción principal
var
nomfichero_entrada: cadena;
nomfichero_salida: cadena;
numero_elementos: entero
lista: tabla[10] de persona;
fvar

leer(nomfichero_entrada);
LeerFichero(nomfichero_entrada,lista,numero_elementos);
si numero_elementos <> -1
OrdenarVector(lista);
leer(nomfichero_salida);
EscribirFichero(nomfichero_salida,lista,numero_elementos);
sino
Escribir(“Lo siento, no se puedo abrir el fichero de datos.”);
fsi
facción

acción LeerFichero (ent nomfich: cadena; sal v:tabla [10] de persona;


sal numitems : entero)
var
p: persona;
i: entero;
f: fichero;
e:lógico;
fvar
AbrirFich(nomfich,”lectura”,f,e);
si e=FALSO
i:=0;
mientras (FinFich(f)=FALSO y i<10)
LeerFich(f,p);
v[i]:= p;
i:=i+1;
fmientras
numitems:=i;
CerrarFich(f);
sino
numitems:=-1;
fsi
facción
acción OrdenarVector(ent numitems:entero , ent/sal v: tabla[10] de persona)
var
i: entero;
paux: persona;
intercambio : lógico;
fvar
intercambio := verdadero;
mientras intercambio=verdadero
intercambio := falso
i := 0;
mientras i < numitems-1
si v[i+1].edad < v[i].edad
paux := v[i];
v[i] := v[i+1];
v[i+1] := paux;
intercambio := verdadero
fsi
i := i+1;
fmientras
fmientras
facción

acción EscribirFichero (ent nomfich: cadena; ent v:tabla [10] de persona;


ent numitems : entero)
var
i: entero;
f:fichero;
e:lógico;
fvar
AbrirFich(nomfich,”escritura”,f,e);
si e=FALSO
para i:=0 hasta numitems-1
EscribirFich(f,v[i]);
fpara
CerrarFich (f);
fsi
facción

Lenguaje C

#include <stdio.h>
#include <string.h>

typedef struct{
char nombre[40+1];
int edad;
}persona;

void LeerFichero (char nomfich[20+1], persona v[10], int *numitems);


void OrdenarVector(int numitems, persona v[10]);
void EscribirFichero (char nomfich[20+1], persona v[10],
int numitems);

void main(void)
{
char nomfichero_entrada[20+1];
char nomfichero_salida[20+1];
int numero_elementos;
persona lista[10];

printf("\nIntroduzca el nombre del fichero de personas/edades");


gets(nomfichero_entrada);
LeerFichero(nomfichero_entrada,lista,&numero_elementos);
if (numero_elementos!=-1)
{
OrdenarVector(numero_elementos, lista);
printf("\nDatos ordenados");
printf("\nIntroduzca el nombre del fichero de salida");
gets(nomfichero_salida);
EscribirFichero(nomfichero_salida,lista,numero_elementos);
}
else
printf(“\nNo se pudo abrir el fichero de datos.”);
}

void LeerFichero (char nomfich[20+1], persona v[10], int *numitems)


{
FILE *S;
persona p;
int i;

S= fopen (nomfich,"rt");
if (S==NULL) exit(1);
i=0;
while (!feof(S))
{
fscanf(S,"%s%d\n",p.nombre, &p.edad);
strcpy(v[i].nombre, p.nombre);
v[i].edad = p.edad;
i = i+1;
}
fclose(S);
*numitems = i;
}

void OrdenarVector(int numitems, persona v[10])


{
int i, intercambio;
persona paux;
intercambio = 1;
while (intercambio == 1)
{
intercambio = 0;
i = 0;
while (i < numitems-1)
{
if (v[i+1].edad < v[i].edad)
{
paux.edad=v[i].edad;
strcpy(paux.nombre, v[i].nombre);
v[i].edad=v[i+1].edad;
strcpy(v[i].nombre, v[i+1].nombre);
v[i+1].edad=paux.edad;
strcpy(v[i+1].nombre, paux.nombre);
intercambio = 1;
}
i = i+1;
}
}
}

void EscribirFichero (char nomfich[20+1], persona v[10],


int numitems)
{
FILE *S;
int i;

S = fopen (nomfich,"wt");
if (S==NULL) exit(1);

for(i=0;i<numitems;i++)
fprintf(S,"%s %d\n",v[i].nombre,v[i].edad);
fclose(S);
}

6. Realizar en lenguaje algorítmico y en C un programa que resuelva el siguiente problema:

• Se dispone de un fichero de tuplas (x,y,z) que determina una figura en el espacio tridimensional. El
tamaño máximo que el fichero podrá alcanzar será 100+M tuplas.

• Se dispone de otro fichero que contiene una matriz 3x3 de transformación de puntos en el espacio.

• Se desea obtener un fichero que contenga los puntos del fichero original transformados (según la
matriz antes mencionada), y ordenados según su distancia al origen de coordenadas.

Nota: El alumno deberá crear los dos ficheros de entrada para las pruebas del programa.

Solución

Para resolver este problema:


• se definirá un nuevo tipo de datos tupla (x,y,z) que llamaremos punto.
• utilizaremos un vector de 100 elementos de tipo punto para almacenar las tuplas del fichero de
entrada.
• utilizaremos una matriz de 3x3 números para almacenar la matriz de transformación.
• utilizaremos otro vector de 100 tuplas que contrendrá las tuplas resultado de la multiplicación de cada
tupla original por la matriz de transformación, y que posteriormente será ordenado.

La descomposición Top-Down del problema en subproblemas queda de la forma:

PRINCIPAL

ESCRIBIR
LEER VECTOR LEER MATRIZ DE OBTENER VECTOR ORDENAR
FICHERO DE
DE PUNTOS TRANSFORMACIÓN TRANSFORMADO VECTOR
SALIDA

LEER VECTOR DE PUNTOS: A partir de un nombre de fichero, carga las tuplas contenidas en un vector
de tuplas, dando a la salida en número de tuplas cargadas.

LEER MATRIZ DE TRANSFORMACIÓN: A partir de un nombre de fichero, carga los nueve números
que contiene en una matriz de 3x3.

OBTENER VECTOR TRANSFORMADO: A partir de un vector de tuplas, el número de tuplas a


procesar y una matriz de transformación, multiplica cada tupla por la matriz, y almacena los resultados en
un vector de tuplas transformadas.

ORDENAR VECTOR: A partir de un vector de tuplas y el número de tuplas a procesar, ordena este
vector con el criterio de la mínima distancia al origen.

ESCRIBIR VECTOR DE SALIDA: A partir de un nombre de fichero de salida, de un vector de tuplas y


el número de tuplas a procesar, las almacena en el fichero de salida.
Lenguaje Algorítmico

Utilizando

tipo
tupla = punto
x,y,z: real;
ftupla
ftipo
función LeerVectorPuntos(ent nom: cadena, sal v: tabla[100] de punto):entero;
función LeerMatriz(ent nom:cadena, sal m: tabla[3][3] de real):lógico;
acción ObtenerTransformado(ent v: tabla [100] de punto, num_tuplas:entero,
m: tabla[3][3] de real,
sal vt: tabla [100] de punto);
acción OrdenarVector(ent numitems:entero, sal v: tabla[100] de punto);
acción EscribirVector(ent nom: cadena, v: tabla [100] de punto,num_tuplas:entero);

acción principal
var
nombre_fichero: cadena;
num_tuplas: entero;
v, vt: tabla [100] de punto;
m: tabla [3][3] de real;
error: lógico;
fvar

leer(nombre_fichero);
num_tuplas:=LeerVectorPuntos(nombre_fichero,v);

si num_tuplas <> -1
leer(nombre_fichero);
error:=LeerMatriz (nombre_fichero,m);
si error=FALSO
ObtenerTransformado(v, num_tuplas, m, vt);
OrdenarVector(num_tuplas, v);
leer(nombre_fichero);
EscribirVector(nombre_fichero,vt, num_tuplas);
// se podría controlar también un posible error al escribir en el fichero
sino
escribir(“Lo siento, no se pudo abrir el fichero de la matriz”);
fsi
sino
escribir(“Lo siento, no se pudo abrir el fichero de datos”);
fsi
facción

función LeerVectorPuntos(ent nom: cadena, sal v: tabla[100] de punto):entero


var
p: punto;
i: entero;
f: fichero;
e: lógico;
fvar
AbrirFich(nom,”lectura”,f,e);
si e=FALSO
i:=0;
mientras FinFich(f)=FALSO y i < 100
LeerFich(f,p);
v[i]:=p;
i:=i+1
fmientras
CerrarFich(f);
sino
i:= -1;
fsi
retorna i;
ffunción

función LeerMatriz(ent nom:cadena, sal m: tabla[3][3] de real):lógico


var
c: real;
i,j: entero;
f: fichero;
e: lógico;
fvar
AbrirFich(nom,”lectura”,f,e);
si e=FALSO
i:=0;
mientras i < 3
j:=0;
mientras j < 3
LeerFich(f,c);
m[i][j]:=c;
j := j+1;
fmientras
i := i+1;
fmientras
CerrarFich(f);
retorna e;
sino
retorna e;
fsi
ffunción

acción ObtenerTransformado(ent v: tabla [100] de punto, num_tuplas:entero,


m: tabla[3][3] de real,
sal vt: tabla [100] de punto)
var
i: entero;
fvar
i:=0;
mientras i < num_tuplas
vt[i].x := v[i].x*m[0][0] + v[i].y*m[1][0] + v[i].z*m[2][0] ;
vt[i].y := v[i].x*m[0][1] + v[i].y*m[1][1] + v[i].z*m[2][1] ;
vt[i].z := v[i].x*m[0][2] + v[i].y*m[1][2] + v[i].z*m[2][2] ;
i:=i+1;
fmientras
facción

acción OrdenarVector(ent numitems:entero, sal v: tabla[100] de punto);


var
i: entero;
paux: punto;
intercambio : lógico;
fvar
intercambio := verdadero;
mientras intercambio=verdadero
intercambio := falso
i := 0;
mientras i < numitems-1
si raiz(v[i+1].x2 + v[i+1].y2 + v[i+1].z2) < raiz(v[i].x2 + v[i].y2 + v[i].z2)
paux := v[i];
v[i] := v[i+1];
v[i+1] := paux;
intercambio := verdadero
fsi
i := i+1;
fmientras
fmientras
facción

acción EscribirVector(ent nom: cadena, v: tabla [100] de punto,num_tuplas:entero);


var
f: fichero;
i: entero;
e:lógico;
fvar
AbrirFich(nom,”escritura”,f,e);
si e=FALSO
i:=0;
mientras i< num_tuplas
EscribirFich(f, v[i]);
i:=i+1;
fmientras
CerrarFich(f);
fsi
// no se realiza nada si existe el error en la escritura del fichero de salida
// por supuesto, esa posibilidad podríamos controlarla (se deja como ejercicio)
facción

7. Realizar en lenguaje algorítmico y en C un programa que resuelva el siguiente problema:

• Se dispone de un fichero, en el que en cada fila se encuentra almacenado un segmento de línea dado
por dos puntos del espacio tridimensional (inicial y final). El tamaño máximo que el fichero podrá
alcanzar será de 100+M segmentos de línea.
• Se desea obtener un fichero que contenga la polilínea formada por los segmentos de línea que unen
los puntos medios de los segmentos originales

Lenguaje Algoritmico:

Definiendo
N=100
Utilizando
Tipo
punto=tupla
x,y,z: real;
ftupla
Ftipo
Tipo
segmento=tupla
Inicio:punto;
Fin:punto;
ftupla
ftipo
funcion LeerFicheroSegmentos (ent nomfich: cadena,
ent/sal poli: tabla[N] de segmento):entero;
accion EncontrarPolilineaMedia (ent pol1: tabla[N] de segmento,
ent/sal pol2: tabla[N] de segmento,
ent num_segmentos: entero);
accion CalcularPuntosMedios (ent pol: tabla[N] de segmento,
ent/sal pm : tabla[N] de punto,
ent num_segmentos: entero);
funcion PuntoMedioSegmento (ent p: punto, ent q: punto):punto;
accion EscribirSegmentosFichero (ent nomfich: cadena, ent pol: tabla[N] de segmento,
ent num_segmentos: entero);

Acción principal
var
num_segmentos: entero;
polilinea1, polilinea2 : tabla [N] de segmento;
pm: tabla[N] de punto;
nomfich_entrada, nomfich_salida: cadena;
fvar
Leer(nomfich_entrada);
num_segmentos:=LeerFicheroSegmentos(nomfich_entrada,polilinea1);
si num_segmentos<>-1
EncontrarPolilineaMedia(polilinea1,polilinea2,num_segmentos);
Leer(nomfich_salida);
EscribirSegmentosFichero(nomfich_salida,polilinea2,num_segmentos);
sino
escribir(“Lo siento, hubo error en la apertura”);
faccion

Funcion LeerFicheroSegmentos( ent nomfich: cadena,


ent/sal poli: tabla[N] de segmento):entero
var
s: segmento;
i: entero;
f: fichero;
e: lógico;
fvar
AbrirFich(nomfich,”lectura”,f,e);
si e=FALSO
i:=0;
mientras (FinFich(f)=FALSO y i<N)
LeerFich(f,s);
poli[i]:=s;
i:=i+1;
fmientras
sino
i:=-1;
fsi
CerrarFich(f);
retorna i;
ffuncion
accion EncontrarPolilineaMedia(ent pol1: tabla[N] de segmento,
ent/sal pol2: tabla[N] de segmento,
ent num_segmentos: entero)
var
pm: tabla[N] de punto;
i : entero;
fvar
CalcularPuntosMedios(pol1,pm,num_segmentos);
para i:=0 hasta num_segmentos-1
si i <> num_segmentos-1
Pol2[i].inicio:=pm[i];
Pol2[i].fin:=pm[i+1];
sino
Pol2[i].inicio:=pm[i];
Pol2[i].fin:=pm[0]; // para cerrar la polilinea
fsi
fpara
faccion

accion CalcularPuntosMedios(ent pol: tabla[N] de segmento,


ent/sal pm : tabla[N] de punto,
ent num_segmentos: entero)
var
i: entero;
pmedio: punto; // en realidad no hace falta
fvar
para i:=0 hasta num_segmentos-1
pmedio:=PuntoMedioSegmento(pol[i].inicio,pol[i].fin);
pm[i]:=pmedio;
fpara
faccion

funcion PuntoMedioSegmento(ent p: punto, ent q: punto):punto


var
pmedio: punto;
fvar
pmedio.x:=(p.x+q.x)/2;
pmedio.y:=(p.y+q.y)/2;
pmedio.z:=(p.z+q.z)/2;
retorna pmedio;
ffuncion

accion EscribirSegmentosFichero(ent nomfich: cadena, ent pol: tabla[N] de segmento,


ent num_segmentos: entero)
var
i: entero;
f: fichero;
e: lógico;
fvar
AbrirFich(nomfich,”escritura”,f,e);
si e=FALSO
para i:=0 hasta num_segmentos-1
EscribirFich(f,pol[i]);
fpara
CerrarFich (f);
fsi // no controlamos si se produce el error (se deja como ejercicio)
faccion
8. Realizar en lenguaje algorítmico y en C un programa que resuelva el siguiente problema:

• Se desea realizar un sistema de clasificación automática de objetos situados en puntos del plano, de
tal forma que como entrada se dispone de un fichero, en el que en cada fila se encuentran
almacenadas las coordenadas planas de un punto y una propiedad de cada punto que puede valer 1 ó
2, y que indica su pertenencia a la clase de puntos C1 o a la clase C2 (ver figura). El tamaño máximo
que el fichero podrá alcanzar será de 100+M puntos.

2
1
0

0 1 2 ...

Fichero de Entrada:

0,0,1
0,1,1
0,2,1
0,3,2
1,0,1
1,1,1
1,2,1
1,3,1
2,0,2
2,1,1
...

• El algoritmo de clasificación será el 3-NearestNeigbourgh (3-NN), o de los tres vecinos más


cercanos. De tal forma que para un punto del plano con coordenadas reales, como por ejemplo el
(1.5,1.7), nos debe determinar si pertenece a la clase 1 o a la 2, estudiando los tres puntos más
cercanos a él, para determinar a que clase pertenecen. El punto (1.5, 1,7) será asignado a la clase de
objetos más repetida en sus tres vecinos más cercanos.

• Escribir el algoritmo para k-NN, siendo k cualquier número entero.

9. Realizar en lenguaje algorítmico y en C un programa que resuelva el siguiente problema:

• En un fichero (1) tenemos la descripción de una estructura metálica plana formada por barras, como
en:

Barra NodoInicio NodoFin TipoPerfil


0 0 1 IPN-100
1 1 2 IPN-200
2 0 2 IPN-100
3 2 3 IPN-100
4 1 3 IPN-100

• En otro fichero (2), tenemos cuanto pesa por metro cada uno de los distintos tipos de perfiles:
TipoPerfil Peso
IPN-100 175
IPN-200 250
UPN-100 150
...

• En un último fichero (3), tenemos las coordenadas de cada nodo de la estructura en el plano:

Nodo X Y
0 10 0
1 5 0
2 5 5
3 0 0

• Los ficheros (1) y (3), son definidos por el usuario de un paquete de cálculo de estructuras, el fichero
(2) es propio del paquete (aunque para este ejercicio debe escribirse)

• Se pide :

A) Que el programa actualice el fichero (1) para que además contenga otro campo, que almacene la
longitud de cada barra de la estructura
B) Calcular el peso total de la estructura definida

10. Realizar en lenguaje algorítmico y en C un programa que resuelva el siguiente problema:

Dados dos ficheros, el primero en el que en cada línea tenemos el dni, el nombre y la edad de una persona
y el segundo en el que tenemos en cada línea el dni e información acerca de la matriculación en las
asignaturas A,B,C,D y E, como se muestra (máximo 100 en cada fichero):

Fichero (1):
DNI NOMBRE EDAD
14236578 pepe 20
12345678 pepi 19
21435678 pepon 21
...

Fichero (2):
DNI A BCDE
14236578 1 0 0 01
12345678 0 1 1 10
21435678 1 1 1 11
...

Se pide:
• Edad media de los matriculados en cada asignatura (por pantalla).
• Listados de DNI y NOMBRE de los que estén matriculados en A, B y C.
Lenguaje Algoritmico:

Definiendo
N=100
Utilizando
Tipo
persona=tupla
dni: cadena
nombre: cadena
edad: entero
ftupla
Ftipo
Tipo
matricula=tupla
dni: cadena
a,b,c,d,e: booleano;
ftupla
ftipo

// Completar con LeerFicheroPersonas


// Completar con LeerFicheroDatos

funcion EncontrarMatriculadosEnABC(ent datos: tabla[N] de matricula,


ent num: entero,
ent/sal v: tabla[N] de entero);

accion ExtraerMatriculadosEnABC(ent lista: tabla[N] de persona,


ent numpersonas: entero,
ent v: tabla[N] de entero,
ent matriculados: entero,
ent/sal lista_matriculados: tabla[N] de persona);

// Completar con EscribirListaFichero

Acción principal
var
num_personas1, num_personas2, matriculados: entero;
lista, lista_matriculados : tabla [N] de persona;
datos: tabla[N] de matricula;
v: tabla[N] de entero;
nomfich_entrada1, nomfich_entrada2, nomfich_salida: cadena;
fvar

// se deja como ejercicio controlar los posibles errores en las aperturas de los ficheros
Leer(nomfich_entrada1);
numpersonas1:=LeerFicheroPersonas(nomfich_entrada1,lista);
Leer(nomfich_entrada2);
numpersonas2:=LeerFicheroDatos(nomfich_entrada2,datos);

// el número de personas de ambos ficheros podría ser diferente


matriculados:=EncontrarMatriculadosEnABC(datos,numpersonas2,v);
ExtraerMatriculadosEnABC(lista,numpersonas1,v,matriculados,lista_matriculados);
Leer(nomfich_salida);
EscribirListaFichero(nomfich_salida, lista_matriculados, matriculados);
faccion
funcion EncontrarMatriculadosEnABC(ent datos: tabla[N] de matricula,
ent num: entero,
ent/sal v: tabla[N] de entero)
var
i,j : entero;
fvar
j:=0;
para i:=0 hasta num
si (datos[i].a=1) y (datos[i].b=1) y (datos[i].c=1)
v[j]:=i; // en el vector v almacenamos los indices de los matriculados
j:=j+1;
fsi
fpara
retorna j;
ffuncion

accion ExtraerMatriculadosEnABC(ent lista: tabla[N] de persona,


ent numpersonas: entero,
ent v: tabla[N] de entero,
ent matriculados: entero,
ent/sal lista_matriculados: tabla[N] de persona)
var
j : entero;
fvar
para j:=0 hasta matriculados-1
lista_matriculados[j]:=lista[v[j]];
fpara
faccion

Bibliografía6

[AHU88] Aho A. V., Hopcroft J. E., Ullman J. D., Estructuras de datos y algoritmos.
Addison-Wesley Iberoamericana ,1988.
[AM97] Antonakos J. L., Mansfield K. C., Programación estructurada en C,
PrenticeHall, 1997.
[BB97] Brassard G., Bratley P., Fundamentos de Algoritmia, Prentice Hall, 1997.
[BC85] Biondi J., Clavel G., Introducción a la programación. Tomo 1: algoritmos y
lenguajes, Masson, 1985.
[CC97] Cerrada J., Collado M., Programación I, Universidad Nacional de Educación a
Distancia, 1997.
[CCM93] Castro, J.; Cucker, F.; Messeguer, X.; Rubio, A.; Solano, Ll.; Valles, B. Curso
de Programación. Editorial Mc.Graw-Hill, 1993.
[CF97] Cerrada C., Feliu V., Estructura y tecnología de computadores I, Universidad
Nacional de Educación a Distancia, 1997.
[ChC87] Chapra, Steven C.; Canale, Raimond P. Métodos Numéricos para Ingenieros.
Editorial Mc.Graw-Hill
[Fai87] Fairley, Richard. Ingeniería de Software. Editorial McGraw-Hill, 1987.
[GGS93] Galve, J; González, J; Sánchez, A; Velázquez, J. Algoritmica. Diseño y
análisis de algoritmos funcionales e imperativos. Editorial Ra-Ma, 1993.
[Joy87] Joyanes, L. Metodología de la Programación. Editorial Mc.Graw-Hill, 1987.
[Joy92] Joyanes Aguilar, Luis. Fundamentos de Programación. Algoritmos y
Estructuras de Datos. 2ª Edición. Editorial McGraw-Hill, 1992.
[Knu86] Knuth, D.E. Algoritmos Fundamentales. Volumen I. Editorial Reverte, 1986.
[KR88] Kernighan, B; Ritchie, D. El Lenguaje de Programación C. 5ª R. Editorial
Prentice-Hall, 1988.
[Lip87] Lipschutz, S. Estructuras de Datos. Editorial Mc.Graw-Hill, 1987.

6
Como en los anteriores capítulos, todas las referencias bibliografías se encuentran disponibles en la
biblioteca de la Escuela Politécnica Superior de Algeciras
[LS85] Lewis, T; Smith, M. Estructuras de Datos. Programación y Aplicaciones.
Editorial Paraninfo, 1985.
[PTV92] Press, W; Teukolsky, S; Vetterling, W; Flannery, B. Numerical Recipes in C.
The Art of Scientific Computing. 2ª Edición. Cambridge University Press,
1992.
[Sch88] Schildt, H. C - Manual de Referencia. Editorial Mc.Graw-Hill, 1988.
[Sch91] Schildt, H. Ansi C a su alcance. Editorial Mc.Graw-Hill, 1991.
[Sch95] Schildt, H. Turbo C/C++ v.3.1- Manual de Referencia. Editorial Mc.Graw-
Hill, 1995.
[SGTLL97] Sanchez, P.J; Galindo, J.; Turias, I.; Lloret, I. Ejercicios Resueltos de
Programación en C. Servicio de Publicaciones de la Universidad de Cádiz,
1997.
[SK86] Sobelman, G.; Krekelberg, D. Técnicas avanzadas en C. Desarrollo de
aplicaciones. Editorial Anaya-Multimedia, 1986.
[SP91] Scoll P. C., Peyrin J.P., Esquemas algorítmicos fundamentales: secuencias e
iteración, Masson, 1991.
[TLL96] Turias, Ignacio; Lloret, Isidro. Guía Práctica de Programación en C. Dpto.
Lenguajes y Sistemas Informáticos. UCA, 1996.
[WPM89] Waite, M; Prata, S.; Martin, D. Programación en C. Introducción y conceptos
avanzados. 2ª Edición. Editorial Anaya-Multimedia, 1989.

You might also like