Resumen de programación C

Anuncio
Estructura de Computadores
2ITIEI
Estructura de Computadores
Cesáreo Fernández Martínez
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 1
Estructura de Computadores
2ITIEI
Contenidos
•
La asignatura tiene básicamente dos bloques
– Estudio de la estructura de los computadores
• CPU, memoria, etc.
– Estudio de la técnicas de programación avanzadas en C
• Estructuras, Listas, Árboles, etc
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 2
1
Estructura de Computadores
2ITIEI
Programa I
•
Estudio de la técnicas de programación avanzadas en C
– Punteros
• Punteros y vectores
• Punteros y funciones
– Estructuras de datos dinámicas
• Introducción
• Elementos de una estructura dinámica de datos: Nodo
• Tipos de estructuras dinámicas de datos
– Listas enlazadas
– Árboles binarios
– Algoritmos de ordenación.
•
•
•
•
•
Introducción
Ordenación de vectores numéricos
Método de la burbuja (o intercambio directo)
Método rápido (quicksort).
Ordenación de vectores de cadenas
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 3
Estructura de Computadores
2ITIEI
Programa II
•
Arquitectura de computadores
– La CPU: ALU, Registros, CU
– La memoria
– El Conjunto de Instrucciones (Instruction Set Arquitecture: ISA)
•
Organización de una máquina RISC
– Reduced Instruction Set Computer, ó
– Ridiculously Simple Computer . Veremos:
• El conjunto de instrucciones que puede ejecutar (Arquitectura)
• Organización
– Los módulos que lo forman: ALU, Registros, etc.
– Cómo están conectados (organización)
– Cómo ejecuta instrucciones
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 4
2
Estructura de Computadores
2ITIEI
Resumen de Normas
•
(Consultar Web de la universidad)
•
La asignatura consta de:
– Teoría
– Laboratorio
•
Teoría: Dos exámenes
– Intermedio: Técnicas avanzadas de programación
– Final: Programación más máquina RISC
– Pruebitas intermedias: Según necesidades de guión
•
Laboratorio
– Sesiones de 2 horas
– Importancia del trabajo previo
• Test de 10 min al comienzo de la práctica
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 5
Estructura de Computadores
2ITIEI
Evaluación
•
Nota final
– Nota = nota_teoría * 0.6 + nota_lab * 0.4;
– Si ambas notas son mayores de 5.0
– Caso contrario se selecciona la menor de las notas
•
En forma de pseudocódigo C
if (nota_teoría>5 && nota_lab>5) {
nota = nota_teoría*0.6 + nota_lab*0.4;
} else {
if (nota_teoría < nota_lab) {
nota = nota_teoría;
} else {
nota = nota_lab;
}
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 6
3
Estructura de Computadores
2ITIEI
Nota de teoría
•
Pruebas
– Prueba final
– Prueba intercuatrimestral
– La pruebas intercuatrimestral sólo sirve para subir nota; en ese
caso contará un 25% de la nota de teoría.
•
En forma de pseudocódigo C
nota_c = nota_examen_final*0.75 + nota_intercuatrimestral*0.25;
if (nota_c > nota_examen_final) {
nota_teoría = nota_c;
} else {
nota_teoria = nota_examen_final;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 7
Estructura de Computadores
2ITIEI
Nota de laboratorio
•
Prácticas en
•
Calificación basada en
– http://www.iit.upco.es/~cesar
– Tests previos a la práctica
• Basados en el trabajo previo de la práctica
– Dos exámenes
• Intercuatrimestral y final
– Informes de la práctica.
• Se entregan la semana siguiente a la práctica
• No informes => no examen
•
En forma de pseudocódigo C
nota_lab = exam_1*0.25+exam_2*0.50+ test*0.25;
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 8
4
Estructura de Computadores
2ITIEI
Bibliografía
•
[Muñoz y Palacios 2006] José Daniel Muñoz Frías y Rafael
Palacios Hielscher. Fundamentos de programación
utilizando el lenguaje C.
– R.B. Servicios Editoriales. S.L.
•
Apuntes de arquitectura de ordenadores. Página WEB
– http://www.iit.upco.es/~cesar
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 9
Estructura de Computadores
2ITIEI
Bibliografía adicional
•
[Antonakos and Mansfield, 1997] Antonakos, J. L. and
Mansfield, K. C. (1997). Programación estructurada en C.
•
[Wirth, 1986]
Wirth, N. (1986). Algoritmos +
estructuras de datos = programas.
•
[Ibáñez, 1995]
Ibáñez, J. B. (1995). Introducción a la
arquitectura de computadores.
– Prentice Hall Iberia, Madrid.
– Ediciones del Castillo S. A.
– Universidad de Valladolid, Valladolid.
•
[Martínez et al., 2001]
Martínez, R. J., Boluda, J. A.,
and Pérez, J. J. (2001). Estructura de computadores y
periféricos.
– Editorial Ra-Ma, Madrid.
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 10
5
Estructura de Computadores
2ITIEI
Revisión de C
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 11
Estructura de Computadores
2ITIEI
Punteros
•
Almacenan la dirección de una variable
– La dirección de memoria en la que está almacenada la variable
•
Parte importante del lenguaje C. Se usan para
– Definir vectores de tamaño variable
– En funciones que devuelven varias cosas
– En estructuras de datos complejas
• Listas
• Árboles
• etc
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 12
6
Estructura de Computadores
2ITIEI
Gráficamente
•
El puntero es una VARIABLE (en memoria) que almacena la
DIRECCIÓN de otra VARIABLE (apunta a ...)
Puntero
Dirección Contenido
Char *
C2B8
A7
int *
C37A
B9 A4
long *
2703
E2 A1 10 30
•
Las direcciones de memoria se dan en Hexacimal
– C2B8 , C37A, etc
– Todas las direcciones (y por tanto los punteros) del MISMO
TAMAÑO
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 13
Estructura de Computadores
2ITIEI
Otra respresentación gráfica
•
Dirección/contenido(valor)
Dirección
Valor
Variable
?
C2B8
pc
C2B8
A7
c
?
C37A
pl
C37A
C37B
C37C
C37D
E2
A1
10
30
l
•
Dirección
El puntero guarda la dirección
Valor
Variable
– Del primer elemento (byte)
• del objeto apuntado
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 14
7
Estructura de Computadores
2ITIEI
Punteros en C
•
Se declaran mediante el operador *
int i;
int *pi;
•
// declara una variable entera
// declara un puntero a variable entera
Se inicializa con &
i = 78;
pi = &i ;
•
// la variable i almacena un 78
// pi apunta a i
Se accede al valor (de la variable apuntada) con *
printf(“/d\n”, *pi);
// imprime el valor de i
Cesáreo Fernández Martínez
(78)
UPCO- ICAI Departamento de Electrónica y Automática 15
Estructura de Computadores
2ITIEI
Operaciones con punteros
•
Operando con la variable apuntada
int i;
int *pi;
i = 78;
pi = &i;
•
*pi = *pi + 8;
*pi += 8;
// suma 8 a i
// suma 8 a i
pi += 8;
// suma 8 al puntero
// el puntero apunta 8 int’s más allá
PELIGRO !!!
– Sólo tiene sentido incrementar el puntero cuando se trabaja con
vectores
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 16
8
Estructura de Computadores
2ITIEI
Punteros y vectores
•
Vectores
– Todos los elementos de igual tamaño
– Almacenados en posiciones consecutivas de memoria
• Basta conocer la dirección del primer elemento y el tamaño del vector
int main(void) {
double a[N];
int i;
double *pd;
for (i= 0; i<N; i++) {
a[i] = 7.8 * i;
}
pd = &a[0];
for (i= 0; i<N; ++) {
printf(“%f\n”, *pd);
pd++;
}
return 0;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 17
Estructura de Computadores
2ITIEI
Funciones
•
Las funciones son un elemento básico para la
estructuración de los programas
– Hacer funciones cortas y que hagan una sola cosa ! (fáciles de
desarrollar y de depurar, reutilizables)
•
•
Las funciones deben ser declaradas y definidas
Declaración (prototipo)
int power(int base, int n);
•
Definición (código)
int power(int base, int n) {
int i, p;
p = 1;
for (i=1; i<=n; i++)
p = p * base;
return p;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 18
9
Estructura de Computadores
2ITIEI
Prototipo
•
A incluir en la cabecera de programa cuando las funciones
se definen en el fichero de entrada DESPUES de main.
int power(int base, int n);
int main (void) {
printf(”%d %d \n”, 10, power(2,10));
}
int power(int base, int n) {
int i, p;
p = 1;
for (i=1; i<=n; i++)
p = p * base;
return p;
}
•
El prototipo indica
– Número y tipo de argumentos (de la función)
– Tipo de resultado
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 19
Estructura de Computadores
2ITIEI
Punteros y funciones
•
Los parámetros se puede pasar por
– Valor: Tipos básicos (atómicos: char, int, long, etc.).
– Referencia: Tipos compuestos (vectores, cadenas).
•
Paso por referencia para tipos atómicos. Ejemplo:
Por Valor
void cambio(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
int main (void) {
int x=5, y=6;
cambio(x,y);
}
Cesáreo Fernández Martínez
Por Referencia
void cambio(int *pa, int *pb) {
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
int main (void) {
int x=5, y=6;
cambio(&x,&y);
}
UPCO- ICAI Departamento de Electrónica y Automática 20
10
Estructura de Computadores
2ITIEI
Devolver varios valores
•
Devolver mediante return
•
Mediante la lista de argumentos: paso por referencia
– Un solo valor.
– Tantos como se desee
void SumaProd(double *, double *, double, double) ;
int main (void) {
double sum;
couble prod;
SumaProd(&sum, &prod, 2.0, 3.0);
printf(”%f %f \n”, sum, prod);
}
void SumaProd(double *psuma, double *pprod, double dato1, double dato2) {
*psuma = dato1 + dato2
*pprod = dato1 * dato2
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 21
Estructura de Computadores
2ITIEI
Vectores con [ ]
•
El nombre del vector es un puntero (constante)
– a[3] = 2.7;
•
Es idéntico a
– *(a+3) = 2.7;
•
Además: cualquier puntero se puede usar como vector!
– *punt = 4;
•
Es idéntico a
– punt[0] = 4;
•
Y
– *(punt+3) = 4; es idéntico a punt[3] = 4;
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 22
11
Estructura de Computadores
2ITIEI
Funciones, vectores y punteros
•
Copia de cadenas con índices
void strcpy(char cadd[],char cads[] ) {
int i=0;
while (cads[i] != ’\0’) {
cadd[i] = cads[i];
i++;
}
cadd[i] = cads[i];
// 0 del final
}
int main (void) {
char s1[] = ”Hola”;
char s2[25];
// espacio suficiente
strcpy(s2,s1);
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 23
Estructura de Computadores
2ITIEI
Funciones, vectores y punteros II
•
Con punteros
void strcpy(char *pd,char *ps) {
while (*ps != ’\0’) {
*pd = *ps;
pd++;
ps++;
}
*pd = *ps;
// 0 del final
}
int main (void) {
char s1[] = ”Hola”;
char s2[25];
strcpy(s2,s1);
}
Cesáreo Fernández Martínez
// cadena
// cadena
UPCO- ICAI Departamento de Electrónica y Automática 24
12
Estructura de Computadores
2ITIEI
Funciones, vectores y punteros III
•
Ambas declaraciones de punteros son equivalentes
– char s[ ]
y
char *ps
•
Lo que se pasa a la función cuando hacemos
– strcpy(s2,s1);
•
•
Son las DIRECCIONES de s2 y s1
strcpy carga ambas direcciones en sendos punteros
– Maneja las cadenas de main usando los punteros !
•
RESERVAR siempre suficiente ESPACIO en la CADENA
DESTINO !!!!!
– El puntero no es más que “un mecanismo alternativo” de acceso a
la cadena.
– pd[25] está fuera de la cadena (escribe en una variable
DISTINTA de la cadena apuntada por pd !)
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 25
Estructura de Computadores
2ITIEI
Memoria dinámica
•
Idónea cuando no se conocen las dimensiones “a priori”
– Sólo se conoce al ejecutar el programa
– Se le pide al usuario a principio de la ejecución
•
Llamadas a sistema operativo para
– Reservar memoria
• El operativo devuelve un puntero
• Liberar la memoria utilizada
•
• Cuando deja de necesitarse
Funciones calloc y malloc (en stdlib.h)
void *calloc(size_t numero_elementos, size_t tamaño_elemento) ;
void *malloc(size_t tamaño_bloque) ;
•
Devuelven
– Puntero a la base del espacio de memoria reservado
– Puntero NULL sin no queda memoria suficiente (Comprobar)
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 26
13
Estructura de Computadores
2ITIEI
Memoria dinámica II
•
La función calloc
– Reserva un bloque de memoria para
• Un número de elementos del tamaño indicado
•
La función malloc
– Reserva un bloque de memoria de
• Tamaño indicado en BYTES
•
Ej: para crear un vector de 100 enteros
int *pent;
pent = (int *) calloc(100, sizeof(int));
if (pent == NULL) {
printf(“Error: No hay suficiente memoria\n”);
} else {
pent[0] = 27;
..
free(pent);
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 27
Estructura de Computadores
2ITIEI
Función free
•
Se utiliza para liberar la memoria reservada con
malloc/calloc
void free(void *puntero_al_bloque) ;
•
El puntero debe apuntar al principio del bloque !
– El siguiente código da un error !
int *pent;
pent = (int *) calloc(100, sizeof(int));
if (pent == NULL) {
printf(“Error: No hay suficiente memoria\n”);
} else {
..
pent++;
..
free(pent);
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 28
14
Estructura de Computadores
2ITIEI
Algoritmo-pseudocódigo
•
Queremos resolver el siguiente problema
– Pedir al usuario un vector de dimensión variable, y
– Generar otro vector con los números pares del vector anterior
•
Detallamos el proceso a seguir en forma de pseudocódigo
-
•
Pedir dimensión del vector a usuario
Reservar memoria para el vector
Pedir al usuario los elementos de vector
Contar el número de elementos pares del vector
Reservar memoria para el vector de números pares
Copiar los números pares desde el primer vector al segundo
Imprimir el segundo vector
Liberar memoria
Ejemplo 1
– Vector de números pares
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 29
Estructura de Computadores
2ITIEI
Recomendaciones/advertencias
•
Cuando se usa memoria estática:
– Definir los vectores en el programa principal (dimensión fija)
– Pasar las direcciones de comienzo a las funciones
– Las funciones no pueden devolver vectores !!!
•
Cuando se usa memoria dinámica:
– El programa principal declara punteros
– La memoria se reserva mediante malloc/calloc
– Estas funciones devuelven punteros, que se almacenan en los
punteros previamente declarados
– Accedemos a las posiciones de memoria mediante * y/o [ ]
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 30
15
Estructura de Computadores
2ITIEI
Estructuras de datos
•
Ideales para agrupar datos de distinto tipo
– Referentes a un mismo objeto
•
Pe.: Para describir el historial médico de una persona
Dato
Tipo de dato
Tipo en C
Nombre
Edad
Peso
Nº Seguridad Social
Historia
Cadena de caracteres
Número entero
Número en punto flotante
Número entero
Cadena de caracteres
char[100]
unsigned short
float
unsigned long
char[1000]
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 31
Estructura de Computadores
2ITIEI
Declaración y definición de estructuras
•
Declaración
struct nombre_de_estructura {
tipo_1 nombre_miembro_1;
tipo_2 nombre_miembro_2;
. . . .
tipo_n nombre_miembro_n;
}
•
•
La declaración no crea objetos, introduce un nuevo nombre
Para crear un objeto (definición):
struct nombre_de_estructura
•
var;
Crea la variable var del tipo nombre_de_estructura
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 32
16
Estructura de Computadores
2ITIEI
Ejemplo
•
Historial médico de un paciente
struct paciente {
char
unsigned short
float
unsigned long
char
};
•
nombre[100];
edad;
peso;
n_seg_social;
historia[1000];
Para crear objetos de este tipo:
struct paciente pepito;
struct paciente juanito;
•
Los objetos de tipo estructura se crean de la misma forma
que los objetos de tipo básico.
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 33
Estructura de Computadores
2ITIEI
Sentencia typedef
•
Permite asociar un nombre cualquiera a un tipo
– Basico
– Derivado
typedef unsigned short WORD;
typedef unsigned char U8;
•
Para definir objetos de estos nuevos tipos
WORD edad;
U8
caracter;
•
// edad es un entero corto: 16 bits
// caracter almacena un byte sin signo: 8 bits
Ventajas de legibilidad y facilidad a la hora de portar el
programa a otros ordenadores
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 34
17
Estructura de Computadores
2ITIEI
Estructuras y typedef
•
Declaración con typedef
typedef struct paciente {
char
nombre[100];
unsigned short edad;
float
peso;
unsigned long n_seg_social;
char
historia[1000];
}PACIENTE;
•
Para crear objetos de este tipo:
PACIENTE pepito;
PACIENTE juanito;
•
Lo que hace el programa más legible
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 35
Estructura de Computadores
2ITIEI
Estructuras dentro de estructuras
•
Una nueva estructura
typedef struct dia {
int
dia;
int
mes;
int
año;
} FECHA;
•
permite introducir la fecha de nacimiento del paciente en la
estructura PACIENTE
typedef struct paciente {
char
nombre[100];
FECHA
fecha_de_nacimiento;
float
peso;
unsigned long n_seg_social;
char
historia[1000];
} PACIENTE;
•
de forma fácil
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 36
18
Estructura de Computadores
2ITIEI
Acceso a los campos de una estructura
•
Operador: ‘.’
– Se usa para acceder a los campos de una estructura. Ej:
pepito.edad = 27;
pepito.peso = 67.5
strcpy(pepito.nombre, “José Pérez López”);
•
Para imprimir los datos
printf(“Paciente: %s\n”, pepito.nombre);
printf(“Edad: %d\n”, pepito.edad);
printf(“Peso: %f\n”, pepito.peso);
printf(“Num. Seg. Social: %ld\n”, pepito.n_seg_social);
printf(“Historia: %s\n”, pepito.historia);
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 37
Estructura de Computadores
2ITIEI
Estructuras y funciones
•
Operador: ‘=‘, se puede usar para copiar estructuras de
mismo tipo
PACIENTE pepito;
PACIENTE copia_de_pepito;
copia_de_pepito = pepito;
– Al contrario de lo que sucede con los vectores
• Que se debe realizar componente a componente
•
Las estructuras se pueden pasar directamente a las
funciones
– Ya que en el paso se copia la estructura en el argumento de la
funcíon (paso por valor)
•
Una función puede devolver una estructura vía return !
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 38
19
Estructura de Computadores
2ITIEI
Ejemplo II. Números Complejos
•
Declaración
typedef struct complejo{
double real;
double imag;
} COMPLEJO;
•
Para crear variables:
int main(void)
{
COMPLEJO comp1, comp2, result;
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 39
Estructura de Computadores
2ITIEI
Ejemplo
•
La siguiente función devuelve una estructura tipo complejo
COMPLEJO InicComplejo(double real, double imag) {
COMPLEJO resultado;
resultado.real = real;
resultado.imag = imag;
return resultado;
}
•
Para llamar a la función (inicializa el número complejo):
. . .
COMPLEJO comp1;
. . .
Comp1 = InicComplejo(2.0, 3.7);
. . .
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 40
20
Estructura de Computadores
2ITIEI
Paso de parámetros
•
El paso de parámetros es similar
COMPLEJO SumaComp(COMPLEJO c1, COMPLEJO c2) {
COMPLEJO res;
res.real = c1.real + c2.real;
res.imag = c1.imag + c2.imag;
return res;
}
•
Para llamar a la función:
. . .
suma = SumaComp(cx, cy);
. . .
– Donde cx y cy son dos complejos previamente definidos e
inicializados. ¿De qué tipo debe ser suma?
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 41
Estructura de Computadores
2ITIEI
Paso por referencia
•
Pasa por el uso de un puntero a estructura. Ej:
COMPLEJO *pcomplejo;
•
La función con paso por referencia:
COMPLEJO SumaComp2(COMPLEJO *pc1, COMPLEJO *pc2) {
COMPLEJO res;
res.real = (*pc1).real + (*pc2).real;
res.imag = (*pc1).imag + (*pc2).imag;
return res;
}
•
La llamada a la función:
suma = SumaComp(&cx, &cy);
•
Ejemplo 3
– Datos de un paciente
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 42
21
Estructura de Computadores
2ITIEI
Paso por referencia II
•
Operador ->
(flecha)
COMPLEJO SumaComp2(COMPLEJO *pc1, COMPLEJO *pc2) {
COMPLEJO res;
res.real = pc1->real + pc2->real;
res.imag = pc1->imag + pc2->imag;
return res;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 43
Estructura de Computadores
2ITIEI
Vectores de estructuras
•
Problema: Producto escalar de dos vectores de complejos
– Enfoque 1: 4 vectores (real+imag, 1er vector, real+imag, 2º vector)
– Enfoque 2: Dos vectores de tipo COMPLEJO
COMPLEJO vector_complejo[10];
•
Para acceder a los miembros:
vector_complejo[0].real
vector_complejo[0].imag
. . .
vector_complejo[9].real
vector_complejo[9].imag
•
•
= 4.3;
= 23.27;
= 2.1;
= 3.7;
Nótese que los índices van de 0 a N-1
Ejemplo 4
– Producto escalar de dos vectores de números complejos
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 44
22
Estructura de Computadores
2ITIEI
Vectores dinámicos de estructuras
•
Se reserva memoria para un vector de estructuras:
PACIENTE *pp;
pp = (PACIENTE *)calloc(np, sizeof(PACIENTE));
•
De la misma forma que para cualquier otro tipo. Pe. int
int *pi;
pi = (int *)calloc(n, sizeof(int));
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 45
Estructura de Computadores
2ITIEI
Recomendaciones/advertencias
•
•
•
Declarar las estructuras usando typedef
Si se tiene un puntero a estructura usar -> en lugar de (* )
Con vectores de estructuras tener en cuenta que
– pp[3].nombre
• Es el nombre del cuarto paciente
– pac.nombre[3]
• Es la cuarta letra del nombre de un paciente
•
Si las estructuras son muy grandes, usar paso por referencia
en las llamadas a funciones
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 46
23
Estructura de Computadores
2ITIEI
Archivos
•
Se utilizan para almacenar datos de forma permanente
•
Soportes de gran capacidad
•
Indicados en nuestro caso (programadores) para
– Disco duro, CD, DVD, etc.
– Aunque de limitado tiempo de acceso
– Alimentar programas que requieren gran cantidad de datos
– Recoger resultados de programas que vuelcan muchos datos
– Almacenar los resultados de forma permanente
•
Tipos de archivo
– Texto ( .txt) : Legibles por humanos (Notepad, Word, etc)
– Binarios (.dat): no legibles. Ocupan menos espacio en disco
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 47
Estructura de Computadores
2ITIEI
Abrir un archivo
•
Para abrir un archivo se usa la función fopen
FILE *fopen(char *Nombre_competo_del_archivo, char *modo);
•
El nombre completo es
– Una cadena de caracteres con el nombre y el camino completo
• Caso de no estar el archivo en el directorio de trabajo
•
El modo es otra cadena de caracteres
– Indica el tipo de operación a realizar en el fichero
• r (lectura), r+ (lectura/escritura),
• w (escritura), w+ (escritura/lectura),
• a (append), b (binary)
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 48
24
Estructura de Computadores
2ITIEI
Abrir un archivo II
•
La función fopen
– Devuelve un puntero a una estructura tipo FILE (estructura de
control)
– Devuelve NULL si el fichero no existe (Comprobar)
• O si no tenemos permiso de acceso
#include <stdio.h>
int main(void) {
FILE *pfich;
. . .
pfich = fopen(“pepe.txt”, “r+”);
if (pfich == NULL) {
printf(“Error: No se puede abrir el archivo.\n”);
} else {
/* Archivo abierto correctamente. Se puede trabaja con él */
. . .
fclose(pfich);
}
return 0;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 49
Estructura de Computadores
2ITIEI
Abrir un archivo III
•
Especificación de camimos
– En Windows
pfich = fopen(“c:\\dani\\datos.m”, “a”);
– En Linux
pfich = fopen(“/home/dani/datos.m”, “a”);
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 50
25
Estructura de Computadores
2ITIEI
Cerrar un archivo
•
Una vez utilizado
– Para no perder datos
– Porque el número de ficheros abiertos (simultáneamente) está limitado
•
La función fclose
int fclose(FILE *puntero_al_archivo);
•
Devuelve
– 0 : si se ha cerrado con éxito
– -1: si ha ocurrido algún error
if (fclose(pfich) != 0) {
printf(“Error al cerrar el archivo.\n”
“es posible que se haya producido una pérdida de datos”);
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 51
Estructura de Computadores
2ITIEI
Lectura/escritura de/a archivo
•
Se usa fprintf/fscanf (similares a prinf/scanf)
int fprintf(FILE *puntero_al_archivo, const char *cadena_de_formato);
int fscanf(FILE *puntero_al_archivo, const char *cadena_de_formato);
•
donde
– Puntero_al_archivo: puntero devuelto por fopen
– Cadena_de_formato: idéntica a las cadenas formato de printf
– … : Número variable de parámetros
•
Ejemplo
fprintf(pfich,”El valor de %d en hex ex %x\n”, 15, 15);
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 52
26
Estructura de Computadores
2ITIEI
Lectura: fscanf
•
Devuelve el número de variable leídas correctamente. Ej
fscanf(pfich,”%d”, &num);
– Devuelve 1 si consigue leer la variable
– Devuelve 0 si hay error de formato
– Devuelve EOF si final de fichero
•
La siguiente llamada
fscanf(pfich,”%d %d”, &n1, &n2);
– Devuelve 2 si consigue leer ambas variables
– Devuelve 1 si sólo consigue leer una
– Devuelve 0 si no consigue leer ninguna
• Y EOF caso de final de fichero con ninguna variable leída
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 53
Estructura de Computadores
2ITIEI
Otras funciones de entrada/salida a archivo
•
Ejemplo de uso de fscanf
– Lee números en coma flotante
•
Otras funciones de E/S
int fgetc(FILE *puntero_a_archivo);
int ungetc(char c,FILE *puntero_a_archivo);
int fputc(int carácter, FILE *puntero_a_archivo);
char *fgets(char *cadena, int tam_cadena, FILE *puntero_a_archivo);
int fputs(const char *cadena, FILE *puntero_a_archivo);
•
Ejemplos 5 y 6
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 54
27
Estructura de Computadores
2ITIEI
Archivos binarios
•
Los archivos de texto tienen caracteres ASCII legibles
– Se pueden modificar con cualquier editor de textos (ej: notepad)
– Printf(“%d”, var); convierte la variable var a 5 caracteres
ASCII
•
Los archivos binarios no son legibles
– Contienen una imagen exacta de la memoria, esto es, lo números
quedan codificados en binario. Ej 10 (d) -> 0000 1010 (0A H)
– Sizeof(var), da el número de bytes de la variable
• (char: 1byte, short int: 2 bytes, int: 2/4 bytes, long: 4/8 bytes)
– No son legibles por humanos
– No son portables (de MSDOS a Windows/Linux)
•
Almacenamos la estructuras en archivos binarios
– Por cuestiones de tamaño
– Por cuestiones de velocidad (lectura/escritura)
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 55
Estructura de Computadores
2ITIEI
Almacenando estructuras en archivos de texto
•
Se almacenan los datos
– Campo a campo
– Usando fprintf
•
Ejemplo 7
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 56
28
Estructura de Computadores
2ITIEI
Almacenando estructuras en archivos binarios
•
Se almacena toda la estructura de una “tacada”
– Usando fwrite
– En un archivo abierto en modo binario
size_t fwrite(void *pestructura, size_t tamaño, size_t numero,
FILE *archivo);
– Donde
• size_t es lo mismo que unsigned long int
• void * es un puntero genérico
– Y
•
•
•
•
pestructura: puntero a la base de la estructura
tamaño: tamaño de la misma (se obtiene con sizeof)
numero: El número de estructuras a escribir
archivo: Puntero al archivo de de escritura
– La función devuelve el número de estructuras escritas
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 57
Estructura de Computadores
2ITIEI
Leyendo estructuras de archivos binarios
•
Se lee toda la estructura de una “tacada”
– Usando fread
– En un archivo abierto en modo binario
size_t fread(void *pestructura, size_t tamaño, size_t numero,
FILE *archivo);
– La función devuelve el número de estructuras leídas
• Comprobar que es igual al segundo parámetro
– numero
•
Ejemplos 8 y 9
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 58
29
Estructura de Computadores
2ITIEI
Programación avanzada en C
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 59
Estructura de Computadores
2ITIEI
Estructuras de datos avanzadas (complejas)
•
Árboles y Listas Enlazadas
•
Unidad de información: Nodo. Dos partes:
– Crecen según las necesidades del programa
– Área de datos. Típicamente un struct
– Área de enlace. Punteros a los nodos siguientes
• Y/o a los nodos anteriores. Ej:
•
enlace
0x1234
datos
27
typedef struct nodo{
struct nodo *psiguiente;
int num;
} NODO;
El ejemplo tiene:
– Un dato sencillo (tipo int)
– Un puntero a una estructura del mismo tipo
• Definición recursiva
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 60
30
Estructura de Computadores
2ITIEI
Forma de trabajo
•
Las estructuras se crean con
– calloc
•
Una vez utilizadas se liberan con
– free
•
Las distintas estructuras
– No necesitan estar en posiciones consecutivas de memoria
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 61
Estructura de Computadores
2ITIEI
Listas y árboles
•
Lista
NULL
3
27
1
NULL
•
Árbol
NULL
Juan
Pepe
NULL
NULL
NULL
Paco
María
NULL
Lola
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 62
31
Estructura de Computadores
2ITIEI
Listas y árboles II
•
Listas
– Área de enlace: Un punteno, al siguiente nodo
– NULL: en el último de la lista
•
Árboles
– Área de enlace: Dos punteros, a los nodos sucesores
– NULL: cuando no hay sucesor en la rama correspondiente
– El árbol de la figura es un árbol binario.
• Puede hacerse de tantas ramas como se desee
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 63
Estructura de Computadores
2ITIEI
Maratón popular
•
Los datos de un corredor en un nodo
– En el área de datos del nodo
#define TAM_NOM_CORR 100
typedef struct corredor {
mombre[TAM_NOM_CORR];
unsigned int dorsal;
unsigned int tiempo;
} T_CORREDOR;
•
/* Nombre del corredor */
/* Dorsal del corredor */
/* Tiempo empleado en la carrera */
El nodo
#define TAM_NOM_CORR 100
typedef struct nodo_corredor {
struct nodo_corredor *psig_nodo;
T_CORREDOR dat_corredor;
} T_NODO_CORREDOR;
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 64
32
Estructura de Computadores
2ITIEI
Declaración del nodo
•
Es una definición recursiva
– Uno de los campos de la estructura
– declara un puntero a una estructura del mismo tipo
• nodo_corredor
typedef struct nodo_corredor {
struct nodo_corredor *psig_nodo;
•
Ojo con la siguiente definición: Es incorrecta !
#define TAM_NOM_CORR 100
typedef struct nodo_corredor {
T_NODO_CORREDOR *psig_nodo;
T_CORREDOR dat_corredor;
} T_NODO_CORREDOR;
Cesáreo Fernández Martínez
/* Error */
UPCO- ICAI Departamento de Electrónica y Automática 65
Estructura de Computadores
2ITIEI
Listas con/sin nodo cabecera
•
Inserción por la cola en una lista
– sin nodo cabecera
Lista vacía
NULL
pprimer_nodo
NULL
1
pprimer_nodo
NULL
pprimer_nodo
Cesáreo Fernández Martínez
1
27
UPCO- ICAI Departamento de Electrónica y Automática 66
33
Estructura de Computadores
2ITIEI
Listas con/sin nodo cabecera II
•
Inserción por la cola en una lista
– con nodo cabecera. El nodo cabecera no tiene datos
Lista vacía
NULL
pcabecera
Lista con un nodo
NULL
pprimer_nodo
1
– El programa es más regular que en el caso anterior
Cesáreo Fernández Martínez
Estructura de Computadores
UPCO- ICAI Departamento de Electrónica y Automática 67
2ITIEI
Operaciones con la lista
•
Operaciones comunes:
– Inicializar la lista
– Recorrer todos los nodos
– Insertar nodos
• Al principio de la lista
• Al final de la lista
• Entre dos nodos de la lista
– Buscar un nodo
– Eliminar un nodo
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 68
34
Estructura de Computadores
2ITIEI
Inicializar la lista
•
Operaciones a realizar en pseudocódigo
T_NODO *IiniLista () {
Asignar memoria para el nodo cabecera
puntero al siguiente nodo del nodo cabecera = NULL
devolver la dirección del nodo cabecera
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 69
Estructura de Computadores
2ITIEI
Inicializar la lista II
•
En código C
T_NODO_CORREDOR *IniLista (void) {
T_NODO_CORREDOR *pcabecera;
p_cabecera = (T_NODO_CORREDOR *)calloc(1, sizeof(T_NODO_CORREDOR));
if (pcabecera == NULL) {
printf(“Error, no queda memoria\n”);
exit(1);
}
pcabecera->psig_nodo = NULL;
return pcabecera:
}
– Reserva espacio para el nodo cabecera
– Puntero a siguiente = NULL
– Devuelve puntero a la base de la lista
• Para que main pueda pasarlo al resto de funciones
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 70
35
Estructura de Computadores
2ITIEI
Recorrer la lista
•
Se recorre la lista para
– Imprimir los elementos de la misma
– Buscar un elemento
– Eliminar un nodo
•
Recorrer la lista en pseudocódigo
pnodo_act = dirección de cabecera
mientras el puntero al siguiente nodo al que apunta pnodo_act no sea NULL
pnodo_act = dirección del siguiente nodo
procesar el nodo al que apunta pnodo_act
fin mientras
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 71
Estructura de Computadores
2ITIEI
Imprimir la lista
•
En código C
void ImprimeLista(T_NODO_CORREDOR *pcabecera)
{
T_NODO_CORREDOR *pnodo_act;
/* Se recorre la lista imprimiendo cada uno de los nodos*/
pnodo_act = pcabecera;
while(pnodo_act->psig_nodo!= NULL){
pnodo_act = pnodo_act->psig_nodo;
ImprimeCorredor( &(pnodo_act->dat_corredor) );
}
}
– Puntero actual a la cabecera
– Puntero a siguiente != NULL
• Puntero actual a siguiente (se salta el primer nodo: vacío)
• Imprime datos del corredor (campo de datos del nodo)
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 72
36
Estructura de Computadores
2ITIEI
Imprimir corredor
•
En código C
void ImprimeCorredor(T_CORREDOR *pcorredor)
{
int horas, minutos, segundos;
segAhms(pcorredor->tiempo, &horas, &minutos, &segundos);
printf("Nombre: %s, dorsal: %d, tiempo: %02d:%02d:%02d\n",
pcorredor->nombre,
pcorredor->dorsal,
horas, minutos, segundos);
}
– Se llama a segAhms
• Para convertir el tiempo total en segundos a : horas, minutos y segs
– Esta función devuelve tres resultados
• Usando paso por referencia
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 73
Estructura de Computadores
2ITIEI
Función segAhms
•
Una implantación
void segAhms(long int tiempo, int *phor, int *pmin, int
*pseg)
{
*phor = tiempo/3600;
*pmin = (tiempo-*phor*3600)/60;
*pseg = tiempo - *phor*3600 - *pmin*60;
}
•
Otra
void segAhms(long int tiempo, int *phor, int *pmin, int
*pseg)
{
*phor = tiempo/3600;
*pmin = (tiempo%3600)/60;
*pseg = (tiempo%3600)%60;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 74
37
Estructura de Computadores
2ITIEI
Inserción de nodos en la lista
•
Varias formas de insertar
– Al principio de la lista
– Al final de la lista
– En medio de la lista
• Para mantenerla ordenada según un cierto criterio
•
Inserción al principio de la lista
Siguiente de pnodo = siguiente de pcabecera
Siguiente de pcabecera = pnodo
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 75
Estructura de Computadores
2ITIEI
Gráficamente
NULL
pcabecera
1
pnodo
Cesáreo Fernández Martínez
7
UPCO- ICAI Departamento de Electrónica y Automática 76
38
Estructura de Computadores
2ITIEI
Es correcto este código ?
•
Insertar al principio de la lista
– ¿ Funciona cuando la lista está vacía ?
void InsertaNodoPrinc(T_NODO_CORREDOR *pcabecera, T_NODO_CORREDOR *pnodo)
{
/* En primer lugar, el nodo que queremos colocar al principio tendrá
que apuntar al que antes era el primero de la lista, cuya dirección está
en el nodo cabecera */
pnodo->psig_nodo = pcabecera->psig_nodo;
/* en segundo lugar hay que hacer que la cabecera apunte al nodo que
acabamos de colocar en primer lugar */
pcabecera->psig_nodo = pnodo;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 77
Estructura de Computadores
2ITIEI
Inserción de nodos al final de la lista
•
En pseucódigo
pnodo_act = dirección de cabecera
mientras que siguiente de pnodo_act no sea NULL
pnodo_act = siguiente de pnodo_act
fin mientras
siguiente de pnodo_act = pnodo
siguiente de pnodo = NULL
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 78
39
Estructura de Computadores
2ITIEI
Inserción de nodos al final de la lista
•
En código C
AnadeNodo(T_NODO_CORREDOR *pcabecera, T_NODO_CORREDOR *pnodo)
{
T_NODO_CORREDOR *pnodo_act;
/* En primer lugar se busca el último nodo de la lista, que será aquel
cuyo puntero psig_nodo sea NULL */
pnodo_act = pcabecera; /* comenzamos por la cabecera */
while(pnodo_act->psig_nodo!= NULL){
pnodo_act = pnodo_act->psig_nodo;
}
/* cuando lleguemos aquí, pnodo_act contiene la dirección del último
nodo de la lista, con lo que podemos añadir el nuevo nodo */
pnodo_act->psig_nodo = pnodo; /* Ahora el que antes era el último
elemento de la lista apunta a pnodo,
que ahora es el último elemento */
pnodo->psig_nodo = NULL; /* como es el último, no hay nodo siguiente*/
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 79
Estructura de Computadores
2ITIEI
Gráficamente
pcabecera
1
NULL
pnodo
Cesáreo Fernández Martínez
7
UPCO- ICAI Departamento de Electrónica y Automática 80
40
Estructura de Computadores
2ITIEI
Inserción de nodos en medio de la lista
•
En pseucódigo
– Para mantener la lista ordenada (dorsal/tiempos)
– Dos punteros: actual y anterior
• Insertamos entre actual y anterior
pnodo_ant = dirección de cabecera
pnodo_act = siguiente de cabecera
mientras pnodo_act no sea NULL
si dorsal de pnodo_act > dorsal de pnodo /* Encontrado */
siguiente de pnodo_ant = pnodo
siguiente de pnodo = pnodo_act
return
/* Hemos terminado */
fin si
pnodo_ant = pnodo_act
/* Se avanza al siguiente nodo*/
pnodo_act = siguiente de pnodo_act
fin mientras
/* Si se llega aquí es que el nodo va al final */
siguiente de pnodo_ant = pnodo
siguiente de pnodo = NULL
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 81
Estructura de Computadores
2ITIEI
Inserción de nodos en medio de la lista
•
En código C
void InsertaNodoOrdenDor(T_NODO_CORREDOR *pcabecera, T_NODO_CORREDOR *pnodo)
{
T_NODO_CORREDOR *pnodo_act;
T_NODO_CORREDOR *pnodo_ant; /* dirección del nodo anterior al que estoy
analizando. Es necesario guardarlo para
que al insertar pnodo, el nodo anterior
al actual apunte a pnodo y pnodo apunte
al actual */
pnodo_act = pcabecera->psig_nodo;
pnodo_ant = pcabecera;
/* Se recorre la lista hasta que se encuentre un nodo cuyo dorsal
sea mayor que el del que se va a insertar o
hasta que se llegue al final de la lista */
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 82
41
Estructura de Computadores
2ITIEI
Inserción de nodos en medio de la lista II
•
En código C
while( pnodo_act != NULL ){
if( (pnodo_act->dat_corredor).dorsal > (pnodo->dat_corredor).dorsal){
/* Encontré el sitio en el que va el nodo. Ahora sólo falta
insertarlo */
pnodo->psig_nodo = pnodo_act;
pnodo_ant->psig_nodo = pnodo;
return; /* Una vez insertado no hace falta hacer nada más, así que
salimos de la función */
}
pnodo_ant = pnodo_act;
pnodo_act = pnodo_act->psig_nodo; /* Pasamos al siguiente nodo */
}
/* Si se llega aquí, es que el nodo va al final */
pnodo_ant->psig_nodo = pnodo;
pnodo->psig_nodo = NULL;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 83
Estructura de Computadores
2ITIEI
Gráficamente
Pnodo_act
Pnodo_ant
3
pnodo
Cesáreo Fernández Martínez
10
7
UPCO- ICAI Departamento de Electrónica y Automática 84
42
Estructura de Computadores
2ITIEI
Búsqueda de un nodo en la lista
•
Recorrer la lista
•
En pseudocódigo
– Hasta encontrar el nodo
pnodo_act = dirección de cabecera
mientras siguiente de pnodo_act no sea NULL
pnodo_act = siguiente de pnodo_act
si los datos de pnodo_act coinciden con los buscados
return pnodo_act
fin si
fin mientras
return NULL /* No se ha encontrado */
Cesáreo Fernández Martínez
Estructura de Computadores
UPCO- ICAI Departamento de Electrónica y Automática 85
2ITIEI
En C
•
Busca número de dorsal
T_NODO_CORREDOR *BuscaNodoDorsal(T_NODO_CORREDOR *pcabecera, int dorsal)
{
T_NODO_CORREDOR *pnodo_act;
/* Se recorre la lista comparando el dorsal de cada nodo con el que
se está buscando */
pnodo_act = pcabecera;
while(pnodo_act->psig_nodo!= NULL){
pnodo_act = pnodo_act->psig_nodo;
if( (pnodo_act->dat_corredor).dorsal == dorsal){ /* Encontrado */
return pnodo_act; /* Devuelvo su dirección */
}
}
/* Si llegamos aquí, es que no hay en la lista un nodo con el dorsal
buscado. En este caso se devuelve un NULL para que el programa
principal obre en consecuencia */
return NULL;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 86
43
Estructura de Computadores
2ITIEI
Eliminar los nodos de una lista
•
Para eliminar todos los nodos de una lista
– Recorrer la lista
– Eliminar nodo (cuidado de no perder el puntero al siguiente nodo)
•
En pseudocódigo
pnodo_act = dirección de cabecera
hacer
pnodo_borrar = pnodo_act
pnodo_act = siguiente de pnodo_act
liberar pnodo_borrar
mientras pnodo_act no sea NULL
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 87
Estructura de Computadores
2ITIEI
En C
•
Secuencia
– Primero: mueve el puntero al nodo actual
– Borra nodo anterior
void LiberaLista(T_NODO_CORREDOR *pcabecera)
{
T_NODO_CORREDOR *pnodo_act;
T_NODO_CORREDOR *pnodo_borrar; /* Nodo que se va a borrar */
/* Se recorre la lista liberando la memoria de cada uno de los nodos*/
pnodo_act = pcabecera;
do{
pnodo_borrar = pnodo_act; /* Antes de que pnodo_act apunte al
siguiente nodo, lo guardamos para poder
liberarlo después */
pnodo_act = pnodo_act->psig_nodo;
free(pnodo_borrar);
}while(pnodo_act!= NULL);
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 88
44
Estructura de Computadores
2ITIEI
Eliminar un nodo de la lista
– Recorrer la lista
• Hasta encontrar el nodo deseado (P.e. dorsal 7)
– Enlazar punteros
• Anterior y siguiente
– Borrar
pnodo_ant = dirección de cabecera
pnodo_act = siguiente de cabecera
mientras pnodo_act no sea NULL
si dorsal de pnodo_act == dorsal buscado /* Encontrado */
siguiente de pnodo_ant = siguiente de pnodo_act
liberar pnodo_act
return 1
/* Hemos terminado
*/
fin si
pnodo_ant = pnodo_act
/* Se avanza al
siguiente nodo*/
pnodo_act = siguiente de pnodo_act
fin mientras
/* Si se llega aquí es que no se ha encontrado el nodo */
return 0
Cesáreo Fernández Martínez
Estructura de Computadores
UPCO- ICAI Departamento de Electrónica y Automática 89
2ITIEI
En C
– Función: BorraNodoDorsal
int BorraNodoDorsal(T_NODO_CORREDOR *pcabecera, int dorsal)
{
T_NODO_CORREDOR *pnodo_act;
T_NODO_CORREDOR *pnodo_ant; /* dirección del nodo anterior al que estoy
analizando. Es necesario guardarlo para
que al borrar el nodo actual, el nodo
anterior al actual apunte al nodo
siguiente
al actual */
pnodo_act = pcabecera->psig_nodo;
pnodo_ant = pcabecera;
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 90
45
Estructura de Computadores
2ITIEI
En C II
/* Se recorre la lista hasta que se encuentre un nodo cuyo dorsal
sea igual al buscado o hasta que se llegue al final de la lista */
while( pnodo_act != NULL ){
if( (pnodo_act->dat_corredor).dorsal == dorsal){
/* Encontré el nodo. Ahora sólo falta eliminarlo de la lista y
liberar su memoria */
pnodo_ant->psig_nodo = pnodo_act->psig_nodo;
free(pnodo_act);
return 1; /* Se devuelve 1 para indicar que el corredor se ha
eliminado de la lista */
}
pnodo_ant = pnodo_act;
pnodo_act = pnodo_act->psig_nodo; /* Pasamos al siguiente nodo */
}
/* Si se llega aquí, es que no se ha encontrado ningún corredor con el
dorsal adecuado. Por tanto se devuelve un cero */
return 0;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 91
Estructura de Computadores
2ITIEI
Ordenar (datos)
•
Organizar datos en
•
Usando un “ordenador”
– Una secuencia específica
– Interna. En RAM
– Externa. En cinta (en desuso)
•
Ordenar objetos
– Según una de sus características
• Campo de la estructura de datos que da la característica
•
Algoritmos estables
– Al ordenar por varios campos
– No destruyen el orden previo
• Según otro campo (orden previo: ISBN, orden nuevo: autor)
- Dentro del mismo autor se mantiene el orden por ISBN
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 92
46
Estructura de Computadores
2ITIEI
Algoritmos
•
Sencillos. Muchas operaciones (n2)
– Burbuja
– Inserción
•
Complicados. Menos operaciones (n log n)
– Quicksort
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 93
Estructura de Computadores
2ITIEI
Burbuja
•
Simula una burbuja en una columna de agua
•
Pseudo
– Los elementos de menor peso suben arriba (base del vector)
desde i=1 hasta N-1
desde j=N-1 hasta 1
si vec[j-1] > vec[j]
intercambia vec[j-1] con vec[j]
fin si
fin desde
fin desde
•
Dos bucles
– Interno: Compara pares adyacentes (de final a principio)
• Intercambia si el de abajo es menor que el de arriba
– En una pasada sube el elemento de menor peso
• A la posición 0 del vector (vector[0])
– Resto de pasadas (bucle externo)
• Para que vayan subiendo el resto de elementos hasta su posición
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 94
47
Estructura de Computadores
2ITIEI
Mejora I
•
Puesto que en la primera pasada
– Ya ha ocupado la posición 0 del vector
– No es necesario seguir comparando este elemento
desde i=1 hasta N-1
desde j=N-1 hasta i /* se ha cambiado sólo esta línea */
si vec[j-1] > vec[j]
intercambia vec[j-1] con vec[j]
fin si
fin desde
fin desde
•
•
El bucle interno ordena cada vez vectores más pequeños
El bucle externo
– Hasta asegurar la ordenación
•
¿Y si queda ordenado en menos pasadas del bucle
externo?
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 95
Estructura de Computadores
2ITIEI
Mejora II
•
No es necesario dar tantas pasadas del bucle externo
– Levamos variable de estado (bandera): ordenado
desde i=1 hasta N-1
ordenado = 1
desde j=N-1 hasta i /* se ha cambiado sólo esta línea */
si vec[j-1] > vec[j]
intercambia vec[j-1] con vec[j]
ordenado = 0
fin si
fin desde
si ordenado == 1
break
fin si
fin desde
•
Si el vector de partida está prácticamente ordenado
– Con los elementos de peso ordenados y al final
• Y algún ligero entre medias
– Esta versión resulta muy eficiente
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 96
48
Estructura de Computadores
2ITIEI
En C
main()
{
int vec[N]={3,4,7,1}; /* Vector a ordenar */
int i, j;
/* Índices para los bucles */
int temp;
int ordenado; /* Bandera que indica si el vector ya está ordenado*/
•
for(i=1; i<N; i++){
ordenado = 1;
for(j=N-1; j>=i; j--){
if(vec[j-1] > vec[j]){
temp
= vec[j];
vec[j]
= vec[j-1];
vec[j-1] = temp;
Si el vector
de
partida está prácticamente ordenado
ordenado = 0;
– }Con los elementos de peso ordenados y al final
}
• Y algún ligero entre medias
if(ordenado == 1){
– break;
Esta versión resulta muy eficiente
}
}
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 97
Estructura de Computadores
2ITIEI
Inserción
•
Comparar las dos cartas a la izquierda. Orden incorrecto
•
Comparar la siguiente carta (pivote) con las anteriores
– Intercambio
– Hacen hueco
– Inserta (el pivote)
int *Ordena(int *pi, int n) {
int i,j,t;
for(i=1; i<n ; i++) {
t = pi[i];
// pivote
for(j=i; j>0 && pi[j-1] > t; j--)
pi[j] = pi[j-1];
pi[j] = t;
}
return pi;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 98
49
Estructura de Computadores
2ITIEI
Versión recursiva
•
Selecciona pivote el elemento de la posición 0
•
A la vuelta de las llamadas recursivas
– Llamada recursiva hasta que queda un elemento
– Compara con el pivote
– Desplaza a la izquierda hasta encontrar el punto de inserción
int *Ordenar(int *pi, int n) {
int i,t;
if (n > 1) {
t = pi[0];
Ordenar(pi+1,n-1);
for(i=0; i<n-1 && pi[i+1]<t; i++)
pi[i] = pi[i+1];
pi[i] = t;
}
return pi;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 99
Estructura de Computadores
2ITIEI
qsort
•
Quick sort
– Es recursivo
– Basado en árboles binarios
•
Utiliza intercambios en distancias largas
– Al contrario de la burbuja (distancias cortas, adyacentes)
•
Ejemplo
9 7 5 3 1
•
C.A.R. Hoare 1962.
Cesáreo Fernández Martínez
1 3 5 7 9
Orden: n log n (frente a n2)
UPCO- ICAI Departamento de Electrónica y Automática 100
50
Estructura de Computadores
2ITIEI
Principio de diseño
•
“Divide y vencerás”
•
Se selecciona un elemento del vector: Pivote
– A la izquierda se ponen los elementos menores que el Pivote
– A la derecha se ponen los elementos mayores que el Pivote
•
Se repite el proceso
– En ambas mitades
– Mientras número de elementos > 1
•
Hasta completar la ordenación
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 101
Estructura de Computadores
2ITIEI
Gráficamente
Pivote
7
9
5
3
Pivote
1
Pivote
+
1
3
5
+
1
Cesáreo Fernández Martínez
9
+
3
5
7
+
7
9
UPCO- ICAI Departamento de Electrónica y Automática 102
51
Estructura de Computadores
2ITIEI
De forma algoritmica
•
Se selcciona un pivote
•
Do
– P.e. El elemento central del vector
– Se busca por la izquierda del pivote
• Un elemento a[i] >= pivote
– Se busca por la derecha del pivote
• Un elemento a[j] <= pivote
– Se intercambian los elementos a[i]
• i++
,
<->
a[j]
j--
•
Repetir mientras i<j
•
El proceso se repite en ambas mitades
– Mientras número de elementos > 1
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 103
Estructura de Computadores
2ITIEI
En pseudocódigo
función quicksort(vec, izq, der)
i=izq
j=der
pivote = vec[(i+j)/2]
hacer
mientras vec[i] < pivote
i++
fin mientras
mientras vec[j] > pivote
j-fin mientras
si i <= j
intercambiar vec[i] con vec[j]
i++
j-fin si
mientras i <= j
si izq < j
// más de un elemento
quicksort(izq, j)
fin si
si der > i
// más de un elemento
quicksort(i, der)
fin si
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 104
52
Estructura de Computadores
2ITIEI
Bucles i/j de forma gráfica
Pivote = 1
3
7
1
i
8
1
1
7
1
i
j
8
3
j
1
7
1
i
j
8
3
Pivote = 1
1
1
7
j
i
Cesáreo Fernández Martínez
8
3
UPCO- ICAI Departamento de Electrónica y Automática 105
Estructura de Computadores
2ITIEI
Nótese
•
A la izquierda del pivote
•
A la derecha del pivote
– Elementos <= que el pivote
– Elementos >= que el pivote
•
El pivote queda insertado
– En cualquier posición del vector
– En su posición definitiva
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 106
53
Estructura de Computadores
2ITIEI
Versión C
•
Con etiqueta DEBUG
– De ayuda a la depuración
void quicksort(int *pvec, int izq, int der)
{
int pivote;
int i,j;
int temp;
i=izq;
j=der;
pivote = pvec[(izq+der)/2];
#ifdef DEBUG
printf("Izq = %d, Der = %d, Pivote = %d ", izq, der, pivote);
#endif
do{
while(pvec[i] < pivote){
i++;
}
while(pvec[j] > pivote){
j--;
}
Cesáreo Fernández Martínez
Estructura de Computadores
UPCO- ICAI Departamento de Electrónica y Automática 107
2ITIEI
Versión C II
if(i <= j){
temp
= pvec[i];
pvec[i] = pvec[j];
pvec[j] = temp;
i++;
j--;
}
}while(i <= j);
#ifdef DEBUG
printf("i= %d, j= %d\n", i, j);
printf("Vec= ");
ImpVec(pvec, N);
#endif
if(izq<j){
quicksort(pvec, izq, j);
}
if(der>i){
quicksort(pvec, i, der);
}
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 108
54
Estructura de Computadores
2ITIEI
qsort de la librería estandar
•
Prototipo
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
•
Argumentos:
– Base del vector
– Número de elementos
– Tamaño de cada elemento
– (*compar): Puntero a la función de comparación
•
La función de comparación
– Recibe: dos punteros a los elementos a comparar
– Devuelve: int>0 si primer_elemento> segundo
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 109
Estructura de Computadores
2ITIEI
Llamada
•
La llamada a qsort
int comp(const void *pa, const void *pb);
main()
{
int vec[N] = {3,7,1,8,1};
....
qsort((void *)vec, N, sizeof(vec[0]), comp);
....
•
La función qsort utiliza punteros void
– De esta forma es genérica !!!
– Puede trabajar con vectores de elementos de cualquier tipo
– Únicamente hay que suministrar la función de comparación
adecuada
– qsort utilizará la función de comparación suministrada
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 110
55
Estructura de Computadores
2ITIEI
Funciones de comparación
•
•
Diferentes funciones de comparación
Para enteros
int comp(const void *pa, const void *pb)
{
return *((int *)pa) - *((int *)pb);
}
•
Para flotantes
int comp(const void *pa, const void *pb)
{
return *((float *)pa) - *((float *)pb);
}
•
La función de comparación
– Convierte los punteros void al tipo adecuado
• Realiza el paso contrario al realizado en la llamada a qsort
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 111
Estructura de Computadores
2ITIEI
qsort puede ordenar objetos de cualquier tipo
•
Entre ellos, puede ordenar cadenas de caracteres
•
Para hacerlo de forma eficiente
– Sólo se necesita suministrar la función de comparación adecuada
– Se utiliza un vector de punteros
– El intercambio de punteros de vector es eficiente
•
Vector de punteros
José Manuel
Juan José
Pepe
Ana María
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 112
56
Estructura de Computadores
2ITIEI
Ordenado
•
Vector de punteros odenado
José Manuel
Juan José
Pepe
Ana María
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 113
Estructura de Computadores
2ITIEI
Vector de punteros
•
Definición
char *pvect[N];
•
// Define un vector de N punteros a cadenas
Entrada de datos
for(i=0;i<N;i++){
fgets(temp, TAM, pf);
// Entrada por fichero
if(strlen(temp)>1){
pvect[i]=calloc(strlen(temp)+1, sizeof(char));
if (pvect[i] == NULL)
erorr(“No hay memoria”);
strcpy(pvect[i], temp);
}
else
break;
}
pvect[i] = NULL;
return i;
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 114
57
Estructura de Computadores
2ITIEI
Ordenando con quicksort
•
Reescribir la función quicksort de clase
•
De forma que en lugar de utilizar
– Operadores >, <, >=, <=
•
Se utilice
– No nos gusta la de lib (cambio char* -> void* y viceversa
– Una función de comparación de cadenas
– strcmp u otra distinta
•
Práctica de lab.
– Para la base de datos de libros
– Con entrada por fichero binario
– Función de comparación: strcmp
•
quicksort recibe char **ppcad !
– (ppcad[0] es el primer puntero, ppcad[i] puntero i)
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 115
Estructura de Computadores
2ITIEI
Ejemplo de doble puntero: Burbuja
void Burbujap(char **ppcad, int ncad)
{
int i,j;
char *ptemp;
int ordenado;
for(i=1; i<ncad; i++){
ordenado = 1;
for(j=ncad-1; j>=i; j--){
if(strcmp(ppcad[j-1], ppcad[j])>0){
ptemp
= ppcad[j];
ppcad[j] = ppcad[j-1];
ppcad[j-1] = ptemp;
ordenado = 0;
}
}
if(ordenado == 1){
break;
}
}
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 116
58
Estructura de Computadores
2ITIEI
Caso de interés práctico
•
Ordenar cadenas de caracteres
– Escaso interés práctico
•
Ordenar vectores de estructuras
•
Ejemplos
– Por un campo de una estructura (tipo cadena): Gran interés
– Biblioteca: Ordenar por autor
– CD’s: Ordenar por título
•
En lugar de vector de punteros a cadenas usamo vecto de
punteros a estructuras
LIBRO *pvect[N];
CD
*pvect[N];
•
// Define un vector de N punteros a LIBRO’s
// Define un vector de N punteros a CD’s
Quicksort recibe LIBRO **ppvec (doble puntero)
– Con la función de comparación adecuada. En este caso usamos
strcmp(ppvec[i]->libro->autor, ppvec[j]->libro->autor)
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 117
Estructura de Computadores
2ITIEI
Casos prácticos: Resumen
•
Con quicksort debemos
– Usar vectores de punteros a estructuras
– No vale para listas
•
Y si se desea la flexibilidad de una lista?
– Borrar/añadir nodos
•
Usar la lista para la entrada de datos
– Doblemente enlazada (si queremos usar burbuja sobre la lista).
•
Para usar quicksort
– Crear un vector de punteros de forma dinámica
– Ordenar utilizando el vector de punteros
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 118
59
Estructura de Computadores
2ITIEI
Árboles
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 119
Estructura de Computadores
2ITIEI
Árboles
•
Basados en nodos
– Con dos o más ramas
– Dos o más punteros (a nodo siguiente).
•
Ej: Ascendientes de Paco
NULL
NULL
Juan
Pepe
NULL
NULL
Paco
NULL
María
NULL
Lola
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 120
60
Estructura de Computadores
2ITIEI
Árboles II
•
•
Ideales para organizar datos que forman una jerarquía
Ejemplos
– Un árbol de carpetas/archivos: Windows, Unix, etc.
– Sitio Web: Página principal, páginas hijas
– Evaluación de expresiones: (a * b + c) * (d – e / f)
a
*
+
b
*
C
-
d
e
/
f
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 121
Estructura de Computadores
2ITIEI
Terminología
•
Descendiente directo
•
Ascendiente directo
•
Niveles
– Cuando un nodo está inmediatamente por debajo de otro
– Justo por encima.
– Raíz: Nivel 1
– Profundad. Máximo nivel
•
Nodos hoja
– No tienen descendientes
– Resto de nodos: Nodos interiores
•
Grado
– Número de descendienes
– Grado 2: árboles binarios
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 122
61
Estructura de Computadores
2ITIEI
Árboles equilibrados
•
Equilibrado: cuando para todo nodo
– El número de nodos en el subárbol izquierdo, y
– El número de nodos en el subárbol derecho
Difieren como mucho en 1
•
Equilibrado y ordenado
– Ideales para realizar búsquedas
– En pocos pasos
1
3
4
5
8
6
9
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 123
Estructura de Computadores
2ITIEI
Árboles binarios
•
Conjunto de nodos que
– Está vacío, o
– Formado por un nodo raíz: más dos subárboles disjuntos
• Derecho
• Inzquierdo
– (si no fuesen disjuntos sería un grafo: útiles para representar
REDES malladas)
•
Nodo (declaración)
typedef struct nodo_arbol{
int n;
struct nodo_arbol *pder;
struct nodo_arbol *pizq;
}T_NODO_ARBOL;
Cesáreo Fernández Martínez
/* Área de datos */
/* Área de enlace */
UPCO- ICAI Departamento de Electrónica y Automática 124
62
Estructura de Computadores
2ITIEI
Construir un árbol
•
•
•
Manteniendo la altura mímima
Manteniendo el árbol equilibrado
Replicando algún tipo de estructura física
– Topología de una red radial
•
Equilibrado de altura mínima sin ordenar
•
Procedimiento recursivo
– Llenar por niveles
– Se genera la raíz
– Se genera el subárbol izquierdo de n/2 nodos
• De la misma forma que el árbol completo: mismo algoritmo
– Se genera el subárbol derecho de n-n/2-1 nodos
• De la misma forma que el árbol completo: mismo algoritmo
Cesáreo Fernández Martínez
Estructura de Computadores
UPCO- ICAI Departamento de Electrónica y Automática 125
2ITIEI
Árbol binario en C
T_NODO_ARBOL *Arbol(int n) {
int ni, nd; /* Número de nodos a la derecha y a la izquierda */
T_NODO_ARBOL *praiz; /* Raíz del árbol que se va a crear */
if(n<=0){ /* Si se desea crear un árbol de tamaño nulo */
return NULL; /* Se devuelve NULL */
}else{
/* Se crea un árbol con 1 nodo raíz, ni nodos a la izquierda y nd a la
derecha */
ni = n/2;
nd = n-ni-1; /* El -1 es por la raíz */
/* Se crea el nodo raíz */
praiz = (T_NODO_ARBOL *)calloc(1,sizeof(T_NODO_ARBOL));
if(praiz==NULL){
printf("Error: No hay memoria suficiente\n"); return NULL;}
/* Se lee el número a almacenar en este nodo */
printf("n= ");
scanf("%d", &(praiz->n));
/* Y se termina creando los subárboles izquierdo y derecho */
praiz->pizq = Arbol(ni);
praiz->pder = Arbol(nd);
return praiz;
}
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 126
63
Estructura de Computadores
2ITIEI
Impresión del árbol
•
De forma recursiva
– Comenzando por el subárbol derecho
• Con tantos espacios como indica margen
void ImprimirArbol(T_NODO_ARBOL *praiz, int margen)
{
int n;
if(praiz != NULL){
ImprimirArbol(praiz->pder, margen+1);
for(n=0; n<margen; n++){
printf(" ");
}
printf("%d\n",praiz->n);
ImprimirArbol(praiz->pizq, margen+1);
}
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 127
Estructura de Computadores
2ITIEI
Resultado de la impresión
•
Mayor espaciado en las hoja
– Menor en los nodos intermedios
7
5
6
1
4
2
3
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 128
64
Estructura de Computadores
2ITIEI
Liberar el árbol
•
Mediante función recursiva
void LiberaArbol(T_NODO_ARBOL *praiz)
{
if(praiz != NULL){
/* Primero se liberan los descendientes del nodo raíz */
LiberaArbol(praiz->pder);
LiberaArbol(praiz->pizq);
/* Y a continuación se libera el nodo raíz de este árbol (o subárbol) */
free(praiz);
}
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 129
Estructura de Computadores
2ITIEI
Programa principal
•
Crea el árbol y lo imprime
main()
{
int n;
T_NODO_ARBOL *praiz;
printf("Número de nodos= ");
scanf("%d", &n);
praiz=Arbol(n);
ImprimirArbol(praiz, 0);
LiberaArbol(praiz);
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 130
65
Estructura de Computadores
2ITIEI
Tablas Hash
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 131
Estructura de Computadores
2ITIEI
Tablas hash
•
•
Ideales para buscar de forma rápida
Es un vector (tabla) de punteros cabecera a diferentes
listas
– Cada nodo de la lista tiene
• Puntero al siguiente
• Campo(s) de información
– En índice del vector es el número “hash”
• Obtenido en función del campo de información
0
Lista 1
0
0
0
0
0
Cesáreo Fernández Martínez
Lista N
UPCO- ICAI Departamento de Electrónica y Automática 132
66
Estructura de Computadores
2ITIEI
Ejemplo
•
Tabla de “defines” . Ej : #define N 10
– Objetivo:
• Montar la tabla de define’s
• Cuando aparece un define. Sustituir por su valor
•
Nodo:
struc nlinst {
struct nlist *next;
char *name;
char *defn;
}
•
// Nombre
// Valor
La tabla es
– Un vector de punteros (de cabecera a diferentes listas)
struc #define HASHSIZE 101
struct nlinst *hashtab[HASHSIZE];
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 133
Estructura de Computadores
2ITIEI
La función hash
•
Devuelve un valor entero positivo función de
– Los caracteres de una cadena
• “suma ponderada” de los caracteres de la cadena
unsigned int hash(char *s) {
unsigned int hashval;
for (hashval=0; *s != ‘\0’; s++)
hashval = *s + 31*hashval;
return hashval % HASHSIZE;
}
•
El valor devuelto
– Es el índice en la tabla de hash
– La cadena buscada sólo puede estar en esta posición de la tabla
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 134
67
Estructura de Computadores
2ITIEI
Búsqueda
•
La búsqueda se realiza sobre
– La lista correspondiente a la posición de la tabla de hash
– Dada por el índice devuelto por la función hash
struct nlist *lookup(char *s) {
struct nlist *np;
for (np = hashtab[hash(s)]; np != NULL; np = np->next)
if(strcmp(s, np->name) == 0)
return np;
return NULL;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 135
Estructura de Computadores
2ITIEI
Install:
Introducir un nombre en la tabla
•
usa lookup para
Install
– Ver si el nombre está ya en la tabla
• Si ya está, la nueva definición anula la antigua
– Si el nombre no está en la tabla
• Se crea y
• Se añade a la lista correspondiente
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 136
68
Estructura de Computadores
Install II:
2ITIEI
Introducir un nombre en la tabla
struct nlist *install(char *name, char *defn) {
struct nlist *np;
unsigned hashval;
if ((np = lookup(name)) == NULL) {
np = (struct nlist *) malloc(sizeof(*np));
if (np == NULL ||np->name = strdup(name))== NULL)
return NULL;
hashval = hash(name);
np->next = hashtab[hashval];
hashtab[hashval] = np;
} else
free((void *) np->defn);
if ((np->defn = strdup(defn)) == NULL)
return NULL;
return np;
}
Cesáreo Fernández Martínez
UPCO- ICAI Departamento de Electrónica y Automática 137
69
Descargar