Está en la página 1de 20

RECURSIVIDAD

DEFINICION: El concepto de recursividad es un concepto muy abstracto y


complejo que tiene que ver tanto con la lógica como también con la matemática
y otras ciencias. Podemos definir a la recursividad como un método de definir
un proceso a través del uso de premisas que no dan más información que el
método en sí mismo o que utilizan los mismos términos que ya aparecen en su
nombre, por ejemplo, cuando se dice que la definición de algo es ese algo
mismo.

La recursividad tiene como característica principal la sensación de infinito, de


algo que es continuo y que por tanto no puede ser delimitado en el espacio o el
tiempo porque se sigue replicando y multiplicando de manera lógica y
matemática. Así, es común encontrar casos de recursividad por ejemplo
en imágenes de espejos que hacen que la imagen sea replicada al infinito, una
dentro de otra hasta que deja de verse pero no por eso deja de existir. Otro
caso típico de recursividad en las imágenes es cuando encontramos
una publicidad en la que el objeto tiene la propaganda de sí mismo en su
etiqueta y así al infinito, o cuando una persona está sosteniendo una caja de un
producto en cuya etiqueta aparece esa misma persona sosteniendo el mismo
producto y así hasta el infinito. En estos casos, la recursividad pasa por el
hecho de que se busca definir algo con lo misma información que ya se tiene.
Lo importante a recordar es que la recursividad está presente no sólo en la
imagen sino también en las palabras, en el lenguaje. Así, la recursividad se
observa cuando se usan frases o expresiones iguales con diferentes
estructuras jerárquicas cuando en realidad el significado final de la expresión
no termina saliéndose de esas expresiones o palabras mencionadas. Un
ejemplo muy claro de esto es cuando hablamos de recursividad y decimos
"Para entender a la recursividad, primero debes entender qué es la
recursividad". En sí, la frase no nos otorga más información porque recurre una
y otra vez a los mismos datos, generando una sensación de infinito como lo
que se mencionó con las imágenes.
5.6. Recursividad
Definici�n

Se dice que una funci�n es recursiva cuando dentro de su bloque de


sentencias hay una llamada a la propia funci�n.
En principio cualquer funci�n puede hacerse una llamada a s� misma, sin
embargo tiene que estar especialmente dise�ada para que funcione
correctamente, ya que al llamarse a s� misma provoca que �sta se vuelva a
ejecutar, y dentro de sus instrucciones se vuelve a llamar, creando un bucle
que si no est� controlado se vuelve infinito.
Por lo tanto una funci�n recursiva forma un bucle al ser llamada a si misma.
Este bucle debe ser controlado de alguna manera para poder salir de �l y no
caer en estructuras indeseadas como bucles infinitos o estructuras que se
autorreplican indefinidamente.

Recursividad condicionada: ejemplo 1


La forma m�s simple de hacer que una funci�n recursiva no cree un bucle
infinito es hacer que la llamada a s� misma est� dentro de una estructura
condicional. De esta forma s�lo si se cumplen ciertas condiciones la
ejecuci�n de la funci�n se repite.
El siguiente ejemplo pide al usuario que pulse una tecla num�rica. Mediante
una funci�n comprobamos la tecla pulsada. Si esta es un numero se sale de la
funci�n, pero si no lo es vuelve a pedir que se pulse una tecla, se llama a s�
misma para volver a comprobarlo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
using namespace std;
void comprobar(char r);

int main(){
char c;
cout << "Pulsa un numero : ";
cin >> c;
comprobar(c);
cout << "Programa terminado." << endl;
}

void comprobar(char r){


int n=int(r);
if (n>=48 and n<=57) {
cout << "Correcto, la tecla pulsada es un numero." << endl;
}
else {
cout << "Incorrecto, la tecla pulsada NO es un numero." << endl;
cout << "Vuelve a pulsar un numero : ";
cin >>r;
comprobar(r);
}
}
El programa tiene una funci�n recursiva, la cual crea un bucle del que no se
sale hasta que el usuario pulsa una tecla num�rica.
Observa c�mo la llamada a la funci�n dentro de la misma est� dentro de una
estructura condicional. Cuando se cumplen las condiciones marcadas por la
condicional se sale del bucle, si no se cumplen, la funci�n vuelve a repetirse.

Recursividad: ejemplo 2
En este ejemplo vamos a hacer que el usuario escriba una frase y nosotros la
repetimos un determinado n�mero de veces.
Evidentemente ser�a mucho m�s f�cil resolver el problema utilizando un
bucle, pero aqu� se trata de ver c�mo se puede resolver tambi�n mediante
una funci�n recursiva. Veamos el ejemplo :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
using namespace std;

void escribir(string frase, int n);

int main(){
string f;
int n=5;
cout << "Escribe una frase. Yo la repetire 5 veces." << endl;
getline(cin, f);
cout << endl;
escribir(f,n);
}

void escribir(string frase, int n){


cout << n << " : " << frase << endl;
n--;
if (n>0) escribir(frase,n);
}
Observa como tenemos un n�mero de control, n que en cada llamada va
disminuyendo en una unidad.
A su vez el hecho de que se produzca o no la siguiente llamada a la funci�n
depende de que el n�mero sea mayor que cero, por lo que cuando el n�mero
alcnce el cero, la funci�n dejar� de autorreplicarse.

Otro ejemplo: calcular factorial


El factorial de un n�mero se define como la multiplicaci�n de ese n�mero por
todos los que son menores que �l. S�lo los n�meros naturales (enteros
positivos) pueden tener factorial. Por ejemplo, el factorial de 4 se define como
4*3*2*1. El factorial de 6 es 6*5*4*3*2*1.
Matem�ticamente la operaci�n factorial se define escribiendo un signo de
admiraci�n detr�s del n�mero: 4! = 4*3*2*1.
Por lo tanto los n�meros negativos no tienen factorial, y adem�s el factorial
de cero es 1.
Con todo esto vamos a hacer una funci�n recursiva que calcule el factorial de
un n�mero. El programa ser� el siguiente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;

int factorial(int n);

int main(){
int n, r;
cout << "FACTORIAL : Escribe un numero : ";
cin >> n;
r=factorial(n);
cout << n << "! = " << r << endl;
}

int factorial(int n) {
if(n < 0) return 0;
else if(n > 1) return n*factorial(n-1); // Recursividad: n>1
return 1; // Condici�n para n == 1 y n == 0
}
El programa calcula el factorial del n�mero. Para n�meros negativos
devuelve el cero. Para el 0 y el 1 devuelve el 1, y para los dem�s n�meros
positivos, mediante la recursividad, vamos multiplicando cada n�mero por el
inmediatamente menor que si mismo hasta llegar a uno, para devolver el
factorial.

Recursividad en C++
lunes, 19 de marzo de 2012
Recursividad en C++
Recursividad en C++:

La recursividad es una técnica de programación elemental que permite que una


función pueda llamarse asimismo desde la misma función. Se puede utilizar la
recursividad como una alternativa a la iteración. La recursividad es una
herramienta poderosa e importante en la resolución de problemas en
programación. Una solución recursiva es normalmente menos eficiente en
términos de tiempo de computadora que una solución iterativa debido a las
operaciones auxiliares que llevan consigo las llamadas suplementarias a las
funciones: sin embargo, en muchas circunstancias el uso de la recursión
permite a los programadores especificar las soluciones naturales, más lógicas,
elegantes, sencillas, que serían, en caso contrario difícil de resolver.

No todas las funciones pueden llamarse a sí mismas, sino que deben estar
diseñadas especialmente para que sean recursivas, de otro modo podrían
conducir a bucles infinitos, o a que el programa termine inadecuadamente.
Tampoco todos los lenguajes de programación permiten usar recursividad. C++
permite la recursividad.

Cada vez que se llama a una función, se crea un juego de variables locales, de
este modo, si la función hace una llamada a sí misma, se guardan sus
variables y parámetros, usando la pila, y la nueva instancia de la función
trabajará con su propia copia de las variables locales. Cuando esta segunda
instancia de la función retorna, recupera las variables y los parámetros de la
pila y continúa la ejecución en el punto en que había sido llamada.

Por ejemplo para calcular el factorial de cualquier número mayor que cero hay
que calcular como mínimo el factorial de otro número. La función que se utiliza
es la función en la que se encuentra en estos momentos, esta función debe
llamarse a sí misma para el número menor inmediato, para poder ejecutarse en
el número actual. Esto es un ejemplo de recursividad.
De esta forma podríamos crear una función recursiva para calcular el factorial
de un número entero.

El factorial se simboliza como n!, se lee como "n factorial", y la definición es:

n! = n * (n-1) * (n-2) * ... * 1

Hay algunas limitaciones:

No es posible calcular el factorial de números negativos, no está definido.

El factorial de cero es 1.

De modo que una función bien hecha para cálculo de factoriales debería incluir
un control para esos casos:

/* Función recursiva para cálculo de factoriales */


int factorial(int n) {
if(n < 0) return 0;
else
if(n > 1) return n*factorial(n-1); /* Recursividad */
return 1; /* Condición de terminación, n == 1 */
}
Veamos paso a paso, lo que pasa cuando se ejecuta esta función, por ejemplo:
factorial (4):
1aInstancia
n=4
n>1
salida ← 4 * factorial (3) (Guarda el valor de n = 4)
2aInstancia
n>1
salida ← 3*factorial (2) (Guarda el valor de n = 3)
3aInstancia
n>1
salida ← 2*factorial (1) (Guarda el valor de n = 2)
4aInstancia
n == 1 → retorna 1
3aInstancia
(recupera n=2 de la pila) retorna 1*2=2
2aInstancia
(recupera n=3 de la pila) retorna 2*3=6
1aInstancia
(recuperan=4delapila)retorna6*4=24
Valor de retorno → 24
Aunque la función factorial es un buen ejemplo para demostrar cómo funciona
una función recursiva, la recursividad no es un buen modo de resolver esta
función, que sería más sencilla y rápida con un simple bucle for.
Una función recursiva tiene generalmente dos partes:
1) Una llamada recursiva con parámetros más sencillos.
2) Una parte de terminación que detiene la recursividad.

Principios de la recursividad:

La recursividad es una de las formas de control más importantes en la


programación. Los procedimientos recursivos son la forma más natural de
representación de muchos algoritmos.
El concepto de recursividad está ligado, en los lenguajes de programación, al
concepto de procedimiento o función. Un procedimiento o función es recursivo
cuando durante una invocación a él puede ser invocado a su vez él mismo.

El conocimiento de los principios fundamentales de la recursividad evita evadir


su utilización cuando su aplicación sea conveniente para un determinado
problema.

El uso de la recursividad es particularmente conveniente para aquellos


problemas que pueden definirse de modo natural en términos de recursividad.

Ventajas y desventajas de la Recursividad:

Ventajas:
· No es necesario definir la secuencia de pasos exacta para resolver el
problema.
· Soluciones simples, claras.
· Soluciones elegantes.
· Soluciones a problemas complejos.

Desventajas:
· Podría ser menos eficiente.
· Sobrecarga asociada con las llamadas a subalgoritmos
· Una simple llamada puede generar un gran número de llamadas
Recursivas. (Fact(n) genera n llamadas recursivas)
· El valor de la recursividad reside en el hecho de que se puede usar para
resolver problemas sin fácil solución iterativa.
· La ineficiencia inherente de algunos algoritmos recursivos.

Ejemplos de funciones recursivas en C++:

1. // Sumar los dígitos de un número


#include <iostream>
using namespace std;
int SumaDigitos(int);
int main() {
cout << 32890123 << ": " << SumaDigitos(32890123) << endl;
return 0;
}
int SumaDigitos(int n) {
if(n < 10) return n;
return n%10+SumaDigitos(n/10);
}

2. // El producto de forma recursiva


#include <iostream>
using namespace std;
int producto(int a, int b){
if (b==0)
return 0;
else
return a+producto(a,b-1);
}

3. // Suma recursiva de los elementos de un vector


#include <iostream>
using namespace std;
int SumaV (int *V, int n){
if (n==0)
return V[0];
else
return V[n]+sumaV(V,n-1);
}

4. // Buscar el máximo de un vector (I)


#include <iostream>
using namespace std;
int Mayor1 (int *V, int n){
int aux;
if (n==0)
return V[0];
else {
aux = Mayor1 (V, n-1);
if (V[n]> aux)
return V[n];
else
return aux;
}

5. // Búsqueda lineal recursiva (con dos casos base)


#include <iostream>
using namespace std;
int BusquedaLineal(int *V, int n, int b)
{
if (n<0)
return 0;
else
if (V[n]==b)
return 1;
else
return BusquedaLineal(V,n-1,b);
}
6. // Función de partición
#include <iostream>
using namespace std;
int partir (int *v, int primero, int ultimo);
void OR (int *v, int izda, int dcha)
{
int pos_pivote; // Pos. del pivote tras partición
if (izda < dcha) {
// Particionar "v"
pos_pivote = partir (v, izda, dcha);
// Ordenar la primera mitad
OR (v, izda, pos_pivote-1);
// Ordenar la segunda mitad
OR (v, pos_pivote+1, dcha);
}
}
int partir (int *v, int primero, int ultimo)
{
void intercambia_int (int &a, int &b);
int izda, dcha; // Indices para recorrer v
int val_pivote; // Valor del pivote.
// El pivote es el primer elemento.
val_pivote = v[primero];
izda = primero + 1; // "izda" va a la dcha.
dcha = ultimo; // "dcha" va a la izda.
do { // Buscar e intercambiar elementos
// Buscar un elemento mayor que el pivote
// avanzando desde la izquierda
while ((izda<=dcha) && (v[izda]<=val_pivote))
izda++;
// Buscar un elemento menor o igual que el pivote
// avanzando desde la derecha
while ((izda<=dcha) && (v[dcha]>val_pivote))
dcha--;
if (izda < dcha) { // Intercambiar
intercambia_int (v[izda], v[dcha]);
dcha--;
izda++;
}
} while (izda <= dcha); // Terminar cuando se
//cruzan "izda" y "dcha"
// Colocar el pivote en su sitio correcto
intercambia_int (v[primero], v[dcha]);
return dcha; // Devolver la pos. del pivote
}

7. // Torres de Hanói

#include <iostream>
using namespace std;
int main (void)
{
void hanoi (int n, int inic, int tmp, int final);
int n; // Numero de discos a mover
cout << "Numero de discos: ";
cin >> n;
hanoi (n, 1, 2, 3); // mover "n" discos del 1 al 3,
// usando el 2 como temporal.
return 0;
}
void hanoi (int n, int inic, int tmp, int final)
{
if (n > 0) {
// Mover n-1 discos de "inic" a "tmp".
// El temporal es "final".
hanoi (n-1, inic, final, tmp);
// Mover el que queda en "inic"a "final"
cout <<"Del poste "<<inic<<" al "<<final<<"\n";
// Mover n-1 discos de "tmp" a "final".
// El temporal es "inic".
hanoi (n-1, tmp, inic, final);
}
}

% Hanói
Numero de discos: 3
Del poste 1 al 3
Del poste 1 al 2
Del poste 3 al 2
Del poste 1 al 3
Del poste 2 al 1
Del poste 2 al 3
Del poste 1 al 3
8. // Visualizar las permutaciones de n elementos.
Las permutaciones de un conjunto son las diferentes maneras de colocar sus
elementos, usando todos ellos y sin repetir ninguno. Por ejemplo para A, B, C,
tenemos: ABC, ACB, BAC, BCA, CAB, CBA.
#include <iostream>
using namespace std;
/* Prototipo de función */
void Permutaciones(char *, int l=0);
int main(int argc, char *argv[]) {
char palabra[] = "ABCDE";
Permutaciones(palabra);
cin.get();
return 0;
}
void Permutaciones(char * cad, int l) {
char c; /* variable auxiliar para intercambio */
int i, j; /* variables para bucles */
int n = strlen(cad);
for(i = 0; i < n-l; i++) {
if(n-l > 2) Permutaciones(cad, l+1);
else cout << cad << ", ";
/* Intercambio de posiciones */
c = cad[l];
cad[l] = cad[l+i+1];
cad[l+i+1] = c;
if(l+i == n-1) {
for(j = l; j < n; j++) cad[j] = cad[j+1];
cad[n] = 0;
}
}
}

9. // Búsqueda binaria
#include <iostream>
using namespace std;
int Binaria(int*, int, int, int);
int tabla[] = {
1, 3, 12, 33, 42, 43, 44, 45, 54, 55,
61, 63, 72, 73, 82, 83, 84, 85, 94, 95,
101, 103, 112, 133, 142, 143, 144, 145, 154, 155,
161, 163, 172, 173, 182, 183, 184, 185, 194, 195
};
int main() {
int pos;
int valor=141;
pos = Binaria(tabla, valor, 0, sizeof(tabla)/sizeof(tabla[0])-1);
if(pos > 0) cout << "Valor " << valor << " encontrado en posicion: " << pos <<
endl;
else cout << "Valor " << valor << " no encontrado" << endl;
return 0;
}
/* Función de búsqueda binaria:
Busca el "valor" dentro del vector "vec" entre los márgenes
inferior "i" y superior "s" */
int Binaria(int* vec, int valor, int i, int s) {
int inferior = i;
int superior = s;
int central;
if(superior <= inferior) return -1;
central = inferior+(superior-inferior)/2;
if(vec[central] == valor) return central;
else if(vec[central] < valor) return Binaria(vec, valor, central+1, superior);
return Binaria(vec, valor, inferior, central-1);
}
10. // Algoritmo de Euclides
#include <iostream>
using namespace std;
int mcd(int, int);
int main() {
int a, b;
a = 364332;
b = 30252;
cout << "mcd(" << a << ", " << b << ")= " << mcd(a,b) << endl;
return 0;
}
int mcd(int a, int b) {
if(a < b) return mcd(b,a);
if(b == 0) return a;
return mcd(b, a % b);
}

También podría gustarte