Professional Documents
Culture Documents
3. Estructuras no lineales
3.1. Recursividad.
Definicin: Un funcin recursiva es una funcin que se llama a si mismo ya sea directa
o indirectamente.
int fn() {
...
fn();
...
}
int fn1() {
...
fn2(. . .);
...
}
int fn2() {
...
fn1(. . .);
...
}
Uno de los requisitos que debe tener un proceso recursivo para considerarlo valido
es que debe tener una condicin de salida o condicin base, para que garantice el
no generar un secuencia infinita y agotara la memoria (Stack) Pila). Por
ejemplo:
n! = n * (n-1) * (n-2) * 1
En el cual :
0! = 1
1! = 1
2! = 2 * 1
3! = 3 * 2 * 1
...
Si n es igual a 5 tendremos:
5! 5 * 4*
3 *1 5 * 4! 5 * (4 * 3*
* 2 *1) 5 * 4 * 3!...
2
( 51)! ( 41)!
De modo que la funcin recursiva del factorial n sera:
n 0 1
n!
n 0 n * (n 1)!
n=5
5*factorial(4)
n=4 4*factorial(3)
5*factorial(4)
3*factorial(2)
n=3
4*factorial(3)
5*factorial(4)
2*factorial(1)
3*factorial(2)
n=2
4*factorial(3)
5*factorial(4)
1*factorial(0)
2*factorial(1)
3*factorial(2)
n=1
4*factorial(3)
5*factorial(4)
1*1 = 1
2*factorial(1)
3*factorial(2)
4*factorial(3)
5*factorial(4)
2*1=2
3*factorial(2)
4*factorial(3)
5*factorial(4)
3*2=6
4*factorial(3)
5*factorial(4)
4*6=24
5*factorial(4)
5*24=120
Factorial de 5: 120
Ejemplos:
Solucin iterativa:
a *b a
a
a
a a
b veces
Solucin recursiva:
b 1 a
a * b
b 0 a a * (b 1)
0+1=1
1+1=2
1+2=3
2+3=5
3+5=8
5 + 8 = 13
..
.
Entonces podemos deducir que:
fibonacci(0) = 0
fibonacci(1) = 1
fibonacci(n)= fibonacci(n-1) + fibonacci(n-2)
Solucin recursiva:
n 0 || n 1 n
fibonacci(n)
n 2 fibonacci(n 1) fibonacci(n 2)
long fibonacci(long n) {
if (n == 0 || n == 1)
return n;
else
return fibonacci(n-1) + fibonacci(n-2);
}
Escriba un programa que utilice una funcin recursiva mcd (mximo como
un divisor) de dos nmeros por el algoritmo de Euclides. El mcd de dos
nmeros a y b se define como el entero mayor que divide a ambos
nmeros. El mcd no est definido si tanto a como b son cero. Los valores
negativos de a y b se sustituyen por sus valores absolutos. Siempre debe
cumplirse la premisa a >= b. Si b = 0 el mcd es a. Por ejemplo el mcd(2970,
1265)
a b Operacin
2970 1265 2990 % 1265=440
1265 440 1265 % 440 = 385
440 385 440 % 385= 55
385 55 385 % 55 = 0
55 0 El mcd es 55
b 0 a
mcd (a, b)
b! 0 mcd (b, a % b)
3.2. rboles.
Las listas enlazadas, pilas y colas son estructuras de datos lineales (es decir,
secuenciales). Un rbol es una estructura bidimensional no lineal, con propiedades
especiales.
V4 V5 V6 V7
V2 V3
V1
Dentro de las ciencias computacionales, los rboles tienen muchas aplicaciones, entre
estas se encuentran:
v1 es el nodo raz.
vn-1 es el padre de vn.
v1, v2, , vn-1 son ancestros de vn.
vn es un hijo de vn-1.
Si a es un ancestro de b, entonces b es un descendiente de a.
Si a y b son hijos de c, entonces a y b son hermanos.
Si a no tiene hijos, entonces a es un vrtice terminal (o una hoja).
Si a no es un vrtice terminal, entonces a es un vrtice interno (o una rama).
Nodo Raz
Vrtice
o V1
Nodo
Nivel 0
V3 V2
Arco Nivel 1
Nivel 2
V7 V6 V5 V4
Ejemplo:
B C
D E F G H
I J K L M N O
Representacin de un rbol
01 v1
02 v2
03 v4
03 v5
02 v3
03 v6
03 v7
Parntesis anidados:
v1(v2(v4,v5), v3(v6,v7))
Grafos:
V1
V3 V2
V7 V6 V5 V4
Diagrama de Venn:
v1
v2 v3
v4 v5 v6 v7
Un rbol ordenado es aquel que est estructurado bajo una organizacin especfica.
B C
D E / F / / H /
/ I / / J / / K / / L /
rboles generales.
Tambin mediante los rboles podemos representar situaciones de la vida diaria tales
como:
Presidente
Vice-Presidente Vice-Presidente
para asuntos para asuntos
Acadmicos Administrativos
Director de
Decano de Decano de Director de
Plantacin
Artes y Ciencias Comercio Adquisiciones
Acadmica
Jefe de
Jefe de Jefe de
Ciencias de la
Matemticas Contadura
Computacin
Urano
Seles
Seles
Navratilova
Graf
Sabatini
Graf
Graf
rboles binarios.
B C
D E F
G H
Existen tres formas de recorrer un rbol binario, las cuales son Preorden, Incorden
Postorden.
Preorden
Inorden
Postorden
Preorden:
20, 15, 10, 5, 12, 18, 17,
19, 33, 25, 21, 27, 50, 40,
70
Inorden:
5, 10, 12, 15, 17, 18, 19,
20, 21, 25, 27, 33, 40, 50,
70
Postorden:
5, 12, 10, 17, 19, 18, 15,
21, 27, 25, 40, 70, 50, 33,
20
Declaracin de un nodoArbol
class nodoArbol {
int obtenDato() {
return dato;
}
nodoArbol obtenHIzq() {
return hizq;
}
nodoArbol obtenHDer() {
return hder;
}
Pila.insertar(null);
recorre = r;
while (recorre != null) {
procesar el nodo recorre
if (recorre.obtenHDer() != null)
Pila.insertar(recorre.obtenHDer());
if (recorre.obtenHIzq() != null)
recorre = recorre.obtenHIzq();
else
recorre = Pila.quitar();
}
}
Pila.insertar(null);
recorre = r;
while (recorre != null) {
while (recorre != null) {
Pila.insertar(recorre);
recorre = recorre.obtenHIzq();
}
recorre = Pila.quitar();
while (recorre != null) {
procesar el nodo recorre
if (recorre.obtenHDer() != null) {
recorre = recorre.obtenHDer();
break;
}
recorre = Pila.quitar();
}
}
}
Pila.insertar(null);
recorre = r;
while (recorre != null) {
while (recorre != null) {
Pila.insertar(recorre);
if (recorre.obtenHDer() != null)
Pila.insertar((-1) * recorre.obtenHDer());
recorre = recorre.obtenHIzq();
}
recorre = Pila.quitar();
while (recorre > 0) {
procesa el nodo recorre
recorre = Pila.quitar();
}
if (recorre < 0)
recorre = (-1) * recorre;
}
}
1 // Ejemplo_Arboles
2
3 import javax.swing.JOptionPane;
4
5 class nodoArbol {
6 private nodoArbol hizq;
7 private int dato;
8 private nodoArbol hder;
9
10 nodoArbol( int dat ) {
11 this( null, dat, null );
12 }
13
63
64 public nodoArbol quitar() {
65 if (!pilavacia())
66 return elemento[cima--];
67 else {
68 error = 2;
69 return null;
70 }
71 }
72
73 public boolean pilavacia() {
74 if (cima == -1)
75 return true;
76 else
77 return false;
78 }
79
80 public boolean pilallena() {
81 if (cima == (MAX_ELEMENTOS - 1))
82 return true;
83 else
84 return false;
85 }
86
87 public int muestraError() {
88 return error;
89 }
90 }
91
92 public class Ejemplo_Arbol {
93 public static void main(String [] args) {
94 int i,cuantos, inf;
95 nodoArbol nodo, recorre, raiz = null;
96
97 cuantos = Integer.parseInt(
98 JOptionPane.showInputDialog("Cuantos elementos deseas:") );
99
100 // Construccin del arbol ordenado
101 for (i=0; i < cuantos ; i++) {
102 inf = Integer.parseInt(
103 JOptionPane.showInputDialog("Dame el valor del nodo " + i + ":"));
104 nodo= new nodoArbol(inf);
105 if (raiz == null)
106 raiz = nodo;
107 else {
108 recorre = raiz;
109 while (true) {
110 if (nodo.obtenDato() > recorre.obtenDato())
111 if (recorre.obtenHDer() == null) {
112 recorre.setHDer(nodo);
113 break;
114 }
115 else
116 recorre = recorre.getHDer();
117 else
118 if (recorre.getHIzq() == null) {
119 recorre.setHIzq(nodo);
120 break;
121 }
122 else
123 recorre = recorre.getHIzq();
124 }
125 }
126 }
127 String Salida = "";
128
129 Salida += "Preorden:\n";
130 Salida += " Recursivo: " + preordenRecursivo(raiz) + "\n";
131
132 JOptionPane.showMessageDialog( null,Salida,
133 "Arbol Binario",JOptionPane.PLAIN_MESSAGE);
134 System.exit(0);
135 }
136
137 public static String preordenRecursivo(nodoArbol r) {
138 if (r != null) {
139 return r.obtenDato() + " " +
140 preordenRecursivo(r.obtenHIzq()) +
141 preordenRecursivo(r.obtenHDer());
142 }
143 else
144 return "";
145 }
3.3. Grafos.
Definicin.
Tipos de grafos.
Un grafo no dirigido es aquel en que sus arcos son pares no ordenados o no dirigidos.
Un grafo dirigido es aquel en el que sus arcos son pares ordenados o dirigidos (sus arcos
tiene una flecha que indica la direccin de la relacin). A un grafo dirigido tambin se le
llama diagrafo.
1 4 C E
5 H
7 9 D F
G=(V,A) G(V, A)
V={1, 4, 5, 7, 9} V={C, D, E, F, H}
A={(1, 4), (4, 1), (1, 5), A={ (C, D), (D, F), (E, C)
(5, 1), (4, 9), (9, 4), (5, 7), (E, H), (H, E) }
(7, 5), (7, 9), (9, 7)}
(a) (b)
(a) Grafo no dirigido y (b) Grafo dirigido
En ocasiones las relaciones entre nodos tienen asociado una magnitud denominada factor
o peso, y al grafo se le llama grafo ponderado.
Por ejemplo, los pueblos que forman una comarca, los nodos estn conformados por los
pueblos, los arcos por los caminos y los pesos es la distancia en kilmetros.
7 San
Lupiana Nicolas
5
12 El
Centenillo 6
Valleviejo El Novillo
7
Grafo ponderado
Grado de un nodo
Camino
4 7
10
11
6 9
Grafo no dirigido
Por ejemplo camino del nodo 4 al nodo 7 se representa por P1 = (4, 6, 9, 7) con una
longitud 3, otro camino seria P2=(10, 11). En el ejemplo de la comarca el camino P=
(Lupiana, Valleviejo, El Novillo) tiene una longitud de 19 (12 + 7).
Un camino P=(v0, v1, v2,, vn) es simple si todos los nodos que forman el camino son
distintos, pudiendo ser igual v0 y vn (los extremos del camino). Los caminos de P1 y P2
son caminos simples.
En un grafo dirigido, un ciclo es un camino simple cerrado. Por tanto, un ciclo empieza y
termina en el mismo nodo, v0 = vn,; debe tener ms de un arco. Un grafo dirigido sin ciclos
es llamado acclico (GDA-Grafo Dirigido Acclico). En general, un ciclo de longitud k se
denomina k-ciclo.
A B C
D E F
Un grafo no dirigido es conexo si existe un camino entre cualquier par de nodos que
forman el grafo y es fuertemente conexo si todos sus nodos estn conectados.
A C A C
E
F F
D D
(a) (b)
(a) Grafo conexo y (b) Grafo fuertemente conexo
Primero considere los vrtices o nodos como nmeros consecutivos empezando del
ndice cero. Tome en cuenta que el nmero de nodos son finitos. Se puede elegir una
representacin secuencial, mediante un arreglo bidimensional conocida como matriz de
adyacencia; o bien una representacin mediante una estructura multienlazada,
denominada lista de adyacencia. La eleccin de una representacin u otra depende del
tipo de grafo y de las operaciones que se vayan a realizar sobre los vrtices y arcos. Para
un grafo denso lo menor es utilizar una matriz de adyacencia. Para un grafo disperso se
suelen utilizar listas de adyacencia.
Camino
Sea G=(V, A) un grafo de n nodos, siendo V={v0, v1, v2,..,vn-1} el conjunto de nodos, y
A={(vi, vj)} el conjunto de arcos. Los nodos se pueden representar por nmeros
consecutivos de 0 a n-1. La representacin de los arcos se hace con una matriz M de n
por n, denominada matriz de adyacencia, tal que cada elemento Mij puede tomar los
valores:
1 si hay un arco (v i , v j )
M ij
0 si no hay un arco (v i , v j )
Matriz de adyacencia:
0 1 2 3 4
D F K L R
0 D 0 1 1 0 0
1 F 1 0 0 0 0
2 K 0 0 0 0 0
3 L 0 1 1 0 0
4 R 1 0 0 0 0
Lista de adyacencia:
D F K /
F D /
K /
L F K /
R D /
3 2
4 5
Matriz de adyacencia:
0 1 2 3 4
1 2 3 4 5
0 1 0 1 0 1 1
1 2 1 0 1 0 0
2 3 0 1 0 1 1
3 4 1 0 1 0 0
4 5 1 0 1 0 0
Lista de adyacencia:
1 2 4 5 /
2 1 3 /
3 2 4 /
4 1 3 /
5 1 3 /
5 5
A F L
4 5
8 9
W V
Matriz de adyacencia
0 1 2 3 4
A F L V W
0 A 0 0 0 0 0
1 F 5 0 5 5 0
2 L 0 0 0 0 9
3 V 8 0 0 0 0
4 W 0 4 0 0 0
Lista de adyacencia:
A /
F A 5 L 5 V 5 /
L W 9 /
V A 8 /
W F 4 /
10 San
Futuro Blass
6 8
5 Villa
4 Grande 6
El Rincon El
Rancho
8
a c
d e
v1 v2 v6
v4 v3 v5
Recorrido de un Grafo
Recorrer un grafo consiste en visitar (procesar) cada uno de los nodos a partir de uno de sus
nodos, en otras palabras, recorrer un grafo consiste en visitar todos los nodos los vrtices
alcanzables a partir de un nodo de inicio.
Recorrido en anchura.- Para realizar el recorrido y procesar los nodos utiliza una cola
Recorrido en profundidad.- Para realizar el recorrido y procesar los nodos utiliza una pila
Recorrido en Anchura
Este mtodo hace uso de una cola como estructura en la que se mantienen los vrtices marcados
que se van a procesar El orden en que una cola trata los elementos hace que, a partir del vrtice
de partida, v, se procesen primero todos los nodos adyacentes a v, despus se procesen los nodos
adyacentes de estos que no estn procesados o visitados.
Algoritmo:
v nodo inicial
w nodo a procesar
Cola.insertar(v);
While (!Cola.colavacia()) {
w = Cola.quitar();
Si (!Procesado.buscarL(w)) {
Procesar(w);
Procesado.insertar(w);
}
Insertar a la Cola todos los vrtices adyacentes de w
}
Cola Procesados
D
BC D
CH B
HR C
RAT H
AT R
T A
T
Recorrido en Profundidad
El recorrido comienza por el vrtice v, este se marca como procesado o visitado y se mete a la pila.
Despus se visitan en profundidad cada vrtice adyacente a v no procesado o visitado; as hasta
que no haya ms vrtices adyacentes no visitado o procesados. Esta estrategia de examinar los
nodos se denomina en profundidad por que la direccin de visitar es hacia adelante mientras sea
posible; al contrario que la bsqueda en anchura que primero visita todos los vrtices posibles en
amplitud.
Algoritmo:
v nodo inicial
w nodo a procesar
Pila.insertar(v);
While (!Pila.pilavacia()) {
w = Pila.quitar();
Si (!Procesado.buscarL(w)) {
Procesar(w);
Procesado.insertar(w);
}
Insertar a la Pila todos los vrtices adyacentes de w
}
Pila Procesados
D
BC D
BR C
BH R
BAT H
BA T
B A
B
Producto de Aprendizaje 3.7: