ELO320 Estructuras de Datos y Algoritmos Introducción...
Transcript of ELO320 Estructuras de Datos y Algoritmos Introducción...
1: Intro 1
ELO320 Estructuras de Datos y Algoritmos
Introducción
Tomás Arredondo Vidal
Este material está basado en:
❒Robert Sedgewick, "Algorithms in C", (third edition), Addison-Wesley, ISBN 0-201-31663-3, 2001.
❒B. Kernighan, R. Ritchie, “The C Programming Language”, Prentice Hall, ISBM 0-13-110362-8, 1988.
❒material en el sitio http://www.wikipedia.org
❒material del curso ELO320 del Prof. Leopoldo Silva y del Prof. Werner Creixell
1: Intro 2
1-Introducción
1.1 Background
1.2 Estructuras y tipos de datos básicos
1.3 Typedefs, estructuras y unión
1.4 Arreglos, malloc y punteros
1: Intro 3
Consideraciones
❒ Imaginen que tienen que desarrollar un producto en algún ámbito de la ingeniería como telecomunicaciones/telematica, control, redes, computadores o electrónica.
❒ ¿Cuales serian las cosas que influenciarían el éxito o fracaso del proyecto?
❒ ¿Cuales serian algunas consideraciones antes de empezar el proyecto?❍ Ver lo que quiere el mercado: tamaño?, costo?, prestaciones?, tiempo de vida?, confiabilidad?, disponibilidad?, mantenibilidad?
1: Intro 4
Arquitectura
❒ Esas consideraciones se denominan requerimientos y son los que determinan la arquitectura del producto.
❒ Para poder diseñar la arquitectura de un producto computacional es necesario considerar:
❍ la(s) plataforma(s) a usar (hw, sw, herramientas, open source?),❍ performance (tiempo real v/s batch processing),❍ el tamaño y tipo de los datos de input/output, ❍ la mantenibilidad deseada (mientras mas obscura la implementación es menos mantenible),
❍ el encapsulamiento o modularidad deseada, ❍ la disponibilidad (e.g. 24x7),❍ la confiabiliad (e.g. 99.999),❍ redundancia y planes de contingencia, ❍ el uso de métodos de abstracción como capas u objetos, los recursos que se disponen para el desarrollo entre otros.
1: Intro 5
Herramientas
❒ Asociado con la arquitectura hay muchas consideraciones relacionadas con las plataformas y herramientas de trabajo como por ejemplo seleccionar:
❍ hardware, ❍ elección de protocolos (e.g. TCP/IP vs RS232), ❍ elección de lenguaje de programación (e.g. Java vs C++), ❍ elección de IDEs/compiladores/depuradores/profilers (e.g C::B), ❍ sistemas de validación (testers automatizados?), ❍ uso de librerías, ❍ uso de plataformas abiertas v/s cerradas etc.
❒ Todas estas decisiones van a tener una seria implicación en el resultado final del sistema que se esta desarrollando.
1: Intro 6
Diseño y testing
❒ Una vez definida la arquitectura y plataformas típicamente se necesita hacer un diseño para especificar los componentesespecíficos (programas, funciones, librerías, objetos o métodos) que forman parte de nuestro sistema a desarrollar.
❒ Todos estos componentes deberían tener especificados en su diseño los inputs y los outputs requeridos para validar su correcto desarrollo que es verificado mediante testing (o pruebas).
❒ Estas pruebas pueden ser:❍ testing funcional o de unidad,❍ testing de integración,❍ testing del systema,❍ testing de acceptacion,❍ testing de regression,❍ white box / black box,❍ stress tests, load tests, performance tests,❍ conformance tests (vs standards).
http://en.wikipedia.org/wiki/Software_testing
1: Intro 7
Desarrollo
❒ El trabajo a desarrollar en este curso principalmente afecta las áreas de diseño y desarrollo.
❒ Los algoritmos y estructuras de datos típicamente son parte vital de la implementación de una aplicación o producto.
❒ Dependiendo de la elección y uso de ellas nuestra aplicación y producto puede ser eficiente o ineficiente, un éxito rotundo o un total fracaso.
❒ Standards son claves para tener uniformidad en el desarrollo (e.g. ver Linux Kernel Coding Style)
1: Intro 8
Proceso de desarrollo
❒ Un tema que muchas veces es ignorado por las organizaciones es que el desarrollar un sistema o aplicación es un proceso complejo que requiere de organización, planificación y de completar diferentes etapas en la vida de el proyecto.
❒ Este trabajo no termina ya que se debe continúar mejorando el producto y los procesos de desarrollo durante la vida del proyecto.
RequerimientosArquitectura
DiseñoDesarrollo
Validación
Mejoramiento Continuo
Waterfall model Iterative model
http://en.wikipedia.org/wiki/Iterative_and_incremental_development
1: Intro 9
1-Introducción
1.1 Background
1.2 Estructuras y tipos de datos básicos
1.3 Typedefs, estructuras y unión
1.4 Arreglos, malloc y punteros
1: Intro 10
Estructuras de datos
❒ Para su funcionamiento los programas requieren algoritmos que operan en estructuras de datos para procesar inputs y para producir los outputs deseados.
❒ Especialmente la elección de estructuras de datosinfluyen en el espacio requerido para almacenar los datos necesarios y en el tiempo necesario para completar los cálculos por los algoritmos seleccionados (SedgewickCap. 3), (K&R Cap. 2).
1: Intro 11
Tipos de datos básicos y modificadores (cont)
❒ Veamos un primer programa:
$ cat hola.cc
#include <stdio.h>
int main(void)
{
printf("hola mundo");
return 0;
}
$ ./hola.exe
hola mundo
1: Intro 12
Tipos de datos básicos y modificadores (cont)
❒ Para ayudar al reuso de los programas y la mejor organización de ellos se recomienda separar los programas en por lo mínimo tres archivos:
❍ Un interfaz (interface) con las definiciones de los tipos de datos y la declaración de las funciones (e.g. un archivo cabecera con extensión .h).
❍ Un archivo de implementación (definición) con extensión .cc.
❍ Un programa (e.g. main( ) ) que utilice el interfaz al incluir el archivo de cabecera (header file) y que incluya los códigos objetos de la implementación de las funciones del interfaz en su compilación.
❒ Es importante usar nombres de variables que tengan sentido y que expliquen resumidamente el significado de lo que contiene la variable. De igual forma los nombres de las funciones.
❒ Las cabeceras (.h) deberian tener un formato que indique el nombre y los inputs/outputs de cada funcion.
1: Intro 13
Tipos de datos básicos y modificadores (cont)
❒ Es buena practica generar un archivo Makefile que sirve para organizar los archivos fuentes y sus dependencias.
❒ El Makefile es leido por un programa llamando make que lo lee para ejecutar sus instrucciones y compilar las funciones en los archivos fuente y generar archivos objetos.
❒ Estos se linkean para y así generar un archivo ejecutable.
❒ El archivo Makefile también se puede nombrar de otra forma (e.g. hola.mk) pero de ser así make tiene que ser invocado incluyendo el nombre con la opción –f (e.g. make –f hola.mk)
1: Intro 14
Tipos de datos básicos
❒ Durante el curso de esta clase vamos a usar el lenguaje “C” para demostrar y desarrollar los diferente algoritmos a estudiar.
❒ C tiene ciertos tipos de datos básicos (standard data types) que se utilizan para construir todas las estructuras mas complejas:
❍ Enteros (int)
❍ Reales (float)
❍ Reales de doble tamaño (double)
❍ Caracteres (char)
1: Intro 15
Tipos de datos básicos y modificadores (cont)
❒ Veamos un programa que imprime estos tipos:
#include <stdio.h>
int main(void)
{
int i=5;
float j=6.0;
char c='t';
printf("i=%d, j=%f, c=%c, str=%s ", i, j, c, “hello”);
return 0;
}
1: Intro 16
Tipos de datos básicos y modificadores
❒ short y long aplican a integers
❍ short int es tipicamente 16 bits y long int 32 bits,
❍ signed y unsigned pueden ser aplicados a char o a cualquier integer.
❒ El tipo long double es un real de precisión doble.
❒ Tambien existe long long en algunas implementaciones.
❒ Estas definiciones dependen del procesador y el compilador que se esta usando.
❒ El tamaño de los tipos esta definido en ANSI (AmericanNational Standards Institute) C en los archivos <limits.h> y <float.h>.
1: Intro 17
Tipos de datos básicos y modificadores (cont)
$ /usr/include$ more limits.h
/* Copyright (C) 1991, 92, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library....*/
/*…Define ANSI <limits.h> for standard 32-bit words. */
/* These assume 8-bit `char's, 16-bit `short int's, and 32-bit `int's and `long int's. */
/* Number of bits in a `char'. */
# define CHAR_BIT 8
/* Minimum and maximum values a `signed char' can hold. */
# define SCHAR_MIN (-128)
# define SCHAR_MAX 127
/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
# define UCHAR_MAX 255
1: Intro 18
Tipos de datos básicos y modificadores (cont)
❒ Los numeros de bits se pueden verificar con un programa:
$ cat types.cc
#include <stdio.h>
main()
{
/* signed types */
int max = (int)((unsigned int) ~0 >> 1); //~0 = all 1s, >> 1 -> 0111…
int min = -max-1;
printf("signed int max = %d\n", max);
printf("signed int min = %d\n", min);
/* unsigned types */
printf("unsigned int max = %u\n", (unsigned int) ~0 );
}
$ types
signed int min = -2147483648
signed int max = 2147483647
unsigned int max = 4294967295
1: Intro 19
Tipos de datos básicos y modificadores (cont)
❒ Un tipo de dato (data type) es un set de valores y una colección de operaciones (funciones) sobre estos (de acuerdo a Sedgewick).
❒ El tipo de operaciones que se hacen con tipos de datos (operandos) dependen de los tipos de datos.
❒ En el caso de ints las operaciones validas son diferentes de las que son para otros tipos como chars.
❒ Esta definición de tipo de data es una extensión del concepto tradicional de K&R de tipo de data en el cual solo se consideran los tipos de valores y no se incluían las operaciones.
1: Intro 20
Lenguajes orientados a objetos
❒ C no es intrínsicamente un lenguaje orientado a objetoscomo C++ o Java pero se pueden usar estructuras para tratar de trabajar en un ambiente mas parecido al de objetos (object oriented programming o OOP).
❒ En general cuando sea necesario (y posible) C hace conversión implícita de un tipo de dato a otro.
1: Intro 21
Conversión implícita de un tipo a otro
❒ Ejemplo de un cast implícito:
/* Hacer una suma de dos short ints y asignar el resultado a un int. */
short int k, n; /* definir variables de origen (16 bits)*/
int z; /* definir variables de destino (32 bits)*/
k=10; n=15; /* inicializar valores */
z= k + n; // k y n tienen que se extendidos, z va a ser // igual a 25
❒ Muchas veces se requiere hacer una conversión de tipo explicita, para eso se hace una operación explicita de conversión de tipo (cast operation).
1: Intro 22
Conversión implícita de un tipo a otro (cont)
❒ Es mejor evitar el uso de las conversiones explicitas en lo posible ya que no es considerada como la mejor practica de programación (es fácil no notar el uso de un cast que puede tener importantes consecuencias en un programa).
❒ Si se desea un nuevo tipo de datos es muchas veces mejor definir la variable con ese tipo desde un principio, obviamente que hay muchas veces que una conversión (o conversión implícita) es simplemente lo mas conveniente y claro como práctica.
❒ Si se usa un cast es siempre bueno un comentario indicando que se esta usando.
1: Intro 23
Conversión implícita de un tipo a otro (cont)
❒ Ejemplo de cast:
int k, n;
float z;
k=10; n=15; /* inicializar valores */
z= ((float) k) / n; /* cast convierte k a float */
/* cual es el valor final de z ? */
1: Intro 24
1-Introducción
1.1 Background
1.2 Estructuras y tipos de datos básicos
1.3 Typedefs, estructuras y unión
1.4 Arreglos, malloc y punteros
1: Intro 25
Typedefs
❒ Se usa la definición de nuevos tipos de datos para poder abstraer la lógica importante de los aspectos mas mundanos de nuestros programas.
❒ En C se usa el typedef para definir nombres a tipos de datos existentes (i.e. como un sinónimo) (ver K&R 6.7).
1: Intro 26
Typedefs❒ Ejemplo de typedef:typedef int Number;
Number function1(intvalue)
{
return value;
}
int main(void)
{
int k=10;
int j=0;
j=function1(k)+3;
printf("j=%d\n",j);
return 0;
}
1: Intro 27
Typedefs y estructuras
❒ Una estructura (struct) en C es una colección de variables agrupados bajo un nombre.
❒ Las estructuras son usadas para organizar y agrupar diferentes tipos de datos (ver ejemplos pixel y pixel2).
struct pix { short int x;short int y;int color;
}struct pix mi_pixel;
❒ Se puede acceder a miembros con un . o una ->mi_pixel.x;
1: Intro 28
Unión
❒ La unión es una variable que puede conteneren diferentes ocasiones objetos de diferentes tipos y tamaños, el compilador se preocupa del mantener los requerimientos de espacio y alineamiento en la unión.
❒ Las uniones nos permiten manipular diferente tipos de data en una sola área y ahorrar espacio en la memoria.
❒ Ejemplo (K & R cap. 6.8):union u_tag {
int ival;float fval;char *sval;
} u;
1: Intro 29
Unión (cont)
❒ La variable u va a ser lo suficientemente grandecomo para almacenar un entero, un real o un punteroa caracteres.
❒ Para acceder a los miembro se usa el sintax:
❍ nombre-union.miembro o puntero-union->miembro
❒ En el caso de u_tag seria de esta manera:
u.ival,
u.fval,
u.sval.
1: Intro 30
1-Introducción
1.1 Background
1.2 Estructuras y tipos de datos básicos
1.3 Typedefs, estructuras y unión
1.4 Arreglos, malloc y punteros
1: Intro 31
Arreglo
❒ El arreglo es un tipo básico de datos que es un primitivo de muchos lenguajes de programación incluyendo C.
❒ El arreglo es una colección de un numero fijo de elementos del mismo tipo.
❒ Los arreglos son estructuras fundamentales que son almacenados contiguamente en memoria y que son accesibles por un índice (entero).
1: Intro 32
Arreglo (cont)
❒ En C los arreglos comienzan con el índice 0 y es responsabilidad del programador que el índice no sea negativo.
❒ También el índice usado en el programa debería ser menor que el tamaño del arreglo o se van a causar condiciones erróneas de ejecución en el programa.
❒ Estos errores muchas veces causan excepciones ya que el programa se estaría refiriendo a áreas de memoria que posiblemente esta fuera de demarcación.
1: Intro 33
Arreglo (cont)
/* Definir e inicializar */
int i=0;
pixel pix_array[5];
for (i=0; i < 5 ;i++)
{
pix_array[i].x=100;
pix_array[i].y=100 + i;
pix_array[i].color=0;
}
/* Mandar a una función paramostrar los pixels en la pantalla */
for (i=0 ; i < 5 ; i++)
{
rc = mstrar( pix[i] );
}
1: Intro 34
Punteros
❒ En C también se puede usar la asignación dinámica de memoria (usando punteros y malloc/calloc) para variar la cantidad de memoria asignado en el arreglo.
❒ Un puntero es una variable que apunta a un objeto en memoria, un puntero debería ser inicializado para que apunte a NULL si no apunta a ningún objeto.
❒ Ejemplo:
/* Definir puntero a pixel y usar malloc para inicializar */
pixel *ppix = NULL;
ppix = (pixel *) malloc(sizeof(pixel));
1: Intro 35
Punteros (cont)
❒ Una vez creado el puntero e inicializado con memoria se puede acceder a los contenidos deseados del puntero con el * o con la -> (usando *puntero.contenido o puntero->contenido)
❒ También se puede obtener la dirección de nuestro puntero (o cualquier objeto) usando &.
❒ *(a+i) y a[i] son equivalentes (Sedgewick 3.2, p.84, K&R 5.3).
1: Intro 36
Punteros (cont)
❒ Ejemplo:
pixel *ppix = (pixel *) malloc(sizeof(pixel));
/* Inicializar contenidos de nuestro pixel */
ppix->x = 100;
ppix->y = 150;
(*ppix).color = 0; /* Equivale ppix->color = 0 */
1: Intro 37
Punteros (cont)
❒ Generalmente cuando se usa malloc también se debería usar free. Esto es porque cuando se usa malloc para asignar memoria es necesario liberar esa memoria usando free.
❒ Si no se hace esto entonces hay un memory leak (fuga de memoria) en nuestro programa.
❒ Esto puede llevar a un core dump (excepción) o a otra condición errónea como que el computador opere lentamente por falta de memoria real (v/s el uso del disco duro como memoria virtual).
1: Intro 38
Punteros (cont)
❒ Ejemplo:
/* Definir un puntero y usar malloc para inicializar */
pixel *ppix = (pixel *) malloc(sizeof(pixel));
/* Hacer lo que queramos con nuestro puntero y objeto */
/* Liberar la memoria y marcar puntero como libre */
free(ppix);
ppix = NULL;