Академический Документы
Профессиональный Документы
Культура Документы
2 Algoritmos iterativos
2.1 Búsqueda
ALGORITMO BúsquedaLineal
CONSTANTES
MaxElementos : ENTERO = 100
TIPOS
Vector = vector[MaxElementos] de ENTERO
i ← i + 1
FIN_MIENTRAS
SI v[ i ] = numBuscado
busquedaLineal ← i
SINO busquedaLineal ← -1
FIN_FUNCION
VARIABLES
v: Vector
num: ENTERO
pos: ENTERO
INICIO
{ Preparar el vector }
DESDE i ← 0 HASTA MaxElementos - 1
v[ i ] ← i * 2
FIN_DESDE
{ Buscar }
LEER( num );
pos = busquedaLineal( v, num, MaxElementos );
{ Informar}
SI pos > -1
ESCRIBIR( “Encontrado en “, pos )
SINO ESCRIBIR( “No encontrado” )
FIN_ALGORITMO
// Algoritmo BúsquedaLineal
#include <cstdio>
while( v[ i ] != numBuscado
&& i < numElem )
{
++i;
}
if ( v[ i ] == numBuscado)
return i;
else return -1;
}
int main()
{
int i;
int num;
int pos;
int v[MaxElementos];
// Preparar el vector
for(i = 0; i < MaxElementos; ++i) {
v[ i ] = i * 2;
}
// Informar
if ( pos > -1 )
printf( "\nEncontrado en %d.\n", pos );
else printf( "\nNo encontrado.\n" );
return 0;
}
2.1.2 Búsqueda binaria
La búsqueda binaria consiste en, dado un vector, comprobar la mitad del vector, con lo que, según
el elemento a buscar, estará en una de las mitades. Este proceso se repite con la mitad donde esté el
elemento, comprobando si el medio es el elemento buscado, y así sucesivamente hasta encontrarlo
(de estar). Ésto implica una limitación básica para que este algoritmo pueda funcionar: el vector
tiene que haberse ordenado previamente, sus elementos deben estar ordenados para poder elegir la
mitad correcta en la que buscar a continuación. Como el algoritmo anterior, devuelve la posición o
-1 en caso contrario.
ALGORITMO BúsquedaBinaria
CONSTANTES
MaxElementos : ENTERO = 100
TIPOS
Vector = vector[MaxElementos] de ENTERO
SI v[ medio ] = numBuscado
busquedaLineal ← medio
SINO busquedaLineal ← -1
FIN_FUNCION
VARIABLES
v: Vector
num: ENTERO
pos: ENTERO
INICIO
{ Preparar el vector }
DESDE i ← 0 HASTA MaxElementos - 1
v[ i ] ← i * 2
FIN_DESDE
{ Buscar }
LEER( num );
pos = busquedaBinaria( v, num, MaxElementos );
{ Informar}
SI pos > -1
ESCRIBIR( “Encontrado en “, pos )
SINO ESCRIBIR( “No encontrado” )
FIN_ALGORITMO
El funcionamiento del algoritmo es obvio: primero se le da al vector de enteros valores
iniciales, y después se le pide un número al usuario. Si la búsqueda binaria devuelve -1, entonces es
que no se encontró; en otro caso, se devuelve la posición en la que se encontró.
A continuación, se incluye la implementación en C++ estructurado de este algoritmo.
#include <cstdio>
if ( v[ medio ] == numBuscado)
return medio;
else return -1;
}
int main()
{
int i;
int num;
int pos;
int v[MaxElementos];
// Preparar el vector
for(i = 0; i < MaxElementos; ++i) {
v[ i ] = i * 2;
}
// Informar
if ( pos > -1 )
printf( "\nEncontrado en %d.\n", pos );
else printf( "\nNo encontrado.\n" );
return 0;
}
2.2 Ordenación
ALGORITMO OrdenaciónPorInserción
CONSTANTES
MaxElementos : ENTERO = 100
TIPOS
Vector = vector[MaxElementos] de ENTERO
{ Preparar el vector }
DESDE i ← 0 HASTA MaxElementos - 1
v2[ i ] ← v[ i ]
FIN_DESDE
{ Insertar ordenadamente }
DESDE i ← 0 HASTA numElem – 1
{ buscar la pos }
j ← 0
MIENTRAS j < numOcupados
Y v[ i ] > v2[ j ]
j ← j + 1
FIN_MIENTRAS
{ desplazar el vector }
DESDE k ← numOcupados HASTA j
v[ k + 1 ] = v[ k ];
FIN_DESDE
VARIABLES
v: Vector
num: ENTERO
pos: ENTERO
i: ENTERO
INICIO
{ Preparar el vector }
DESDE i ← 0 HASTA MaxElementos
SI ( ( i mod 2 ) == 0 )
v[ i ] ← i / 2;
SINO v[ i ] ← i * 2
FIN_DESDE
{ Ordenar }
LEER( num );
ordenaInsercion( v, MaxElementos );
{ Informar }
DESDE i ← 0 HASTA MaxElementos
ESCRIBIR( v[ i ] )
FIN_DESDE
FIN_ALGORITMO
// Algoritmo OrdenaciónPorInserción
#include <cstdio>
// Insertar ordenadamente
for(posVorg = 0; posVorg < numElem; ++posVorg) {
// buscar la pos
posOrd = 0;
while ( posOrd < numOcupados
&& v2[ posVorg ] > v[ posOrd ] )
{
++posOrd;
}
// desplazar el vector
for(posDesp = numOcupados; posDesp >= posOrd; --posDesp) {
v[ posDesp + 1 ] = v [ posDesp ];
}
return;
}
int main()
{
int i;
int num;
int pos;
int v[MaxElementos];
// Preparar el vector
for(i = 0; i < MaxElementos; ++i) {
if ( ( i % 2 ) == 0 )
v[ i ] = 120 + ( i / 2 );
else v[ i ] = 120 + ( i * 2 );
}
// Informar
for(i = 0; i < MaxElementos; ++i) {
printf( "%d ", v[ i ] );
}
printf( "\n" );
return 0;
}
● 1: factorial( 4 )
○ 2: factorial( 3 )
■ 3: factorial( 2 )
● 4: factorial( 1 )
Así, la multiplicación de tres por cuatro supondría las siguientes llamadas recursivas (los
valores entre corchetes son las operaciones que se realizan una vez llegados hasta la base de la
recursión):
● multiplicacion( 3, 4 ) = 3 + multiplicacion( 3, 3 ) [=3 + 6]
○ multiplicacion( 3, 3 ) = 3 + multiplicacion( 3, 2 ) [= 3 + 6]
■ multiplicacion( 3, 2 ) = 3 + multiplicacion( 3, 1 ) [= 3 + 3]
● multiplicacion( 3, 1 ) = 3 + multiplicacion( 3, 0 ) [= 3 + 0]
○ multiplicacion( 3, 0 ) [= 0]
La programación del algoritmo en C++ estructurado es prácticamente directa:
5 10 15 20
En cursiva se marcan los valores que se retornan después del retorno del caso base. ¿Qué
sucedería si el elemento a buscar fuese el 11?
Nótese que al ser división entera (puesto que los miembros de la expresión son enteros), el
resultado de dividir 1 / 2 es 0.
A continuación, se incluye el código fuente en C++ estructurado:
// Algoritmo BusquedaBinariaRecursiva
#include <cstdio>
if ( v[ medio ] != numBuscado ) {
if ( medio == bajo ) {
medio = -1;
} else {
if ( numBuscado > v[ medio ] )
bajo = medio;
else alto = medio;
return medio;
}
int main()
{
int i;
int num;
int pos;
int v[MaxElementos];
// Preparar el vector
for(i = 0; i < MaxElementos; ++i) {
v[ i ] = i * 2;
}
// Informar
if ( pos > -1 )
printf( "\nEncontrado en %d.\n", pos );
else printf( "\nNo encontrado.\n" );
return 0;
}
4 Conclusiones
En este tema se han visto algoritmos básicos de búsqueda y ordenación, a la vez que se ha
introducido la recursividad. Tal y como se ha visto, el resultado es el mismo en ambos casos, sea el
algoritmo recursivo o iterativo, y su eficiencia teórica no cambia.
Un factor que sí se debe tener en cuenta es que el algoritmo recursivo supone realizar
llamadas a funciones en lugar de iteraciones de bucles, y en general lo primero es bastante más
complejo, y consume más recursos (como memoria en la pila de llamadas) que lo segundo.
Siendo así, es posible plantearse siquiera la necesidad de utilizar algoritmos recursivos. Las
ventajas de estos algoritmos no radican en su eficiencia, sino en la superior abstracción que se
obtiene con ellos (es decir, el diseño de ciertos algoritmos complejos se hace más sencillo).
Supóngase el siguiente ejemplo: una calculadora debe evaluar expresiones como (6+(5*4)) / 2, de
manera que siempre haya una pareja de paréntesis antes de cada subexpresión, y no se incluyan
espacios. Por supuesto este problema se puede resolver de manera iterativa, pero de manera
recursiva la solución es mucho más simple, como se puede ver a continuación:
ALGORITMO Calculadora
FUNCION calcular(E operando1: ENTERO, operador: CARACTER, operando2: ENTERO) :
ENTERO
VARIABLES
resultado: ENTERO
INICIO
{ Prec. Operador = '*' O '/', O '+' O '-' }
CASO DE operador
'*': resultado ← operando1 * operando2
'/': resultado ← operando1 / operando2
'+': resultado ← operando1 + operando2
'-': resultado ← operando1 – operando2
FIN_CASO
calcular ← resultado
FIN_FUNCION
{ tomar operador }
operador = expresion[ pos ]
pos ← pos + 1
VARIABLES
entrada: CADENA
INICIO
LEER( entrada );
ESCRIBIR( resultado, evaluarExpresion( entrada ) )
FIN_ALGORITMO