Estructura de Datos

Download Report

Transcript Estructura de Datos

Programación Científica
Dr. Romeo Sánchez Nigenda.
E-mail: [email protected]
http://yalma.fime.uanl.mx/~romeo/
Oficina: 1er. Piso del CIDET. Oficina con Dr. Oscar Chacón
Horas de Tutoría: 10am-11am Martes y Jueves
Website: http://yalma.fime.uanl.mx/~romeo/Prog/
Sesiones: 48
* Slides aumentados con información de Dr. Roger Ríos, y Dr.
Fernando López
Temario:
1.
2.
3.
4.
5.
6.
7.
40% Proyecto
30% Examen Parcial
30% Examen Final
10% Participación
Fundamentos de Programación en C
Apuntadores y Funciones
Arreglos y Estructuras
Manejo de Memoria
Recursividad
Entrada y Salida de Archivos
Desarrollo y Depuración de Proyecto de
Programación
Total a calificar: 110 puntos!
Material de apoyo:
A. KELLY, I. POHL. A Book on C. Addison-Wesley, Reading, EUA, 1998.
2. B. KERNIGHAN, D. RITCHIE. The C Programming Language. Prentice Hall,
Second Edition, 1988.
3. D. KNUTH. The Art of Computer Programming. Addison Wesley, 1998.
4. H. DEITEL, P. DEITEL. Como Programar en C/C++. Prentice Hall, Segunda
Edición. 1995.
5. L. Joyanes, I. Zahonero. Programación en C - Metodología, Algoritmos y Estructura de
Datos. McGraw Hill-Interamericana, 2006.
6. B. Stroustrup. The C++ Programming Language. Addison Wesley. Third Edition.
1997.
Software:
Compiladores GCC (GNU Compiler Collection)
IDEs (Integrated Development Environment):
http://www.eclipse.org/downloads/
http://kdevelop.org/
http://www.bloodshed.net/devcpp.html
Recursión

Objetivo: El alumno comprenderá la representación y
manejo de datos en forma recursiva

Temario:
◦ Definición
◦ Ejemplos
 Factorial de un número
 Serie de Fibonacci
 Cálculo de una inversión
◦ Funcionamiento interno de la recursión
◦ Uso de pilas para simular recursión
Recursividad

Es la forma en la cual se especifica un proceso basado en su propia
definición. Es evidente que el proceso especificado debe terminar
con un resultado definido.

Un problema que pueda ser definido en función de su tamaño, sea
este N, puede ser dividido en instancias más pequeñas del mismo
problema, aplicándose inducción sobre las más pequeñas para
resolver el problema en general.

Ejemplo: Función Factorial n!
◦ Dado un entero positivo n, se define al factorial de n como el producto de todos
los enteros entre n y 1.
◦ Por ejemplo el factorial de 5 = 5 * 4 * 3 * 2 * 1 = 120
◦ Entonces:
n! = 1 if n==0
Otra manera n! = n * (n – 1) * (n – 2) … * 1 si n>0
Factorial

Solución iterativa:
prod = 1
for(int x = n; x > 0; x++) {
prod *= x;
}
return prod;

Características de una función factorial
0! = 1
1! = 1 * 0!
2! = 2 * 1!
3! = 3 * 2!
…
n! = n * (n-1)!
Factorial y Funcionamiento Interno

Siguiendo nuestra definición, el factorial de 5! es:
1. 5! = 5 * 4!
Internamente, las funciones recursivas
2.
3.
4.
5.
6.
Cualquier
referencia a
una variable
local se hace
través del
tope de la pila
utilizan
pilas
para
4! = 4 * 3!
generaciones sucesivas
locales y parámetros.
3! = 3 * 2!
2! = 2 * 1!
1! = 1 * 0!
0! = 1
mantener las
de variables
Cada vez que se introduce una función recursiva se agrega
al tope de la pila una nueva asignación de sus variables.
6.
5.
4.
3.
2.
1.
0! = 1,
1! = 1 * 1 = 1
2! = 2 * 1 = 2
3! = 3 * 2 = 6
4! = 4 * 6 = 24
5! = 5 * 24 = 120
old
new
Cuando retorna la función, se remueve la
pila, se libera la asignación en el tope, y la
asignación previa se convierte en el tope
actual de la pila.
Factorial

Función Recursiva
int factorial(int n) {
if (n == 0) return 1;
else if(n<0) return 0; //Error no existe factorial de números negativos
return n * factorial(n – 1);
}

Multiplicación de Números Naturales

El producto a * b se define como a sumado a sí mismo b veces, es decir:
a * b = a if b==1
a * b = a * (b – 1) + a if a>1
5 * 3 = 5 * 2 + 5 = 5 * 1 + 5 + 5 = 5 + 5 + 5 = 15
int natural(int a, int b){
if(b == 1)
return a;
else
return natural(a, b-1) + a;
}
Secuencia Fibonacci

Secuencia de enteros en la que cada elemento en la
secuencia es la suma de los dos elementos anteriores
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, … donde fib(0) = 0, y fib(1) = 1

Definición recursiva
Fib(n) = n if n==0 || n==1
Fib(n) = Fib(n-2) + Fib(n-1) if (n>=2)
Ejemplo:
Fib(6) = Fib(4) + Fib(5) = Fib(2) + Fib(3) + Fib(5) = Fib(0) + Fib(1) + Fib(3) + Fib(5) =
0 + 1 + Fib(3) + Fib(5) = 1 + Fib(1) + Fib(2) + Fib(5) = 1 + 1 + Fib(0) + Fib(1) + Fib(5) =
1 + 1 + 0 + 1 + Fib(5) = 3 + Fib(5) = 3 + Fib(3) + Fib(4) = 3 + Fib(1) + Fib(2) + Fib(4) =
3 + 1 + Fib(0) + Fib(1) + Fib(4) = 4 + 0 + 1 + Fib(4) = 5 + Fib(2) + Fib(3) =
5 + Fib(0) + Fib(1) + Fib(3) = 5 + 1 + Fib(3) = 6 + Fib(1) + Fib(2) = 6 + 1 + Fib(2) =
7 + Fib(0) + Fib(1) = 8
Secuencia Fibonacci

Algoritmo iterativo
int lfib=0, hfib=1, x;
for(int i=2;i<=n;i++){
x = lfib;
lfib = hfib;
hfib = x+lfib;
}
return hfib;

Algoritmo Recursivo
int fibonacci(int n){
if (n == 0 || n == 1) {
return n;
}
return fibonacciR(n - 1) + fibonacciR(n - 2);
}
Búsqueda Binaria
Considere un conjunto de elementos ordenados
 La búsqueda secuencial checaría elemento por elemento

2
5
8
9
10
20
25
33
45
80
32?
La búsqueda binaria reduce los elementos a buscar por la mitad al
considerar la primera mitad del arreglo si el elemento a buscar es menor
que el elemento intermedio, o la segunda mitad si es mayor
0
2
min
intermedio
5
8
9
10
20
25
N-1
33
45
>
<
32?
A considerar
80
max
Búsqueda Binaria
0
2
5
min
8
9
10
20
25
33
5
8
9
10
Descartados!
80
(Min+max) /2
max
4
80
7
A considerar
20
25
33
45
min
max
<
A considerar
2
intermedio
45
>
<
32?
2
N-1
intermedio
5
8
9
10
20
25
min
max
32?
>
>
32?
33
45
80
5
Búsqueda Binaria
int busqueda_binaria(int a[], int min, int max, int elem){
//No encontramos el elemento cuando los dos extremos se cruzan
if(min>max)
return -1;
//Index intermedio
int pivote = (int)(min+max)/2;
//Regresa el intermedio si es igual que el elemento que busco
if(elem == a[pivote])
return pivote;
if(elem < a[pivote])
return busqueda_binaria(a,min, pivote-1, elem);
else
return busqueda_binaria(a,pivote+1, max, elem);
}
Propiedades de un algoritmo recursivo

Para que sea correcto no debe generar una secuencia
infinita. Debe definirse una función recursiva f en términos
que no implique f para algunas secuencias

Ejemplos:
 Factorial: 0! =1
 Fibonacci: fib(0) = 0, fib(1) = 1
 Búsqueda Binaria: if(min>max) return -1; if(elem==a[pivote]) return pivote;

Definir una función recursiva en términos de casos más
simples. Por ejemplo, el factorial de un número n! puede
definirse como n * (n-1)!
Simulación de recursión usando pilas
Motivación:

Algunos lenguajes de programación (como
Fortran y Cobol) no permiten funciones
recursivas.

En muchos casos, una solución recursiva es
más costosa que una no recursiva, tanto en
términos de tiempo como de espacio.
Simulación de recursión usando pilas

Qué sucede cuando se llama a una función?
1.
2.
3.

Que sucede cuando retorna una función?
1.
2.
3.

Se pasan argumentos
Asignan e inicializan variables locales
Establecer el control de la función (dirección de retorno)
Se recupera dirección de retorno
Se libera el área de datos de la función (e.g., variables locales)
Se restablece el control para la rutina que llama y se guardan
valores de retorno de la función
Note que la cadena de direcciones de retorno forma una pila. Es decir, la
dirección de retorno más reciente es la primera que se remueve de la
cadena, y únicamente podemos acceder a la dirección de retorno
dentro de la que se ejecuta la función (el tope)
Simulación de recursión usando pilas

Ejemplo: Factorial(n)
Versión simulada con Pilas
Versión Recursiva
int factorial(int n) {
if (n == 0) return 1;
return n * factorial(n – 1);
}
Recursión
Encadenamiento
int simfactorial(int n) {
struct stack s;
int x = n;
long int prod;
s.top = -1;
while (x != 0) {
push(&s, x--);
}
prod = 1;
while (s.top >= 0) {
prod *= pop(&s);
}
return prod;
}