0% encontró este documento útil (0 votos)
13 vistas37 páginas

04 Arboles

Cargado por

Pancho.fd
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
13 vistas37 páginas

04 Arboles

Cargado por

Pancho.fd
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 37

ÁRBOLES

ESTRUCTURAS DE DATOS NO LINEALES

• Las ED no lineales son aquellas en donde cada


dato puede tener más de un predecesor y más
de un sucesor.

• Las ED jerárquicas son un tipo de ED no lineal


donde cada dato tiene un único predecesor,
excepto el primero que no tiene predecesor.
UTILIDADES
✓ Analizar circuitos eléctricos.
✓ Representar fórmulas
matemáticas.
✓ Organizar información en
sistemas de bases de datos.
ÁRBOL: DEFINICIÓN
Un árbol es una colección de
datos jerárquica, en el que
cada nodo tiene un padre a excepción del
nodo raíz, que representa la jerarquía
máxima sobre el resto de los elementos.

Fuente: Algoritmos y estructuras de datos en Python: un enfoque agil y estructurado de Walter Bel.
ÁRBOLES: DEFINICIÓN FORMAL
Los árboles son una estructura de datos recursiva ya que está compuesta por árboles
más pequeños llamados subárboles.
Formalmente, un árbol se puede definir de manera recursiva como sigue:
1. Un solo nodo es, por sí mismo, un árbol. Ese nodo es también la raíz de dicho
árbol.
2. Supóngase que n es un nodo y que A1, A2, …, Ak son árboles con raíces n1, n2,
…, nk respectivamente. Se puede construir un nuevo árbol haciendo que n se
constituya en el padre de los nodos n1, n2, …, nk. En dicho árbol n es la raíz y A1,
A2, …, Ak son los subárboles de la raíz. Los nodos n1, n2, …, nk son hijos del
nodo n.
EJEMPLO

Un índice y su representación como árbol.


Fuente: Estructura de datos y algoritmos de Aho, Hopcroft y Ullman.
TERMINOLOGÍA BÁSICA
• Nodo; es cada uno de los elementos de un árbol.
• Arco (arista); es la línea que une un nodo de un árbol con su
sucesor.
• Raíz: es el nodo que se encuentra en la parte superior del
árbol, mediante el cual se accede al árbol.
• Hoja: son todos los nodos que no tienen sucesores, se los
conoce como nodos terminales.
• Rama: es la conexión entre dos nodos.
TERMINOLOGÍA BÁSICA
• Nodo interno: son todos aquellos nodos que tienen al menos un
hijo, a excepción de la raíz.

• Subárbol: es un subconjunto de nodos del árbol, aunque un solo


nodo es considerado un árbol también.

• Grado de un nodo: es el número de subárboles de dicho nodo,


• Grado de un árbol: es el grado (o aridad) máximo de todos los
nodos del árbol, es decir la cantidad máxima de hijos que tiene
alguno de los nodos del árbol.
TERMINOLOGÍA BÁSICA
• Camino: Si n1, n2 … nk es una sucesión de nodos de un árbol tal que
ni es el padre de ni+1 para 1 ≤ i < k, entonces la secuencia se
denomina camino del nodo ni al nodo nk. La longitud del camino es
el número de nodos del camino menos 1.
• Nivel de un nodo: se define por el número de ramas entre dicho
nodo y la raíz más uno.
• Altura de un nodo: es la longitud del camino más largo entre ese
nodo y una hoja.
• Altura de un árbol: es la altura de su nodo raíz.
TERMINOLOGÍA BÁSICA
• Padre: es aquel nodo del que depende al menos un nodo hijo, es decir
que los hijos son aquellos nodos a los que apuntan las flechas que salen
de este.
• Hijo: es un nodo que depende directamente de otro, es decir está
conectado mediante una flecha que llega. Todos, menos el nodo raíz.
• Hermanos: son el conjunto de nodos que tienen el mismo padre.
• Descendientes: son todos aquellos nodos que pertenecen a los
subárboles de los hijos de dicho nodo.
• Ancestros: son todos aquellos nodos en el camino desde la raíz a dicho
nodo.
EJERCICIO ¿Qué nodos son hojas?
¿Qué nodo es la ráiz?
¿Cuáles son los nodos internos?
¿Quién es el padre de C?
¿Quiénes los hijos de C?
¿Quiénes los ancestros de C?
¿Quiénes los descendientes de E?
¿Quiénes son los hermanos de E?
¿Cuál es el grado del árbol?
¿Cuál es el camino de A a K?
¿Cuál es la altura del arbol?
RECORRIDO DE ÁRBOLES
Los tres ordenamientos se definen recursivamente como sigue:
• Si un árbol A es nulo, entonces la lista vacía es el listado de los nodos
de A en los órdenes previo, simétrico y posterior.
• Si A contiene un solo nodo, entonces ese nodo constituye el listado
de los nodos de A en los órdenes previo, simétrico y posterior.
• Si ninguno de los anteriores es el caso, sea A un árbol con raíz n y
subárboles A1, A2, …, Ak, como muestra la figura
PREORDER
El listado en orden previo de los nodos
de A está formado por la raíz de A,
seguida de los nodos de A1 en orden
previo, luego por los nodos A2 en
orden previo y así sucesivamente hasta
los nodos Ak en orden previo.
1 2 3 5 8 9 6 10 4 7
INORDER
El listado en orden simétrico de los
nodos A está constituido por los
nodos de A1 en orden simétrico,
seguidos de n y luego por los nodos
de A2, …, Ak, con cada grupo de
nodos en orden simétrico.
2 1 8 5 9 3 10 6 7 4
POSTORDER
El listado en orden superior de los
nodos de A tiene los nodos de A1 en
orden posterior, luego los de A2 en
orden posterior y así sucesivamente
hasta los nodos de Ak en orden
posterior y por último la raíz n.
2 8 9 5 10 6 3 7 4 1
ÁRBOL BINARIO

ÁRBOL BINARIO DE BÚSQUEDA


ÁRBOL BINARIO: DEFINICIÓN
Un árbol binario es un tipo particular de árbol donde cada nodo NO
puede tener más de dos sucesores, es decir, es un árbol de grado
dos.
El árbol binario de búsqueda (ABB) es un caso particular donde los
nodos están ordenados del siguiente modo: todos los nodos del
subárbol izquierdo son menores que el padre y todos los del
subárbol derecho mayores.
EJEMPLOS

Fuente: Algoritmos y estructuras de datos en Python: un enfoque agil y estructurado de Walter Bel.
ESPECIFICACIÓN
TAD Nombre_del_TAD Otras operaciones
Igualdad Observacional Axiomas
Usa Exporta
Parámetro Formal
Géneros
Observadores básicos
Generadores
TAD ArbolBinarioBusqueda <a>
Igualdad Observacional
Si c y d son dos árboles binarios de búsqueda c es igual a d si se
cumple que c y d tienen el mismo valor y el subárbol izquierdo es igual
al subárbol izquierdo, y el derecho al derecho.
Usa
Natural, Bool, Secuencia<a>, None
Parámetro Formal
a
Géneros
ArbolBinarioBusqueda <a>
Observadores básicos
es_vacio(ArbolBinarioDeBusqueda<a>) → Bool
cantidad_de_nodos(ArbolBinarioDeBusqueda<a>) → Natural
maximo(ArbolBinarioDeBusqueda<a>) → Natural
{Pre: el árbol tiene al menos un elemento}
minimo(ArbolBinarioDeBusqueda<a>) → Natural
{Pre: el árbol tiene al menos un elemento}
Generadores
vacío() → ArbolBinarioDeBusqueda<a>
{Post: El Árbol retornado esta vacío}
a_partir_de(Secuencia<a>) → ArbolBinarioDeBusqueda<a>
{Post: El árbol contiene los elementos de la secuencia recibida}
Otras operaciones
insertar(ArbolBinarioDeBusqueda<a>, b)→ ArbolBinarioBusqueda<a>
{Pos: El árbol no esta vacío}
eliminar(ArbolBinarioDeBusqueda<a>, a)→ ArbolBinarioBusqueda<a>
copiar(ArbolBinarioDeBusqueda<a>) -> ArbolBinarioDeBusqueda
Axiomas
vacío(): Crea un árbol vacío (sin elementos)
a_partir_de(Secuencia<a> s): crea un árbol que contiene los valores de la
secuencia
insertar(ArbolBinarioDeBusqueda<a> a, b valor): agrega el elemento b al árbol
eliminar(ArbolBinarioDeBusqueda<a> a, b valor):borra del árbol a el valor b
cantidad_de_nodos(ArbolBinarioDeBusqueda<a> a): Retorna la cantidad de
elementos del árbol a
es_vacío(ArbolBinarioDeBusqueda<a> a): Retorna verdadero si el árbol está
vacío y falso en caso contrario
máximo(ArbolBinarioDeBusqueda<a> a): retorna el valor del mayor elemento
del árbol a
mínimo(ArbolBinarioDeBusqueda<a> a): retorna el valor del menor elemento
del árbol a
copiar(ArbolBianrioDeBusqueda<a> a): retorna un nuevo árbol que es copia del
árbol a
Exporta
ArbolBinarioDeBusqueda<a, b>, vacío, a_partir_de, insertar, eliminar,
cantidad_de_nodos, es_vacío, mínimo, máximo
ÁRBOL BINARIO DE
BÚSQUEDA
IMPLEMENTACIÓN
ABB: REPRESENTACIÓN CON NODOS
// Nodo de un árbol binario de • Uso eficiente de memoria: se usa memoria
búsqueda dinámica, ocupando solo el espacio
necesario.
package main
• Inserciones y eliminaciones flexibles sin
type Nodo struct { necesidad de reacomodar elementos.
valor int • Mayor uso de memoria debido a los
punteros adicionales.
izquierda *Nodo
• Mayor tiempo de acceso debido a la
derecha *Nodo} necesidad de recorrer los punteros en
memoria.
ABB: REPRESENTACIÓN CON ARREGLO
Cada nodo se guarda en un índice del
arreglo, y sus hijos se calculan mediante:
• Hijo izquierdo en la posición 2i + 1
• Hijo derecho en la posición 2i + 2
• Padre en la posición (i-1) / 2

• Rápido acceso a los nodos.


• Menor uso de memoria en árboles balanceados.
• Inserciones y eliminaciones costosas debido a la necesidad de
reorganizar el arreglo.
CONCLUSIÓN
La elección entre una representación u otra depende del tipo de
operaciones que se quieran realizar y la estructura del árbol:

• Para operaciones dinámicas con frecuentes inserciones y


eliminaciones, la mejor opción es nodos enlazados.

• Para acceso rápido en un árbol balanceado y estático, la


representación con arreglo es más eficiente.
ÁRBOL BINARIO DE
BÚSQUEDA
IMPLEMENTACIÓN EN GO
//define la estructura para el Arbol binario de búsqueda
type ArbolBB struct {
valor int
hijo_izq, hijo_der *ArbolBB
}
//crea un arbol binario vacío
func newAbb() *ArbolBB {
New(): Función que asigna nueva memoria a todo tipo de
arbol := new(ArbolBB) datos. Recibe un tipo de dato y retorna la dirección del tipo de
dato creado.
arbol.valor = 0
arbol.hijo_izq = nil
arbol.hijo_der = nil
return arbol
}
func a_partir_de(datos []int) *ArbolBB {
var arbol *ArbolBB
arbol = newAbb()
fin := len(datos)
for i := 0; i < fin; i = i + 1 {
arbol.insertar(datos[i])
}
return arbol
}
// verifica si el arbol está vacío
func (a *ArbolBB) es_vacio() bool {
return (a.valor == 0) && (a.hijo_izq == nil) && (a.hijo_der == nil)
}
// inserta un elemento en el árbol
func (a *ArbolBB) insertar(elem int) *ArbolBB {
if a.es_vacio() {
a.valor = elem
a.hijo_izq = new(ArbolBB)
a.hijo_der = new(ArbolBB)
} else if elem < a.valor {
a.hijo_izq.insertar(elem)
} else if elem > a.valor {
a.hijo_der.insertar(elem)
}
return a
}
func (a *ArbolBB) maximo() int {
if !a.hijo_der.es_vacio() {
return a.hijo_der.maximo()
}
return a.valor
}

func (a *ArbolBB) minimo() int {


if !a.hijo_izq.es_vacio() {
return a.hijo_izq.minimo()
}
return a.valor
}
func (a *ArbolBB) es_hoja() bool {
return a.hijo_izq.es_vacio() && a.hijo_der.es_vacio()
}

func (a *ArbolBB) cantidad_de_nodos() int {


if a.es_vacio() {
return 0
} else if a.es_hoja() {
return 1
} else {
return 1+a.hijo_izq.cantidad_de_nodos()+ a.hijo_der.cantidad_de_nodos()
}
}
// recorridos del árbol
func (a *ArbolBB) postOrder() {
func (a *ArbolBB) inOrder() {
if !a.es_vacio() {
if !a.es_vacio() {
a.hijo_izq.postOrder()
a.hijo_izq.inOrder()
a.hijo_der.postOrder()
fmt.Println(a.valor, " ")
fmt.Println(a.valor, " ")
a.hijo_der.inOrder()
}
}
}
}
func (a *ArbolBB) preOrder() {
if !a.es_vacio() {
fmt.Println(a.valor, " ")
a.hijo_izq.preOrder()
a.hijo_der.preOrder()
}
}
func (a *ArbolBB) eliminar(elem int) *ArbolBB {
if a.es_vacio() {
fmt.Println("El elemento a eliminar no está en el árbol")
return a
} else if elem < a.valor {
a.hijo_izq.eliminar(elem)
} else if elem > a.valor {
a.hijo_der.eliminar(elem)
} else if (a.valor == elem) && a.es_hoja() {
a.valor = 0
a.hijo_izq = nil
a.hijo_der = nil
} else if a.hijo_izq.es_vacio() {
} else if a.hijo_izq.es_vacio() {
a.valor = a.hijo_der.valor
a.hijo_izq = a.hijo_der.hijo_izq
a.hijo_der = a.hijo_der.hijo_der
} else if a.hijo_der.es_vacio() {
a.valor = a.hijo_izq.valor
a.hijo_izq = a.hijo_izq.hijo_izq
a.hijo_der = a.hijo_izq.hijo_der
} else {
minimo_subArbolDer := a.hijo_der.minimo()
a.hijo_der.eliminar(minimo_subArbolDer)
a.valor = minimo_subArbolDer
}
return a
}

También podría gustarte