Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Estudios
ESTRUCTURA DE DATOS
Superiores de
Elaboró:
Ecatepec LIC. Dora Araceli Cruz Huerta
2011
Departamento
de
Licenciatura en Informática
Av. Valle del Mayo Esq. Av. Hank González Col. Valle de Anáhuac C.P. 55210 Ecatepec de Morelos, Edo. de
México
Por:
OBJETIVO:
TEMARIO
2
1.1.1 Tipos de datos simples.
1.1.1.1 Definición de bit, byte, carácter y palabra.
1.1.1.2 Manipulación de bits.
1.1.1.3 Representación de datos simples.
1.1.2 Tipos de datos abstractos.
1.2 Estructuras de datos.
1.2.1 Definición.
1.2.2 Clasificación.
1.2.2.1 Lineales y no lineales.
1.2.2.2 Dinámicas y estáticas.
2.1 Arreglos.
2.1.1 Definición.
2.1.2 Unidimensionales.
2.1.3 Bidimensionales.
2.1.4 Multidimensionales.
2.1.5 Resolución de problemas con arreglos.
2.1.6 Clases para la implementación de arreglos.
2.2 Pilas.
2.2.1 Definición.
2.2.2 Operaciones.
2.2.3 Clases para la implementación de pilas.
2.3 Colas.
2.3.1 Definición.
2.3.2 Tipos.
2.3.2.1 Colas simples.
2.3.2.2 Colas circulares.
2.3.2.3 Colas dobles.
2.3.3 Operaciones.
2.3.4 Clases para la implementación de colas.
3
4.1 Árboles.
4.1.1 Definición.
4.1.2 Representación en memoria de árboles.
4.1.2.1 Árboles generales.
4.1.2.2 Árboles binarios.
4.1.3 Recorridos en un árbol binario.
4.1.3.1 Preorden.
4.1.3.2 Inorden.
4.1.3.3 Posorden.
4.1.4 Balanceo de árboles binarios.
4.1.5 Clases para la implementación de árboles.
4.2 Grafos.
4.2.1 Definición.
4.2.2 Tipos de grafos.
4.2.3 Representación de grafos en memoria.
4.2.4 Clases para la implementación de grafos.
Entero
Números enteros sin parte decimal.
(Integer)
4
Carácter (Char) Caracteres del código ASCII
Boleano
Pueden contener los valores de falso o verdadero
(Boolean)
Real Números que pueden incluir una parte decimal
En una secuencia de caracteres que se trata como un solo
Cadena (String)
dato.
Tipos enteros
En esta categoría generalmente cuenta con 5 tipos diferentes, cada uno abarca
un rango específico de valores y utilizan una diferente cantidad de memoria
dependiendo de ese rango. Naturalmente el trabajar con rangos menores nos
ofrece una mayor velocidad y menor espacio en memoria, pero si se utilizan
enteros largos se cuenta con mayor presición. Los tipos de enteros en son:
Tipos reales
Los números reales son aquellos que cuentan con una parte decimal. En
algunos lenguajes de programación se tienen varios tipos de datos reales, pero
no se puede utilizar, más que el tipo real, en máquinas que no cuenten con un
coprocesador matemático. Los tipos de datos reales son:
5
Double 5.0E-324 a 1.7E308
Extended 1.9E-4851 a 1.1E4932
Comp -9.2E18 a 9.2E18
Los números reales deben llevar por fuerza al menos un dígito de cada lado del
punto decimal así sea éste un cero. Como ejemplo, el número 5 debe
representarse como: 5.0, el .5 como 0.5 , etc.
Tipos carácter
Los caracteres son cada uno de los símbolos que forman el código ASCII.. Los
caracteres se especifican entre apostrofes:
Tipo cadena
6
Las cadenas son secuencias de caracteres o arreglos que tienen una longitud
máxima de 255 caracteres. Se definen entre apostrofes.
Nombre : Cadena;
El tamaño por defecto para un tipo string es de 255 caracteres, pero es posible
definir uno mas pequeño utilizando el siguiente formato:
Variable : Cadena[Tamaño];
Nombre : String[30];
{Permite un máximo de 30 caracteres en la variable}
Escribir (Nombre[5]);
{Visualiza el 5to carácter de la cadena}
Tipos lógicos
Este tipo de datos tienen la peculiaridad de que solo pueden tomar dos tipos de
datos: verdadero o falso, el verdadero puede ser representado por su nombre
en inglés: True y el falso por False; también se representan por 1 y por 0
respectivamente.
7
Los datos lógicos tienen una enorme aplicación en la evaluación de ciertos
procesos, así como en el control de flujo de los programas.
• Simples
• Estructurados
La principal característica de los datos simples es que ocupan solo una casilla
de memoria, por lo tanto una variable simple hace referencia a un único valor a
la vez. Dentro de este grupo de datos se encuentran: enteros, reales, carácter,
boleanos, enumerados y subrrango (los dos últimos no existen en algunos
lenguajes de programación).
• Arreglos.
• Registros.
• conjuntos.
Bit: es una síntesis de dos términos en inglés: Binary digit, que en español
significan dígito binario, o lo que es lo mismo, número (dígito) con dos posibles
valores (binario). El término surge de usar las dos primeras letras de Binary con
la última de digit.: bit. Es la unidad de información más sencilla posible en el
sistema binario.
8
Byte: Unidad de información que consta de 8 bits equivalente a un único
carácter, como una letra, número o signo de puntuación.
Palabra: Conjunto de bits que, como unidad elemental, puede manipular una
computadora. La longitud en bits de una palabra en una computadora puede
ser de 8, 16, 32, etc., y depende del microprocesador de su unidad central de
proceso.
Un bit puede representar solamente dos valores. Dos bits, cuatro posibles
valores y ocho bits 256 posibles combinaciones de unos y ceros. Una unidad
de medida muy utilizada en la informática es el byte, que consiste en la
agrupación de ocho bits.
9
00, 01, 11, 10
Usando grupos de 8 bits (es decir, bytes) es posible representar a todos los
caracteres que conforman el abecedario, incluyendo las mayúsculas y los
signos especiales, como el de moneda o los acentos, de tal suerte que cuando
se oprime la "e" en el teclado, el microprocesador recibe un paquete de 8 bits
con la siguiente combinación de valores:
0 1100101
0 1000101
• binario: 0000011110011000
Los datos que utilizan los programas se pueden clasificar en base a diferentes
criterios. Uno de los más significativos es aquel que dice que todos los datos
que utilizan los programas son simples o compuestos.
10
• Ejemplo 1: Un año es un dato simple.
• Año...: 2006
• Ejemplo 2: Una fecha es un dato compuesto por tres datos simples (día,
mes, año).
• Fecha:
• Día...: 30
• Mes...: 11
• Año...: 2006
• Letra...: t
Una letra se representa con un carácter del alfabeto. Pero, cuando varias letras
se agrupan, entonces se obtiene un dato compuesto por varios caracteres.
11
Figura. Clasificación de los tipos de datos simples en pseudocódigo.
Todos los datos simples son ordinales, excepto el dato de tipo real. Un dato
ordinal es aquel que puede tomar por valor un elemento perteneciente a un
conjunto en el que todo elemento tiene un predecesor y un sucesor, excepto el
primero y el último. Por ejemplo, el valor 5, perteneciente al conjunto de los
números enteros, tiene como predecesor al 4, y como sucesor al 6. Sin
embargo, entre dos números reales siempre hay un número infinito de
números.
> Introducción
12
se recorría desde un punto marcado como Inicio hasta llegar a un punto Fin.
Con el tiempo se fueron creando nuevos lenguajes y en nuestros días los más
utilizados son los llamados “Orientados a Objetos”.
Historia
Definición
13
Por ello, el programador puede crear una función denominada ‘Área’, la cual va
a ser llamada el número de veces que sean necesitadas por el usuario y así el
programador se evita mucho trabajo, el programa resulta más rápido, más
eficiente y de menor longitud. Para lograr esto, se crea el método Área de una
manera separada de la interfaz gráfica presentada al usuario y se estipula ahí
la operación a realizar, devolviendo el valor de la multiplicación. En el método
principal solamente se llama a la función Área y el programa hace el resto.
Caracterización
Los TDA que nos van a interesar de ahora en adelante son aquellos que
reflejen cierto comportamiento organizando cierta variedad de datos
estructuradamente. A esta forma estructurada de almacenar los datos será a la
que nos refiramos para caracterizar cada TDA.
Caractericemos entonces los TDA. Un TDA tendrá una parte que será invisible
al usuario la cual hay que proteger y que se puede decir que es irrelevante para
14
el uso del usuario y está constituida tanto por la maquinaria algorítmica que
implemente la semántica de las operaciones como por los datos que sirvan de
enlace entre los elementos del TDA, es decir, información interna necesaria
para la implementación que se esté haciendo para ese comportamiento del
TDA. Resumiendo podemos decir, que tanto la implementación de las
operaciones como los elementos internos del TDA serán privados al acceso
externo y ocultos a cualquier otro nivel.
La abstracción
15
Veamos los diferentes tipos de abstracción que podemos encontrar en un
programa:
2. Abstracción de datos:
Veamos entonces que son las estructuras de datos. Las estructuras de datos
son colecciones de variables, no necesariamente del mismo tipo, relacionadas
entre sí de alguna forma. Las estructuras de datos están caracterizadas por el
tipo de dato de los elementos guardados en la estructura y por la relación
definida sobre estos elementos.
16
1.2 Estructuras de datos.
Debido a que por lo general tenemos que tratar con conjuntos de datos y no
con datos simples (enteros, reales, booleanos, etc.) que por sí solos no nos
dicen nada, ni nos sirven de mucho, es necesario tratar con estructuras de
datos adecuadas a cada necesidad.
1.2.1 Definición.
17
Una estructura de datos define la organización e interrelacionamiento de estos,
y un conjunto de operaciones que se pueden realizar sobre él. Las operaciones
básicas son:
1.2.2 Clasificación.
18
pilas, colas y listas ligadas lineales. Las estructuras de datos no lineales
incluyen grafos y árboles.
Son aquellas en las que el tamaño ocupado en memoria se define antes de que
el programa se ejecute y no puede modificarse dicho tamaño durante la
ejecución del programa.
2.1 Arreglos.
19
- Unidimensionales (vectores)
- Bidimensionales (tablas o matrices)
- Multidimensionales (tres o más dimensiones)
2.1.1 Definición.
Un arreglo (array) es una colección de datos del mismo tipo, que se almacenan
en posiciones consecutivas de memoria y reciben un nombre común. Para
referirse a un determinado elemento de un array se deberá utilizar un índice,
que especifique su posición relativa en el array. Un arreglo es una colección
finita, homogénea y ordenada de elementos. Finita:Todo arreglo tiene un límite;
20
es decir, debe determinarse cuál será el número máximo de elementos que
podrán formar parte del arreglo. Homogénea: Todos los elementos del arreglo
deben ser del mismo tipo. Ordenada: Se puede determinar cuál es el primer
elemento, el segundo, el tercero,.... y el n-ésimo elemento.
2.1.2 Unidimensionales.
Para acceder a valores específicos del arreglo, use un valor de índice que
apunte al elemento deseado. Por ejemplo, para acceder al primer elemento del
arreglo calificaciones debe utilizar el valor de índice 0 (calificaciones[0]). Los
programas en C++ siempre indizan el primer elemento de un arreglo con 0 y el
último con un valor menor en una unidad al tamaño del arreglo.
2.1.3 Bidimensionales.
21
Este tipo de arreglos al igual que los anteriores es un tipo de dato estructurado,
finito ordenado y homogéneo. El acceso a ellos también es en forma directa por
medio de un par de índices.
Los arreglos bidimensionales se usan para representar datos que pueden verse
como una tabla con filas y columnas. La primera dimensión del arreglo
representa las columnas, cada elemento contiene un valor y cada dimensión
representa una relación.
22
x : array [1..5,1..7] of integer
Donde:
2.1.4 Multidimensionales.
Donde:
• i = 1 ... n
• n = No. total de dimensiones
23
Las operaciones para la resolución de problemas en arreglos pueden
clasificarse de la siguiente forma:
• Lectura
• Escritura
• Asignación
• Actualización
• Ordenación
• Búsqueda
a) LECTURA
b) ESCRITURA
c) ASIGNACION
d) ACTUALIZACION
24
1.- Insertar.
2.- Borrar.
Si N>=1 entonces
inicio
i<--1
encontrado<--falso
mientras i<=n y encontrado=falso
inicio
si arreglo[i]=valor_a_borrar entonces
inicio
encontrado<--verdadero
N<--N-1
para k desde i hasta N haz
arreglo[k]<--arreglo[k-1]
fin
en caso contrario
i<--i+1
fin
fin
Si encontrado=falso entonces
mensaje (valor no encontrado)
3.- Modificar.
Si N>=1 entonces
inicio
i<--1
encontrado<--falso
mientras i<=N y encontrado=false haz
inicio
Si arreglo[i]=valor entonces
arreglo[i]<--valor_nuevo
encontrado<--verdadero
En caso contrario
i<--i+1
fin
fin
25
Las clases de implementación de arreglos son un conjunto de caracteres
incluido el espacio en blanco, que se almacena en un área contigua de la
memoria central. La longitud de una cadena es el número de caracteres que
contiene. Una cadena vacía es la que no tiene ningún carácter. Una constante
de tipo cadena es un conjunto de caracteres válidos encerrados entre comillas.
Una variable de cadena es aquella cuyo contenido es una cadena de
caracteres. El último carácter de la cadena marca el fin de la cadena.
• · Asignación.
• · Entrada/ Salida
Leer(nombre, estado_civil)
Escribir(nombre, apellido)
Escribir(nombre, apellido)
2.2 Pilas.
Las pilas son otro tipo de estructura de datos lineales, las cuales presentan
restricciones en cuanto a la posición en la cual pueden realizarse las
inserciones y las extracciones de elementos. Una pila es una lista de elementos
en la que se pueden insertar y eliminar elementos sólo por uno de los
extremos. Como consecuencia, los elementos de una pila serán eliminados en
orden inverso al que se insertaron. Es decir, el último elemento que se metió a
la pila será el primero en salir de ella.
26
Una pila (stack en inglés) es una estructura de datos de tipo LIFO (del inglés
Last In First Out, último en entrar, primero en salir) que permite almacenar y
recuperar datos. Se aplica en multitud de ocasiones en informática debido a su
simplicidad y ordenación implícita en la propia estructura.
2.2.2 Operaciones.
Para el manejo de los datos se cuenta con dos operaciones básicas: apilar
(push), que coloca un objeto en la pila, y su operación inversa, retirar (o
desapilar, pop), que retira el último elemento apilado.
Por analogía con objetos cotidianos, una operación apilar equivaldría a colocar
un plato sobre una pila de platos, y una operación retirar a retirarlo.
27
La recursión se puede dar de dos formas:
|
| 1, N=0
Factorial <
| N*(n-1)!, N>0
|
sp <--0
mientras n <> 1 haz
push(pila,n)
n<--n-1
mientras sp <> 0 haz
factorial<--factorial*pop(pila)
|
| 0 , si a < b
Q <
| Q(a-b,b)+1, si a<=b
|
sp<--0
Q<--0
lee(a), lee(b)
mientras a>=b haz
push(pila,1)
a<--a-b
mientras sp< > 0 haz
Q<-- Q + pop(pila)
2.3 Colas.
28
Una cola es una estructura de almacenamiento, donde la podemos considerar
como una lista de elementos, en la que éstos van a ser insertados por un
extremo y serán extraídos por otro.
Las colas son estructuras de tipo FIFO (first-in, first-out), ya que el primer
elemento en entrar a la cola será el primero en salir de ella.
2.3.1 Definición.
Una cola es una estructura de datos, caracterizada por ser una secuencia de
elementos en la que la operación de inserción push se realiza por un extremo y
la operación de extracción pop por el otro. También se le llama estructura FIFO
(del inglés First In First Out), debido a que el primer elemento en entrar será
también el primero en salir.
2.3.2 Tipos.
• Bicolas: son colas en donde los nodos se pueden añadir y quitar por
ambos extremos; se les llama DEQUE (Double Ended QUEue). Para
representar las bicolas lo podemos hacer con un array circular con Ini y
Fin que apunten a cada uno de los extremos. Hay variantes:
29
1 De dos elementos siempre se atenderá antes al que tenga mayor
prioridad.
2 Si dos elementos tienen la misma prioridad se atiende primero el que
llego antes.
In- Sirve para ingresar los valores que se van agregando, este valor será el
primero en la cola y se quedara con el apuntador externo "front", los demás
serán parte de la cola y el ultimo que este en la cola será apuntado por el
apuntador externo "end".
Algoritmo:
Vacía =3
sino =8
3. crear nodo
4. asignación de valor
7. fin
30
8. crear nodo
9. asignación de valor
10. el apuntador externo "nuevo" asigna al apuntador interno "next" del nodo del nuevo
valor apuntar al nodo que esta apuntando el apuntador externo "end".
12. el apuntador externo "end" asigna al apuntador interno "next" apuntar a nulo
13. fin
Out- Sirve para sacar el primer valor que fue ingresado. Si hay solo un valor en
la estructura, simplemente ya no hay mas valores en la pila. Si se intenta sacar
un valor cuando no hay valores se avisara que no hay valores.
31
Algoritmo:
Vacía =3
Solo 1 valor =5
Sino =7
4. fin
5. se muestra el valor por borrar y los apuntadores externos "end" y "front" serán nulos
6. fin
7. se muestra el valor por borrar y se inicializa un ciclo para desconectar el primer valor y
hacer el segundo como primero.
8. y para eso el apuntador externo "front" se actualiza con al ayuda del apuntador externo
"aux" y asigna al apuntador interno "next" apuntar a nulo
9. fin
32
Para el algoritmo #7 el diseño de la estructura seria:
33
2.3.2.2 Colas circulares.
Las colas lineales tienen un grave problema, como las extracciones sólo
pueden realizarse por un extremo, puede llegar un momento en que el
apuntador A sea igual al máximo número de elementos en la cola, siendo que
al frente de la misma existan lugares vacíos, y al insertar un nuevo elemento
nos mandará un error de overflow (cola llena).
Las condiciones que debemos tener presentes al trabajar con este tipo de
estructura son las siguientes:
ALGORITMO DE INICIALIZACIÓN
F < -- 0
A<-- 0
34
ALGORITMO PARA EXTRAER
Si F=0 entonces
mensaje (underflow)
en caso contrario
x <-- cola[F]
si F=A entonces
F <-- 0
A<-- 0
en caso contrario
si F=máximo entonces
F <--1 en caso contrario F <-- F+1
Algoritmo de Inicialización
F < -- 1
A <-- 0
Si A=máximo entonces
mensaje (overflow)
en caso contrario
A <--A+1
cola[A]<-- valor
35
Algoritmo para Extraer
Si F>A entonces
mensaje (underflow)
en caso contrario
mensaje (frente/atrás)
si frente entonces
x <-- cola[F]
F <-- F+1
en caso contrario
x <-- cola[A]
A <-- A-1
Algoritmo de Inicialización
F <--1
A <-- 0
Si F>A entonces
mensaje (overflow)
en caso contrario
mensaje (Frente/Atrás)
si Frente entonces
cola[F] <--valor
en caso contrario
A <-- A+1
cola[A] <--valor
Si F=0 entonces
mensaje (underflow)
en caso contrario
x <--cola[F]
F <-- F+1
2.3.3 Operaciones.
Las operaciones que nosotros podemos realizar sobre una cola son las
siguientes:
• Inserción.
36
• Extracción.
Las inserciones en la cola se llevarán a cabo por atrás de la cola, mientras que
las eliminaciones se realizarán por el frente de la cola (hay que recordar que el
primero en entrar es el primero en salir).
se desencola, obteniendo un 3:
se encola un 7:
37
Como alternativa se usa el array circular. Esta estructura nos permite volver al
comienzo del array cuando se llegue al final, ya sea el índice de entrada o el
índice de salida.
UNIDAD 3 LISTAS ENLAZADAS
El campo liga, que es de tipo puntero, es el que se usa para establecer la liga
con el siguiente nodo de la lista. Si el nodo fuera el último, este campo recibe
como valor NIL (vacío).
Las operaciones que podemos realizar sobre una lista enlazada son las
siguientes:
Recorrido.
Esta operación consiste en visitar cada uno de los nodos que forman la lista .
Para recorrer todos los nodos de la lista, se comienza con el primero, se toma
el valor del campo liga para avanzar al segundo nodo, el campo liga de este
nodo nos dará la dirección del tercer nodo, y así sucesivamente.
Inserción.
38
Insertar un nodo al final.
Borrado.
Búsqueda.
Esta operación consiste en visitar cada uno de los nodos, tomando al campo
liga como puntero al siguiente nodo a visitar.
3.1.1 Simples.
En esta sección se mostrarán algunos algoritmos sobre listas simples sin nodo
de cabecera y con nodo de cabecera.
Una lista con nodo de cabecera es aquella en la que el primer nodo de la lista
contendrá en su campo dato algún valor que lo diferencíe de los demás nodos
(como : *, -, +, etc). Un ejemplo de lista con nodo de cabecera es el siguiente:
En el caso de utilizar listas con nodo de cabecera, usaremos el apuntador CAB para
hacer referencia a la cabeza de la lista.
Para el caso de las listas sin nodo de cabecera, se usará la expresión TOP para
referenciar al primer nodo de la lista, y TOP(dato), TOP(liga) para hacer referencia al
dato almacenado y a la liga al siguiente nodo respectivamente.
Algoritmo de Creación
top<--NIL
repite
new(p)
leer(p(dato))
si top=NIL entonces
top<--p
en caso contrario
q(liga)<--p
p(liga)<--NIL
q<--p
mensaje('otro nodo?')
leer(respuesta)
hasta respuesta=no
39
Algoritmo para Recorrido
p<--top
mientras p<>NIL haz
escribe(p(dato))
p<--p(liga:)
p<--top
mientras p(liga)<>NIL haz
p<--p(liga)
new(q)
p(liga)<--q
q(liga)<--NIL
p<--top
mensaje(antes/despues)
lee(respuesta)
si antes entonces
mientras p<>NIL haz
si p(dato)='x' entonces
new(q)
leer(q(dato))
q(liga)<--p
si p=top entonces
top<--q
en caso contrario
r(liga)<--q
p<--nil
en caso contrario
r<--p
p<--p(link)
si despues entonces
p<--top
mientras p<>NIL haz
si p(dato)='x' entonces
new(q)
leer(q(dato))
q(liga)<--p(liga)
p(liga)<--q
p<--NIL
en caso contrario
p<--p(liga)
p<--top
mientras p(liga)<>NIL haz
40
p<--p(liga)
new(q)
p(liga)<--q
q(liga)<--NIL
p<--top
leer(valor_a_borrar)
mientras p<>NIL haz
si p(dato)=valor_a_borrar entonces
si p=top entonces
si p(liga)=NIL entonces
top<--NIL
en caso contrario
top(liga)<--top(liga)
en caso contrario
q(liga)<--p(liga)
dispose(p)
p<--NIL
en caso contrario
q<--p
p<--p(liga)
new(cab)
cab(dato)<--'*'
cab(liga)<--NIL
q<--cab
repite
new(p)
leer(p(dato))
p(liga)<--NIL
q<--p
mensaje(otro nodo?)
leer(respuesta)
hasta respuesta=no
leer(valor_a_borrar)
p<--cab
q<--cab(liga)
mientras q<>NIL haz
si q(dato)=valor_a_borrar entonces
p<--q(liga)
dispose(q)
q<--NIL
en caso contrario
p<--q
41
q<--q(liga)
3.1.2 Dobles.
Listas dobles lineales. En este tipo de lista doble, tanto el puntero izquierdo
del primer nodo como el derecho del último nodo apuntan a NIL.
Listas dobles circulares. En este tipo de lista doble, el puntero izquierdo del
primer nodo apunta al último nodo de la lista, y el puntero derecho del último
nodo apunta al primer nodo de la lista.
Debido a que las listas dobles circulares son más eficientes, los algoritmos que
en esta sección se traten serán sobre listas dobles circulares.
42
Algoritmo de creación
top<--NIL
repite
si top=NIL entonces
new(p)
lee(p(dato))
p(ld)<--p
p(li)<--p
top<--p
en caso contrario
new(p)
lee(p(dato))
p(ld)<--top
p(li)<--p
p(ld(li))<--p
mensaje(otro nodo?)
lee (respuesta)
hasta respuesta=no
--RECORRIDO A LA DERECHA.
p<--top
repite
escribe(p(dato))
p<--p(ld)
hasta p=top
--RECORRIDO A LA IZQUIERDA.
p<--top
repite
escribe(p(dato))
p<--p(li)
hasta p=top(li)
43
Algoritmo para insertar antes de 'X' información
p<--top
mensaje (antes de ?)
lee(x)
repite
si p(dato)=x entonces
new(q)
leer(q(dato))
si p=top entonces
top<--q
q(ld)<--p
q(li)<--p(li)
p(ld(li))<--q
p(li)<--q
p<--top
en caso contrario
p<--p(ld)
hasta p=top
p<--top
mensaje(despues de ?)
lee(x)
repite
si p(dato)=x entonces
new(q)
lee(q(dato))
q(ld)<--p(ld)
q(li)<--p
p(li(ld))<--q
p(ld)<--q
p<--top
en caso contrario
p<--p(ld)
hasta p=top
p<--top
mensaje(Valor a borrar)
lee(valor_a_borrar)
repite
si p(dato)=valor_a_borrar entonces
p(ld(li))<--p(ld)
p(li(ld))<--p(li)
si p=top entonces
si p(ld)=p(li) entonces
top<--nil
en caso contrario
top<--top(ld)
dispose(p)
p<--top
44
en caso contrario
p<--p(ld)
hasta p=top
3.1.3 Circulares.
Algoritmo de creación
repite
new(p)
lee(p(dato))
si top=nil entonces
top<--p
q<--p
en caso contrario
q(liga)<--p
q<--p
p(liga)<--top
mensaje (otro nodo ?)
lee(respuesta)
hasta respuesta=no
p<--top
repite
escribe(p(dato))
p<--p(liga)
hasta p=top
45
Algoritmo para insertar antes de 'X' información
new(p)
lee(p(dato))
si top=nil entonces
top<--p
p(liga)<--top
en caso contrario
mensaje(antes de ?)
lee(x)
q<--top
r<--top(liga)
repite
si q(dato)=x entonces
p(liga)<--q
r(liga)<--p
si p(liga)=top entonces
top<--p
q<--q(liga)
r<--r(liga)
hasta q=top
new(p)
lee(p(dato))
mensaje(después de ?)
lee(x)
q<--top
r<--top(liga)
repite
si q(dato)=x entonces
q(liga)<--p
p(liga)<--r
q<--q(liga)
r<--r(liga)
hasta q=top
46
Algoritmo para borrar
mensaje(valor a borrar )
lee(valor_a_borrar)
q<--top
r<--top
p<--top
mientras q(liga)<>top haz
q<--q(liga)
repite
si p(dato)=valor_a_borrar entonces
si p=top entonces
si top(liga)=top entonces
top<--NIL
en caso contrario
top<--top(liga)
q(liga)<--top
en caso contrario
r(liga)<--p(liga)
dispose(p)
p<--top
en caso contrario
r<--p
p<--p(liga)
hasta p=top
3.1.4 Multilistas.
Juan Matemático 1
Daniel Físico 2
José Matemático 2
Pascual Ingeniero 3
Miguel Ingeniero 1
47
Felipe Abogado 2
Ejemplo Las declaraciones para una lista enlazada de nombres son las
siguientes:
TYPE
VAR
Lista : TipoListaEnlazada;
En este ejemplo, la variable Lista será un puntero al primer nodo de una lista o
la constante puntero NIL. Nótese, además, que la definición del tipo puntero
PteroLista precede a la definición del tipo registro NodoLista. Esta es la única
situación en la que se permite utilizar un identificador (en este caso, NodoLista)
antes de definirlo.
Para construir una lista enlazada debemos ser capaces de crear una lista
vacía.
48
BEGIN
Lista := NIL;
END
Comprobar si una lista enlazada está vacía
Dado que una lista enlazada vacía se representa mediante un puntero nulo,
resulta sencillo determinar si una lista enlazada está vacía o no.
Uno de los métodos para construir una lista enlazada consiste en añadir
repetidamente elementos al principio de la lista, comenzando con una lista
vacía.
BEGIN
new( PteroTemp );
PteroTerm^.Datos := Elem;
PteroTemp^.Sig := Lista;
Lista := PteroTerm
END
• Para movernos por una lista enlazada, la idea es variar una variable
puntero dentro de una estructura de repetición, utilizando los campos de
enlaces para saltar de un nodo al siguiente.
BEGIN
PteroAct := Lista;
WHILE PteroAct <> NIL DO
49
BEGIN
write( PteroAct^.Datos );
PteroAct := PteroAct^.Sig
END END
UNIDAD 4 ESTRUCTURAS NO LINEALES
4.1 Árboles.
A los árboles ordenados de grado dos se les conocen como árboles binarios ya
que cada nodo del árbol no tendrá más de dos descendientes directos. Las
aplicaciones de los árboles binarios son muy variadas ya que se les puede
utilizar para representar una estructura en la cual es posible tomar decisiones
con dos opciones en distintos puntos.
4.1.1 Definición.
• Caso base: un árbol con sólo un nodo (es a la vez raíz del árbol y hoja).
Una sucesión de nodos del árbol, de forma que entre cada dos nodos
consecutivos de la sucesión haya una relación de parentesco, decimos que es
un recorrido árbol.
50
Existen dos recorridos típicos para listar los nodos de un árbol: primero en
profundidad y primero en anchura. En el primer caso, se listan los nodos
expandiendo el hijo actual de cada nodo hasta llegar a una hoja, donde se
vuelve al nodo anterior probando por el siguiente hijo y así sucesivamente.
En el segundo, por su parte, antes de listar los nodos de nivel n + 1 (a distancia
n + 1 aristas de la raíz), se deben haber listado todos los de nivel n. Otros
recorridos típicos del árbol son preorden, postorden e inorden:
Sin embargo la más utilizada es la primera, puesto que es la más natural para
tratar este tipo de estructuras.
Los nodos del árbol binario serán representados como registros que
contendrán como mínimo tres campos. En un campo se almacenará la
información del nodo. Los dos restantes se utilizarán para apuntar al subárbol
izquierdo y derecho del subárbol en cuestión.
51
El algoritmo de creación de un árbol binario es el siguiente:
Procedimiento crear(q:nodo)
inicio
mensaje("Rama izquierda?")
lee(respuesta)
si respuesta = "si" entonces
new(p)
q(li) <-- nil
crear(p)
en caso contrario
q(li) <-- nil
mensaje("Rama derecha?")
lee(respuesta)
si respuesta="si" entonces
new(p)
q(ld)<--p
crear(p)
en caso contrario
q(ld) <--nil
fin
INICIO
new(p)
raiz<--p
crear(p)
FIN
Los árboles pueden ser construidos con estructuras estáticas y dinámicas. Las
estáticas son arreglos, registros y conjuntos, mientras que las dinámicas están
representadas por listas.
52
ancestro, etc.. Formalmente se define un árbol de tipo T como una estructura
homogénea que es la concatenación de un elemento de tipo T junto con un
número finito de árboles disjuntos, llamados subárboles. Una forma particular
de árbol puede ser la estructura vacía.
Los árboles tienen una gran variedad de aplicaciones. Por ejemplo, se pueden
utilizar para representar fórmulas matemáticas, para organizar adecuadamente
la información, para construir un árbol genealógico, para el análisis de circuitos
eléctricos y para numerar los capítulos y secciones de un libro.
A. B. Distinto.
A. B. Similares.
A. B. Equivalentes.
A. B. Completos.
A. B. DISTINTO
Se dice que dos árboles binarios son distintos cuando sus estructuras son
diferentes. Ejemplo:
53
A. B. SIMILARES
Dos árboles binarios son similares cuando sus estructuras son idénticas, pero
la información que contienen sus nodos es diferente. Ejemplo:
A. B. EQUIVALENTES
Son aquellos árboles que son similares y que además los nodos contienen la
misma información. Ejemplo:
A. B. COMPLETOS
Son aquellos árboles en los que todos sus nodos excepto los del ultimo nivel,
tiene dos hijos; el subárbol izquierdo y el subárbol derecho.
4.1.3.1 Preorden.
PREORDEN
• Examinar la raíz.
• Recorrer el subárbol izquierdo en preorden.
• recorrer el subárbol derecho en preorden.
54
4.1.3.2 Inorden.
INORDEN
4.1.3.3 Posorden.
POSTORDEN
Un árbol está balanceado si para cada uno de sus nodos se tiene que las
alturas de sus dos subárboles difieren a lo más en 1.
• Arbol balanceado por altura: en dónde todos los hijos o nodos hoja se
intentan mantener a la misma distancia de la raíz.
Propiedades:
55
2) Todas las aristas de G son puentes.
3) ½ A½ = n - 1.
Los árboles forman una de las subclases de las gráficas de uso más amplio. En
el terreno de la computación los árboles sirven para organizar y relacionar los
datos de una base de datos.
Las listas tienen un elemento en cada posición. Los árboles tienen una etiqueta
en cada nodo (algunos autores distinguen entre árboles con y sin etiquetas. Un
árbol sin etiquetas tiene sentido aunque en la inmensa mayoría de los
problemas necesitaremos etiquetar los nodos. Es por ello por lo que a partir de
ahora sólo haremos referencia a árboles etiquetados).
56
4.2 Grafos
Hoy en día podemos ver muchas cosas que nos pueden parecer de lo mas
cotidianas, carreteras, líneas telefónicas, líneas de televisión por cable, el
transporte colectivo metro, circuitos eléctricos de nuestras casas, automóviles,
y tantas cosas mas; lo que no pensamos frecuentemente es que estos forman
parte de algo que en matemáticas se denomina como grafos.
En este trabajo se tratará de explicar lo que son los grafos, sus tipos, y algunas
derivaciones de ellos, así como su representación gráfica y en algunos casos,
su representación en algún programa informático, así como en la memoria.
4.2.1 Definición.
57
4.2.2 Tipos de grafos.
Ejemplos
G1 = (V1, A1)
V1 = {1, 2, 3, 4} A1 = {(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)}
G2 = (V2, A2)
V2 = {1, 2, 3, 4, 5, 6} A2 = {(1, 2), (1, 3), (2, 4), (2, 5), (3, 6)}
G3 = (V3, A3)
V3 = {1, 2, 3} A3 = { <1, 2>, <2, 1>, <2, 3> }
Grafo regular: Aquel con el mismo grado en todos los vértices. Si ese
grado es k lo llamaremos k-regular.
Grafo completo: Aquel con una arista entre cada par de vértices. Un grafo
completo con n vértices se denota Kn.
58
A continuación ponemos los dibujos de K1,2, K3,3, y K2,5
Grafo nulo: Se dice que un grafo es nulo cuando los vértices que lo
componen no están conectados, esto es, que son vértices aislados.
Grafos Platónicos: Son los Grafos formados por los vértices y aristas de
los cinco sólidos regulares (Sólidos Platónicos), a saber, el tetraedro, el cubo,
el octaedro, el dodecaedro y el icosaedro.
59
GRAFOS EULERIANOS.
GRAFOS CONEXOS.
60
La matriz de adyacencia, que se obtuvo a partir del grafo anterior es la
siguiente:
• Creación.
• Inserción.
• Búsqueda.
• Eliminación.
61
En esta sección, continuaremos utilizando los apuntadores que se usaron en
las secciones anteriores. TOP para hacer referencia al primer nodo, LD para
indicar liga derecha y LA para indicar liga abajo, por último usaremos los
apuntadores P y Q para hacer referencia a los nuevos nodos que vayan a ser
usados.
ALGORITMO DE CREACION.
repite
si top=NIL entonces
new(top)
top(la)<--NIL
top(ld)<--NIL
lee(top(dato))
q<--top
en caso contrario
new(p)
p(ld)<--NIL
p(la)<--NIL
q(la)<--p
lee(p(dato))
q<--p
mensaje(otro vertice ?)
lee(respuesta)
hasta repuesta=no
p<--top
mientras p<>NIL haz
mensaje(tiene vértices adyacentes p(dato) ?)
lee(respuesta)
si respueta=si entonces
repite
new(q)
lee(q(dato))
q(ld)<--p(ld)
p(ld)<--q
mensaje(otro vértice ?)
lee(respuesta2)
hasta respuesta2=no
p<--p(la)
ALGORITMO DE INSERCION
mensaje(valor a insertar ?)
lee(valor_a_insertar)
si top<>NIL entonces
p<--top
mientras p(la)<>NIL haz
p<--p(la)
new(q)
62
lee(q(dato))
p(la)<--q
q(la)<--NIL
mensaje(Hay vértices adyacentes?)
lee(respuesta)
si respuesta=si entonces
mensaje(Cuantos vértices?)
lee(número_vértices)
desde i=1 hasta número_vértices haz
new(p)
lee(p(dato))
q(ld)<--p
q<--q(ld)
en caso contrario
mensaje(no existe lista)
ALGORITMO DE BUSQUEDA
mensaje(vértice a buscar)
lee(vértice_a_buscar)
p<--top
repite
si p(dato)=vértice_a_buscar entonces
repite
p<--p(ld)
escribe(p(dato))
hasta p(ld)=NIL
en caso contrario
p<--(la)
hasta p=NIL
ALGORITMO DE BORRADO
mensaje(vértice a borrar ?)
lee(vértice_a_borrar)
p&Lt--top
r<--p
q<--p
sw<--falso
repite
si p(dato)=vértice_a_borrar entonces
si p=top entonces
top<--top(la)
r<--top
sw<--verdadero
en caso contrario
r(la)<--p(la)
repite
p<--p(ld)
dispose(q)
q<--p
63
hasta p=NIL
si sw=verdadero entonces
p<--r
q<--p
en caso contrario
p<--r(la)
q<--p
en caso contrario
r<--p
repite
q<--p(ld)
si q(dato)=vértice_a_borrar entonces
p(ld)<--q(ld)
dispose(q)
q<--p
en caso contrario
p<--p(ld)
hasta p=NIL
64
BIBLIOGRAFIAS
65