Estructuras Jerarquicas y Apuntadores
Estructuras Jerarquicas y Apuntadores
Estructuras Jerarquicas y Apuntadores
MÓDULO II
Profesor(a): Integrante:
Introducción 3
2.1.-Indirección 5
2.2.-Asignación 5
2.3.-Comparación 6
3.2.-Recorrido de árboles 11
3.3.-Árboles de sintaxis 12
3.6.-Árbol-B 19
Conclusión 21
Referencias Bibliográficas 22
2
INTRODUCCIÓN
unión de datos. En este capítulo se revisan aspectos y detalles de programación con variables
documentación detallada de los programas o sketch que se ejecutan directamente en las plataformas
electrónicas
Las estructuras de datos hasta ahora vistas se almacenan estáticamente en la memoria física
del ordenador. El espacio de memoria se reserva con anticipación y no cambia durante la ejecución
del programa y esto permite una comprobación de tipos en tiempo de compilación. La definición
y manipulación de estos objetos se realiza en Pascal mediante los punteros (variables cuyo
contenido son posiciones de memoria. También hablaremos sobre un apuntador siendo variable
que contiene la dirección de memoria de otra variable. Los apuntadores se utilizan para dar claridad
y simplicidad a las operaciones a nivel de memoria. Lenguaje C es un lenguaje de alto nivel porque
permite programar a bajo nivel. La programación a bajo nivel se refiere a la manipulación de los
3
1.-Gestión dinámica de memoria
Hasta ahora, los tipos de datos que hemos visto (a excepción de strings y ficheros) eran
estructuras de datos estáticas, es decir, estructuras que no pueden cambiar de tamaño a lo largo
de todo el programa. Pero en los lenguajes dinámicos se pueden crear estructuras de datos
dinámicas, estructuras que sí que pueden variar su tamaño durante la ejecución del programa.
Además es posible crearlas y destruirlas en cualquier punto del programa, de manera que las
Este tipo de variables tienen sin embargo una diferencia muy importante con las variables
estáticas y es que en general no tienen nombre que las identifique. Por eso necesitamos utilizar
unas variables especiales para referenciar las variables dinámicas: los punteros.
Un puntero es una variable que contiene una posición de memoria, y por tanto se dice que
Ejemplo:
P 1000
variable;
O directamente:
tipo * variable;
Ejemplo:
4
typedef int * Ptr_int; Ptr_int p_i;
O directamente:
int * p_i
El tipo de dato al que apunta el puntero (en el ejemplo int) se denomina tipo base del
puntero.
Se debe tener en cuenta que cuando declaramos una variable de tipo puntero sólo se
Para obtener el contenido de una variable dinámica a la que apunta el puntero, utilizaremos
Ejemplo:
2.1.-Indirección
2.2.-Asignación
constante NULL (dirección nula). Esta constante se utiliza normalmente para inicializar los
punteros.
Ejemplo:
p = new int;
5
p
*p = 2;
q = new int;
*q = 5; q
p = q; *p = *q;
p p q
2.3.-Comparación
Sobre los punteros también están definidos los operadores de comparación, aunque los
únicos que se deben utilizar son los operadores de igualdad (==) o desigualdad (<>) de punteros,
La memoria dinámica que se almacena en el heap es aquella que se utiliza para almacenar
datos que se crean en el medio de la ejecución de un programa. En general, este tipo de datos puede
llegar a ser casi la totalidad de los datos de un programa. Por ejemplo, supóngase un programa que
de memoria en C se hace con un mecanismo muy simple, pero a la vez muy propenso a errores.
Los dos tipos de operaciones son la petición y liberación de memoria. El ciclo es sencillo, cuando
se precisa almacenar un nuevo dato, se solicita tanta memoria en bytes como sea necesaria, y una
vez que ese dato ya no se necesita la memoria se devuelve para poder ser reutilizada. Este esquema
6
se conoce como “gestión explícita de memoria” pues requiere ejecutar una operación para pedir la
void *malloc(size_t size). Es la función para reservar tantos bytes consecutivos de memoria
void *calloc(size_t nmemb, size_t size). Reserva espacio para tantos elementos como
indica su primer parámetro nmemb, y cada uno de ellos con un tamaño en bytes como indica
igual que la función anterior devuelve la dirección de memoria al comienzo del bloque
reservado. Esta función inicializa todos los bytes de la zona reservada al valor cero.
void free(void *ptr). Función que dado un puntero, libera el espacio previamente
reservado. El puntero que recibe como parámetro esta función tiene que ser el que se ha
obtenido con una llamada de reserva de memoria. No es necesario incluir el tamaño. Una
vez que se ejecuta esta llamada, los datos en esa porción de memoria se consideran basura,
void *realloc(void *ptr, size_t size). Función para redimensionar una porción de memoria
previamente reservada a la que apunta el primer parámetro al tamaño dado como segundo
redimensionada, que no tiene por qué ser necesariamente igual al que se ha pasado como
parámetro. Los datos se conservan intactos en tantos bytes como el mínimo entre el tamaño
antiguo y el nuevo.
7
2.5.-Aplicaciones de los Apuntadores
A continuación un ejemplo en C++ donde una función opera 2 punteros y modifica su valor original
Los árboles son unas estructuras de datos, formadas por nodos y enlaces, que guardan
desarrollo de compiladores, los árboles se utilizan para representar expresiones de sintaxis del
8
lenguaje de programación. En inteligencia artificial, los árboles se utilizan para programación de
Preorden: (raíz, izquierdo, derecho). Para recorrer un árbol binario no vacío en preorden,
se deben realizar las siguientes operaciones recursivamente en cada nodo, comenzando con
el nodo de raíz:
1. Visite la raíz
Inorden: (izquierdo, raíz, derecho). Para recorrer un árbol binario no vacío en inorden
2. Visite la raíz
Postorden: (izquierdo, derecho, raíz). Para recorrer un árbol binario no vacío en postorden,
3. Visite la raíz
En preorden, la raíz se recorre antes que los recorridos de los subárboles izquierdo
y derecho
derecho, y
9
En postorden, la raíz se recorre después de los recorridos por el subárbol izquierdo
y el derecho
Un árbol n-ario es una estructura re cursiva, en la cual cada elemento tiene un número
binario. La diferencia radica en que esta estructura puede manejar múltiples sub árboles asociados
Orden de un elemento:
Implementación genérica:
10
3.2.-Recorrido de árboles:
manera sistemática, exactamente una vez, cada nodo en una estructura de datos de árbol
(examinando y/o actualizando los datos en los nodos). Tales recorridos están clasificados por el
orden en el cual son visitados los nodos. Los siguientes algoritmos son descritos para un árbol
Comparado a las estructuras de datos lineales como las listas enlazadas y arreglos
Comenzando en la raíz de un árbol binario, hay tres pasos principales que pueden ser
realizados y el orden en la cual son realizados define el tipo de recorrido. Estos pasos (en ningún
orden particular) son: ejecución de una acción en el nodo actual (referido como “visitando” el
nodo), recorriendo al nodo hijo de la izquierda, y recorriendo al nodo hijo de la derecha. Así el
Los nombres dados para un estilo particular de recorrido vienen de la posición del elemento
de raíz con respecto a los nodos izquierdo y derecho. Imagine que los nodos izquierdo y derecho
son constantes en espacio, entonces el nodo raíz pudiera colocarse a la izquierda del nodo izquierdo
(pre-orden), entre el nodo izquierdo y derecho (in-orden), o a la derecha del nodo derecho (post-
11
orden). Con el fin de ilustrar, se asume que los nodos izquierdos tienen siempre prioridad sobre los
nodos derechos. Este ordenamiento puede ser invertido mientras el mismo orden sea asumido para
3.3.-Árboles de sintaxis
Cada nodo del árbol denota una construcción que ocurre en el código fuente. La sintaxis es abstracta
en el sentido que no representa cada detalle que aparezca en la sintaxis verdadera. Por ejemplo, el
sintáctica tal como IF condición THEN puede ser denotada por un solo nodo con dos ramas.
12
Esto hace a los árboles de sintaxis abstracta diferente de los árboles de sintaxis concreta,
llamados tradicionalmente árboles de parser, que son a menudo construidos por la parte parser de
no intuitivo). Una vez construido, información adicional es agregada al AST por procesamiento
Un árbol binario de búsqueda también llamado BST (acrónimo del inglés Binary Search
Tree) es un tipo particular de árbol binario que presenta una estructura de datos en forma de árbol
usada en informática.
Para una fácil comprensión queda resumido en que es un árbol binario que cumple que el
subárbol izquierdo de cualquier nodo (si no está vacío) contiene valores menores que el que
contiene dicho nodo, y el subárbol derecho (si no está vacío) contiene valores mayores.
Para estas definiciones se considera que hay una relación de orden establecida entre los
elementos de los nodos. Que cierta relación esté definida, o no, depende de cada lenguaje de
programación. De aquí se deduce que puede haber distintos árboles binarios de búsqueda para un
13
La altura h en el peor de los casos es siempre el mismo tamaño que el número de elementos
El interés de los árboles binarios de búsqueda (ABB) radica en que su recorrido en in orden
proporciona los elementos ordenados de forma ascendente y en que la búsqueda de algún elemento
Dependiendo de las necesidades del usuario que trate con una estructura de este tipo, se
podrá permitir la igualdad estricta en alguno, en ninguno o en ambos de los subárboles que penden
de la raíz. Permitir el uso de la igualdad provoca la aparición de valores dobles y hace la búsqueda
más compleja.
Existen diferentes tipos y variaciones de los árboles binarios, y una de las más importantes
árboles AVL.
Un árbol binario balanceado (también conocidos simplemente como árboles AVL en honor
a sus creadores Adelson-Velski y Landis) es un árbol binario de búsqueda (ABB) en el que las
menos la altura de su subárbol izquierdo; pero en este blog se adoptará la primera. Por convención,
Durante el proceso de inserción o eliminación puede ocurrir un desbalance, es decir, que el valor
absoluto de la altura de alguno de los nodos del árbol AVL sea mayor que 1.
14
En caso de existir desbalance en alguno de los nodos, es decir, una condición que incumpla lo
establecido por la expresión anterior, se tiene que re balancear el árbol para que éste siga siendo un
En este sentido, existen cuatro casos que corrigen el balanceo de un árbol AVL:
A continuación se describen dos de estos cuatro casos, debido a que los otros dos son
Rotación simple
El primer caso de rebalanceo, la rotación derecha también conocida como rotación simple, se
La figura (a) muestra hasta antes de la inserción del elemento representado por el cuadrado
rojo (cuadrado más obscuro), un árbol AVL balanceado. El balance puede determinarse
gráficamente por los niveles representados por líneas horizontales punteadas: el balance para los
(cuadrado más obscuro), se presenta un desbalance sobre el nodo B: ahora el balance para los nodos
A y B es 1 y 2 respectivamente.
15
Por otro lado, la figura (b) muestra la solución al desbalanceo descrito en el párrafo anterior.
Para visualizarlo mejor, imagine que en la figura (a), en el nodo representado por B existe una
polea fija, de tal forma que al "jalar" z hacia abajo, el subárbol izquierdo de B representado por A
sube, mientras que B baja convirtiéndose en el subárbol derecho de A. Note cómo y pasa de ser
Ejemplo:
Considere el árbol AVL (asegúrese de que en efecto sea un árbol AVL y determine que el
balance de cada uno de los nodos que se presenta es correcto) que aparece en la siguiente figura en
(a):
Caso 1 de rotación dará como resultado el árbol AVL que aparece en la figura (c) dependiendo
16
del elemento (1 o 3) que se haya insertado, de tal forma que la rotación simple derecha se realiza
Observe cómo la aplicación de la rotación simple corrige el balance general del árbol, de
anterior, así como de determinar por su propia cuenta, el balance de cada uno de los nodos para
Rotación doble
El caso de rebalanceo que implica una rotación doble es un proceso un poco más elaborado
que el de la rotación simple, ya que como su nombre lo indica, implica dos rotaciones. La
Ante una situación como la que se presenta en la figura (a) la solución está dada por la
figura (c). Ahora bien, existe un paso intermedio entre éstas, mismo que está representado por la
17
La figura (a) muestra, hasta antes de la inserción del elemento representado por el cuadrado
rojo (cuadrado más obscuro), un árbol AVL balanceado. El balance puede determinarse
gráficamente por los niveles representados por líneas horizontales punteadas: el balance para los
por el cuadrado rojo (cuadrado más obscuro), se presenta un desbalance sobre el nodo C: ahora el
balance para los nodos A, B y C es -1, (1 o -1 según sea el elemento insertado) y 2 respectivamente.
rotación derecha sobre C (asegúrese de comprobarlo). Por otro lado, note los signos de los balances
En base a lo anterior, la figura (b) muestra una rotación izquierda sobre A aunque el
nodo A no está desbalanceado. Note que el balance no se ha corregido todavía, ya que el balance
de A es 0 o 1, el de B es 2 o 1, y el de C 2.
Ahora bien, partiendo de la figura (b), una nueva rotación derecha sobre C generará el árbol
Asegúrese de comprender la doble rotación izquierda derecha explicada hasta aquí antes de
con anterioridad.
Ejemplo:
Para ilustrar la rotación doble, considere el árbol AVL que aparece en la siguiente figura en (a).
Una vez más y antes de continuar, compruebe que dicho árbol es un árbol AVL y que los balances
18
La rotación doble se presenta al insertar cualquiera de los elementos 5 o 7 (figura (b)).
La aplicación de la rotación doble dará como resultado el árbol AVL que aparece en la
figura (c) dependiendo del nodo que se haya insertado. Se deja como ejercicio para el lector generar
el paso intermedio y comparar su resultado con el de la figura (c). El paso intermedio consiste en
hacer una rotación izquierda sobre 4 en la figura (b), y posteriormente una rotación derecha sobre
8; estas dos rotaciones deberán generar la figura (c). Una vez más observe los signos de los balances
en los ejemplos.
3.6.-Árbol-B
archivos. Al igual que los árboles binarios de búsqueda, son árboles balanceados de búsqueda, pero
cada nodo puede poseer más de dos hijos.1 Los árboles B mantienen los datos ordenados y las
La idea tras los árboles-B es que los nodos internos deben tener un número variable de
nodos hijo dentro de un rango predefinido. Cuando se inserta o se elimina un dato de la estructura,
la cantidad de nodos hijo varía dentro de un nodo. Para que siga manteniéndose el número de nodos
dentro del rango predefinido, los nodos internos se juntan o se parten. Dado que se permite un
19
rango variable de nodos hijo, los árboles-B no necesitan re balancearse tan frecuentemente como
los árboles binarios de búsqueda auto-balanceables. Pero, por otro lado, pueden desperdiciar
memoria, porque los nodos no permanecen totalmente ocupados. Los límites (uno superior y otro
inferior) en el número de nodos hijo son definidos para cada implementación en particular. Por
ejemplo, en un árbol-B 2-3 (A menudo simplemente llamado árbol 2-3), cada nodo sólo puede
Un árbol-B se mantiene balanceado porque requiere que todos los nodos hoja se encuentren a la
misma altura.
Los árboles B tienen ventajas sustanciales sobre otras implementaciones cuando el tiempo
de acceso a los nodos excede al tiempo de acceso entre nodos. Este caso se da usualmente cuando
los nodos se encuentran en dispositivos de almacenamiento secundario como los discos rígidos. Al
maximizar el número de nodos hijo de cada nodo interno, la altura del árbol decrece, las
operaciones para balancearlo se reducen, y aumenta la eficiencia. Usualmente este valor se coloca
de forma tal que cada nodo ocupe un bloque de disco, o un tamaño análogo en el dispositivo.
Mientras que los árboles B 2-3 pueden ser útiles en la memoria principal, y además más fáciles de
explicar, si el tamaño de los nodos se ajusta para caber en un bloque de disco, el resultado puede
Los creadores del árbol B, Rudolf Bayer y Ed McCreight, no han explicado el significado
de la letra B de su nombre. Se cree que la B es de balanceado, dado que todos los nodos hoja se
mantienen al mismo nivel en el árbol. La B también puede referirse a Bayer, o a Boeing, porque
sus creadores trabajaban en los Boeing Scientific Research Labs por ese entonces.
20
CONCLUSIÓN
El modelo jerárquico de base de datos es uno de los primeros en aparecer, solo podían
modelar relaciones pero se podía arreglar usando los Vínculos Virtuales. Los vínculos virtuales
posibilitan las relaciones, el principal problema del este sistema es el de la poca independencia de
efectúa con punteros, esto facilitaba para que el usuario pueda conseguir un diseño físico de la base
de datos.
21
REFERENCIAS BIBLIOGRÁFICAS
Recuperado de:
https://libroweb.alfaomega.com.mx/book/890/free/data/lecturas_complementarias/cap5/ard
uino_Cap5_Web.pdf.
https://www.monografias.com/trabajos79/modelo-jerarquico/modelo-jerarquico
B#/media/Archivo:B-tree_example.svg
https://es.wikipedia.org/wiki/%C3%81rbol_de_sintaxis_abstracta
https://es.wikipedia.org/wiki/Recorrido_de_%C3%A1rboles#Ejemplo
https://www.infor.uva.es/~jvalvarez/docencia/tema2.pdf
b.unam.mx/salac/practicasEDAA/eda1_p2.pdf
http://informatica.uv.es/iiguia/AED/oldwww/2004_05/AED.Tema.08.pdf
22