trabajo investigacion de algoritmos

72
TEORÍA DE ALGORITMOS II VILLALOBOS ESTUDILLO WILLIAM PROFRA.: PÉREZ VILLANUEVA JUANA 10/07/2016 CENTRO UNIVERSITARIO SALINA CRUZ

Upload: wiliam-villalobos

Post on 05-Aug-2016

220 views

Category:

Documents


1 download

DESCRIPTION

En esta presente investigación contiene los temas: Estructura de datos Externas, Archivos, Búsqueda y ordenamiento y Programación de aplicaciones.

TRANSCRIPT

TEORÍA DE ALGORITMOS II VILLALOBOS ESTUDILLO WILLIAM

PROFRA.: PÉREZ VILLANUEVA JUANA

10/07/2016

CENTRO UNIVERSITARIO SALINA CRUZ

Contenido 1. ESTRUCTURA DE DATOS EXTERNOS, ARCHIVOS ................................................................................... 3

1.1 Conceptos y Definiciones .................................................................................................................... 3

1.2 Características ..................................................................................................................................... 3

2.2.1 Residencia ..................................................................................................................................... 3

2.2.2 Permanencia ................................................................................................................................. 3

2.2.3 Portabilidad .................................................................................................................................. 3

1.2.3 Capacidad ..................................................................................................................................... 4

1.3 Clasificación ......................................................................................................................................... 9

1.3.1 Permanentes ............................................................................................................................... 9

1.3.1.1 De constantes .......................................................................................................................... 9

1.3.1.2 De situación: ............................................................................................................................ 9

1.3.1.2 Maestros: ................................................................................................................................... 9

1.3.1.3 Históricos: ................................................................................................................................. 9

1.3.2 De movimientos .......................................................................................................................... 9

1.3.3 De trabajo: .................................................................................................................................. 9

1.4 Organización ........................................................................................................................................ 9

1.4.1 Secuencia ..................................................................................................................................... 9

1.4.2 Random o directo ....................................................................................................................... 10

1.4.3 Indexada ..................................................................................................................................... 10

2. Búsqueda y Ordenamiento ...................................................................................................................... 10

2.1 Algoritmo de búsqueda ..................................................................................................................... 10

2.1.1 Secuencial ................................................................................................................................... 11

2.1.2 Binaria ......................................................................................................................................... 11

2.1.3 Cálculo de dirección ................................................................................................................... 12

2.2 Ordenamiento ................................................................................................................................... 14

2.2.1 Optimo teórico para ordenamiento de tablas ........................................................................... 17

2.2.2 Intercambio simple ..................................................................................................................... 18

2.2.3 Algoritmo de la burbuja.............................................................................................................. 19

2.2.4 Shell sort ..................................................................................................................................... 22

2.2.5 Quick sort................................................................................................................................... 23

2.2.6 Tree sort o Heap sort .................................................................................................................. 25

2.2.7 Ordenamiento pot intercalation ................................................................................................ 26

2.2.8 Ordenamiento por distribución .................................................................................................. 28

2.3 Ordenamiento externo ...................................................................................................................... 28

2.3.1 El torneo de tenis para ordenamiento externo .......................................................................... 28

2.3.2 Interacción con lotes. Algoritmo balanceado............................................................................. 29

2.3.3 El algoritmo poli fase para interacción por lote ......................................................................... 29

2.3.4 El algoritmo de cascada .............................................................................................................. 30

2.4 Árboles balanceados ......................................................................................................................... 30

2.4.1 Definiciones ................................................................................................................................ 30

2.4.2 Árboles AVL ................................................................................................................................ 33

2.4.3 Árboles tipo B ............................................................................................................................. 37

2.5 Dispersión al azar desmenuzamiento o hassing................................................................................ 45

2.5.1 Algoritmos .................................................................................................................................. 46

2.5.2 Funciones de dispersión ............................................................................................................. 47

2.5.3 Manejo de colisiones .................................................................................................................. 47

2.5.4 Manejo de sobre flujo ................................................................................................................ 48

2.5.5 Un corrector de ortografía ......................................................................................................... 49

3. Programación de aplicaciones ................................................................................................................. 49

3.1 Descripción del lenguaje a utilizar ..................................................................................................... 49

3.1.1 Estructura de un programa y reglas sintácticas ......................................................................... 50

3.1.2 Palabras reservadas .................................................................................................................... 53

3.1.3 Tipos de datos y variables .......................................................................................................... 54

3.1.4 Instrucciones asociadas a: .......................................................................................................... 56

3.1.4.1 Operaciones primitivas ............................................................................................................ 56

3.1.4.2 Estructuras de control ............................................................................................................. 57

3.1.4.3 Operaciones aritméticas.......................................................................................................... 57

3.1.4.4 Funciones matemáticas ........................................................................................................... 58

3.1.4.5 Manejo de caracteres .............................................................................................................. 59

3.1.4.7 Estructura de datos ................................................................................................................. 61

3.1.4.7 Operaciones especiales ........................................................................................................... 61

3.1.5 Subrutinas / procedimientos ...................................................................................................... 61

3.2.1 Funciones.................................................................................................................................... 62

3.2 Estructura de los datos internos ....................................................................................................... 64

3.2.1 Vectores ...................................................................................................................................... 65

3.2.2 Matrices ...................................................................................................................................... 70

3.2.3 Poliedros ..................................................................................................................................... 70

1. ESTRUCTURA DE DATOS EXTERNOS, ARCHIVOS

1.1 Conceptos y Definiciones

Concepto:

Archivo: Para poder acceder a determinada información en cualquier momento, se

necesitará que ella esté depositada en soportes físicos los cuales la almacenan en forma

permanente. Este es el caso de la memoria externa o auxiliar como ser disquete, disco

duro, cinta magnética, etc.-, en las cuales sin necesidad de estar conectadas a la corriente

eléctrica, la información permanece allí. La forma de guardar los datos en estos

dispositivos auxiliares es mediante unas estructuras llamadas archivos o ficheros.

Definición:

“Es una estructura externa de datos, constituida por un conjunto de elementos

todos del mismo tipo, organizados en unidades de acceso, llamadas registros.”

1.2 Características

Residen en soporte de almacenamiento externo.

La información se almacena de forma permanente.

Alta capacidad de almacenamiento de datos.

Independencia de la información que guardan respecto a los programas

que los usan.

2.2.1 Residencia

La forma de guardar los datos en estos dispositivos auxiliares es mediante unas

estructuras llamadas archivos o ficheros.

2.2.2 Permanencia

Para poder acceder a determinada información en cualquier momento, se

necesitará que ella esté depositada en soportes físicos los cuales la almacenan en

forma permanente.

2.2.3 Portabilidad

Este es el caso de la memoria externa o auxiliar como ser disquete, disco duro,

cinta magnética, etc.-, en las cuales sin necesidad de estar conectadas a la

corriente eléctrica, la información permanece allí. La forma de guardar los datos

en estos dispositivos auxiliares es mediante unas estructuras llamadas archivos o

ficheros.

1.2.3 Capacidad

DISQUETES

USB

Estas memorias se han convertido en el sistema de almacenamiento y transporte

personal de datos más utilizado, desplazando en este uso a los tradicionales

disquetes y a los CD. Se pueden encontrar en el mercado fácilmente memorias

de 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 GB, y hasta 1 TB.2 Las memorias con

capacidades más altas pueden aún estar, por su precio, fuera del rango del

"consumidor doméstico". Esto supone, como mínimo, el equivalente a 180 CD de

700 MB o 91 000 disquetes de 1440 KiBaproximadamente.

DISCO DURO

Capacidad.- La capacidad de almacenamiento de los discos duros ha ido

aumentando a través de los años, desde unos cuantos megabytes hasta llegar en

la actualidad a estandarizarse en varios cientos de gigabytes e incluso terabytes.

CD

DVD

MICRO SD

MEMORY STICK

Las capacidades comerciales actuales en nuestro país son:

Formato de

memoria Capacidades en MB / GB

Memory Stick 64 Megabytes (MB), 128 MB

MS Pro Duo 512 MB, 1 Gigabyte (GB), 2 GB, 4 GB, 8 GB, 16 GB, 32 GB

MS Pro Magic Gate 256 MB, 512 MB, 1 GB, 2 GB, 4 GB

MS micro - M2 512 MB, 1 GB, 2 GB, 4 GB, 8 GB, 16 GB

BLU-RAY

Normalmente una capa de disco Blu-Ray puede almacenar cerca de 25 GB de

información, habiendo discos ópticos de esa tecnología que disponen cuatro capas

y que por tanto llegan a almacenar 100 GB de información total. La velocidad actual

de transferencia de datos que tienen estos discos viene a ser de 36 mbps,

analizándose la posibilidad de aumentar esta velocidad a unos 82 mbps.

La superficie de la que consta el Blu-Ray es resistente a todo tipo de rayaduras

debido a un material llamado como Durabis que viene a formar la última capa de

protección física de estos discos

1.3 Clasificación

Según su función o uso que se hace de ellos:

1.3.1 Permanentes: Su información varía poco en el tiempo

1.3.1.1 De constantes: Consultas. Baja o nula modificación (Códigos

Postales).

1.3.1.2 De situación: estado actual de la información (F. maestros)

1.3.1.2 Maestros: Estos contienen información que varía poco. En algunos casos

es preciso actualizarlos periódicamente.

1.3.1.3 Históricos: Nunca se modifican (Rentas de años anteriores)

1.3.2 De movimientos: Información para actualizar ficheros permanentes

(compra-ventas diarias).

1.3.3 De trabajo: Tienen una vida limitada, normalmente menor que la duración

de la ejecución de un programa. Su utilizan como auxiliares de los anteriores.

1.4 Organización

Organización de Archivos: La organización de un archivo define la forma en la que

los registros se disponen sobre el soporte de almacenamiento, o también se define

la organización como la forma en que se estructuran los datos en un archivo. En

general, se consideran tres organizaciones fundamentales:

•Organización secuencial

•Organización directa o aleatoria (random)

•Organización secuencial indexada

Obs: En Pascal estándar los archivos son de Org. Secuencial Turbo Pascal

permite el acceso aleatorio o directo en todos los archivos (excepto en archivos

de textos).

1.4.1 Secuencia

Organización secuencial No es más que una sucesión de registros almacenados en

forma consecutiva sobre un soporte externo. Los registros están ubicados

físicamente en una secuencia usualmente fijada por uno o más campos de control

contenidos dentro de cada registro, en forma ascendente o descendente. Esta

organización tiene el último registro en particular, contiene una marca (en general

un asterisco) de fin de archivo, la cual se detecta con funciones tipo EOF (end of

file) o FDA (Fin de Archivo).

1.4.2 Random o directo

Los datos se colocan y se acceden aleatoriamente mediante su posición, es decir,

indicando el lugar relativo que ocupan dentro del conjunto de posiciones posibles.

En esta organización se pueden leer y escribir registros, en cualquier orden y en

cualquier lugar. Inconvenientes:

a) Establecer la relación entre la posición que ocupa un registro y su contenido.

b) Puede desaprovecharse parte del espacio destinado al archivo. Ventaja:

Rapidez de acceso a un registro cualquiera.

1.4.3 Indexada

Un archivo con esta organización consta de tres áreas: Área de índices Área

primaria Área de excedentes (overflow)

Ventaja:

a) Rápido acceso, y, además, el sistema se encarga de relacionar la posición de

cada registro con su contenido por medio del área de índices.

b) Gestiona las áreas de índices y excedentes.

Desventajas:

a) Necesidad de espacio adicional para el área de índices.

b) el desaprovechamiento de espacio que resulta al quedar huecos intermedios

libres después de sucesivas actualizaciones.

2. Búsqueda y Ordenamiento

2.1 Algoritmo de búsqueda

Con mucha frecuencia los programadores trabajan con grandes cantidades de

datos almacenados en arrays y registros, y por ello será necesario determinar si

un array contiene un valor que coincida con un cierto valor clave. El proceso de

encontrar un elemento específico de un array se denomina búsqueda. En esta

sección se examinarán dos técnicas de búsqueda: búsqueda lineal o secuencial, la

técnica más sencilla, y búsqueda binaria o dicotómica, la técnica más eficiente.

2.1.1 Secuencial

La búsqueda secuencial busca un elemento de una lista utilizando un valor destino

llamado clave.

En una búsqueda secuencial (a veces llamada búsqueda lineal), los elementos de

una lista o vector se exploran (se examinan) en secuencia, uno después de otro.

La búsqueda secuencial es necesaria, por ejemplo, si se desea encontrar la

persona cuyo número de teléfono es 958-220000 en un directorio o listado

telefónico de su ciudad. Los directorios de teléfonos están organizados

alfabéticamente por el nombre del abonado en lugar de por números de teléfono,

de modo que deben explorarse todos los números, uno después de otro, esperando

encontrar el número 958-220000.

El algoritmo de búsqueda secuencial compara cada elemento del array con la clave

de búsqueda.

Dado que el array no está en un orden prefijado, es probable que el elemento a

buscar pueda ser el primer elemento, el último elemento o cualquier otro. De

promedio, al menos el programa tendrá que comparar la clave de búsqueda con la

mitad de los elementos del array. El método de búsqueda lineal funcionará bien

con arrays pequeños o no ordenados. La eficiencia de la búsqueda secuencial es

pobre, tiene complejidad lineal, O(n).

2.1.2 Binaria

La búsqueda secuencial se aplica a cualquier lista. Si la lista está ordenada, la

búsqueda binaria proporciona una técnica de búsqueda mejorada. Una búsqueda

binaria típica es la búsqueda de una palabra en un diccionario. Dada la palabra, se

abre el libro cerca del principio, del centro o del final dependiendo de la primera

letra del primer apellido o de la palabra que busca. Se puede tener suerte y acertar

con la página correcta; pero, normalmente, no será así y se mueve el lector a la

página anterior o posterior del libro. Por ejemplo, si la palabra comienza con «J» y

se está en la «L» se mueve uno hacia atrás. El proceso continúa hasta que se

encuentra la página buscada o hasta que se descubre que la palabra no está en la

lista.

Una idea similar se aplica en la búsqueda en una lista ordenada. Se sitúa la lectura

en el centro de la lista y se comprueba si la clave coincide con el valor del

elemento central. Si no se encuentra el valor de la clave, se sigue la búsqueda uno

en la mitad inferior o superior del elemento central de la lista. En general, si los

datos de la lista están ordenados se puede utilizar esa información para acortar el

tiempo de búsqueda.

2.1.3 Cálculo de dirección

ALGORITMO DE ORDENAMIENTO POR CALCULO DE DIRECCIONES

PROCEDURE HASH;

TYPE

TIPO.NODO=RECORD;

NEXT,INFO: INTEGER;

END;

VAR

NODO:ARRAY [1...N] OF TIPO.NODO

F: ARRAY [O...9] OF INTEGER

P,PRIM,Q,I,J,AVAIL,Y:INTEGER;

BEGIN

FOR I:=1 TO N-1 DO

BEGIN

NODO[I].INFO:=X[I];

NODO[1].NEXT:=I+1;

END;

NODO[N].INFO:=X[N];

NODO[N].NEXT:=0;

FOR I:=0 TO 9 DO

F[I]:=0;

FOR I:=1 TO N DO

BEGIN

Y:=X[I]; PRIM:=Y DIV 10;

INSERT_LISTA (F(PRIM),Y);

END;

I:=0;

FOR J:=0 TO N DO

BEGIN

P:=F[J];

WHILE P <> 0 DO

BEGIN

I:=I+1;

X[I]:=NODO[P].INFO;

P:=NODO[P].NEXT;

END;

END;

END;

1 [56] J=-->0 [0]=0

2 [28] 1 [1]=0->[14|]

3 [32] 2 [2]=0->[28|]

4 [14] 3 [3]=0->[32|]

5 [51] 4 [4]=0

5 [5]=0->[51|]-->[56|]-¬

6 [6]=0

7 [7]=0

8 [8]=0

9 [9]=0

NODO

INFO NEXT

[56 | 2 ] 1=1 [14]

[28 | 3 ] 2 [28]

[32 | 4 ] 3 [32]

[14 | 5 ] 4 [51]

[51 | 0 ] 5 [56]

I=1,2,3,4,5

Y=56,28,32,14,51

PRIM=5,2,3,1,5

P=0,4,0,2,0,3,0,0,5,1,0,0,0,0,0

2.2 Ordenamiento

La ordenación o clasificación de datos (sort, en inglés) es una operación consistente

en disponer un conjunto —estructura— de datos en algún determinado orden con

respecto a uno de los campos de elementos del conjunto. Por ejemplo, cada

elemento del conjunto de datos de una guía telefónica tiene un campo nombre, un

campo dirección y un campo número de teléfono; la guía telefónica está dispuesta

en orden alfabético de nombres; los elementos numéricos se pueden ordenar en

orden creciente o decreciente de acuerdo al valor numérico del elemento. En

terminología de ordenación, el elemento por el cual está ordenado un conjunto de

datos (o se está buscando) se denomina clave.

Una colección de datos (estructura) puede ser almacenada en un archivo, un array (vector o tabla), un array de registros, una lista enlazada o un árbol. Cuando los

datos están almacenados en un array, una lista enlazada o un árbol, se denomina

ordenación interna. Si los datos están almacenados en un archivo, el proceso de

ordenación se llama ordenación externa. Una lista se dice que está ordenada por la clave k si la lista está en orden

ascendente o descendente con respecto a esta clave. La lista se dice que está en

orden ascendente si:

i < j implica que k[i] <= k[j]

y se dice que está en orden descendente si:

i > j implica que k[i] <= k[j]

Para todos los elementos de la lista. Por ejemplo, para una guía telefónica, la lista

está clasificada en orden ascendente por el campo clave k, donde k[i] es el nombre

del abonado (apellidos, nombre).

4 5 14 21 32 45 orden ascendente 75 70 35 16 14 12 orden descendente Zacarias Rodriguez Martinez Lopez Garcia orden descendente

Los métodos (algoritmos) de ordenación son numerosos, por ello se debe prestar

especial atención en su elección. ¿Cómo se sabe cuál es el mejor algoritmo? La

eficiencia es el factor que mide la calidad y rendimiento de un algoritmo. En el

caso de la operación de ordenación, dos criterios se suelen seguir a la hora de

decidir qué algoritmo —de entre los que resuelven la ordenación— es el más

eficiente: 1) tiempo menor de ejecución en computadora; 2) menor número de instrucciones.

Sin embargo, no siempre es fácil efectuar estas medidas: puede no disponerse de

instrucciones para medida de tiempo —aunque no sea éste el caso del lenguaje

C—, y las instrucciones pueden variar, dependiendo del lenguaje y del propio estilo

del programador. Por esta razón, el mejor criterio para medir la eficiencia de un

algoritmo es aislar una operación específica clave en la ordenación y contar el

número de veces que se realiza. Así, en el caso de los algoritmos de ordenación,

se utilizará como medida de su eficiencia el número de comparaciones entre

elementos efectuados. El algoritmo de ordenación A será más eficiente que el B,

si requiere menor número de comparaciones.

Así, en el caso de ordenar los elementos de un vector, el número de comparaciones

será función del número de elementos (n) del vector (array). Por consiguiente, se

puede expresar el número de comparaciones en términos de n (por ejemplo, n+4,

o bien n2 en lugar de números enteros (por ejemplo, 325).

En todos los métodos de este capítulo, normalmente —para comodidad del lector—

se utiliza el orden ascendente sobre vectores o listas (arrays unidimensionales). Los métodos de ordenación se suelen dividir en dos grandes grupos:

• Directos burbuja, selección, inserción • Indirectos (avanzados) Shell, ordenación rápida, ordenación por mezcla, Radixsort En el caso de listas pequeñas, los métodos directos se muestran eficientes, sobre

todo porque los algoritmos son sencillos; su uso es muy frecuente. Sin embargo,

en listas grandes estos métodos se muestran ineficaces y es preciso recurrir a los

métodos avanzados.

2.2.1 Optimo teórico para ordenamiento de tablas

INTRODUCCIÓN:

A la hora de tratar datos, muchas veces nos conviene que estén ordenados. Estos

métodos nos pueden resultar eficientes cuando hacemos las búsquedas.

ORDENACIÓN:

Consiste en organizar un conjunto de datos en un orden determinado según un

criterio.

La ordenación puede ser interna o externa:

Interna: La hacemos en memoria con arryas. Es muy rápida.

Externa: La hacemos en dispositivos de almacenamiento externo con

ficheros.

Para determinar lo bueno que es un algoritmo de ordenación hay que ver la

complejidad del algoritmo (cantidad de trabajo de ese algoritmo), se mide en el

número de operaciones básicas que realiza un algoritmo. La operación básica de

un algoritmo es la operación fundamental, que es la comparación.

Existen diferentes algoritmos de ordenación elementales o básicos cuyos detalles

de implementación se pueden encontrar en diferentes libros de algoritmos. La

enciclopedia de referencia es [KNUTH 1973]1 y sobre todo la 2.a edición

publicada en el año 1998 [KNUTH 1998]2. Los algoritmos presentan diferencias

entre ellos que los convierten en más o menos eficientes y prácticos según sea la

rapidez y eficiencia demostrada por cada uno de ellos. Los algoritmos básicos de

ordenación más simples y clásicos son:

• Ordenación por selección.

• Ordenación por inserción.

• Ordenación por burbuja.

Los métodos más recomendados son: selección e inserción, aunque se estudiará el

método de burbuja, por aquello de ser el más sencillo aunque a la par también es

el más ineficiente; por esta causa no recomendamos su uso, pero sí conocer su

técnica.

Los datos se pueden almacenar en memoria central o en archivos de datos

externos guardados en unidades de almacenamiento magnético (discos, cintas,

disquetes, CD-ROM, DVD, discos flash USB, etc.) Cuando los datos se guardan en

listas y en pequeñas cantidades, se suelen almacenar de modo temporal en arrays

y registros; estos datos se almacenan exclusivamente para tratamientos internos

que se utilizan en gestión masiva de datos y se guardan en arrays de una o varias

dimensiones.

Los datos, sin embargo, se almacenan de modo permanente en archivos y bases

de datos que se guardan en discos y cintas magnéticas.

2.2.2 Intercambio simple

El algoritmo de ordenación tal vez más sencillo sea el denominado de intercambio que ordena los elementos de una lista en orden ascendente. Este algoritmo se basa

en la lectura sucesiva de la lista a ordenar, comparando el elemento inferior de la

lista con los restantes y efectuando intercambio de posiciones cuando el orden

resultante de la comparación no sea el correcto.

El algoritmo se ilustra con la lista original 8, 4, 6, 2 que ha de convertirse en la

lista ordenada 2, 4, 6, 8. El algoritmo realiza n − 1 pasadas (3 en el ejemplo),

siendo n el número de elementos, y ejecuta las siguientes operaciones.

El elemento de índice 0 (a[0]) se compara con cada elemento posterior de la lista

de índices 1, 2 y 3. En cada comparación se comprueba si el elemento siguiente

es más pequeño que el elemento de índice 0, en ese caso se intercambian. Después

de terminar todas las comparaciones, el elemento más pequeño se localiza en el

índice 0.

Pasada 1 El elemento más pequeño ya está localizado en el índice 0, y se considera la

sublista restante 8, 6, 4. El algoritmo continúa comparando el elemento de índice

1 con los elementos posteriores de índices 2 y 3. Por cada comparación, si el

elemento mayor está en el índice 1 se intercambian los elementos. Después de

hacer todas las comparaciones, el segundo elemento más pequeño de la lista se

almacena en el índice 1.

Pasada 2 La sublista a considerar ahora es 8, 6 ya que 2, 4 está ordenada. Una comparación

única se produce entre los dos elementos de la sublista

2.2.3 Algoritmo de la burbuja

El método de ordenación por burbuja es el más conocido y popular entre

estudiantes y aprendices de programación, por su facilidad de comprensión y

programación; por el contrario, es el menos eficiente y por ello, normalmente, se

aprende su técnica pero no suele utilizarse.

La técnica utilizada se denomina ordenación por burbuja u ordenación por hundimiento debido a que los valores más pequeños «burbujean» gradualmente

(suben) hacia la cima o parte superior del array de modo similar a como suben las

burbujas en el agua, mientras que los valores mayores se hunden en la parte

inferior del array. La técnica consiste en hacer varias pasadas a través del array.

En cada pasada, se comparan parejas sucesivas de elementos. Si una pareja está

en orden creciente (o los valores son idénticos), se dejan los valores como están.

Si una pareja está en orden decreciente, sus valores se intercambian en el array.

Algoritmo de la burbuja

En el caso de un array (lista) con n elementos, la ordenación por burbuja requiere

hasta n − 1 pasadas.

Por cada pasada se comparan elementos adyacentes y se intercambian sus valores

cuando el primer elemento es mayor que el segundo elemento. Al final de cada

pasada, el elemento mayor ha «burbujeado» hasta la cima de la sublista actual. Por

ejemplo, después que la pasada 0 está completa, la cola de la lista A[n − 1] está

ordenada y el frente de la lista permanece desordenado. Las etapas del algoritmo

son:

• En la pasada 0 se comparan elementos adyacentes:

(A[0],A[1]),(A[1],A[2]),(A[2],A[3]),...(A[n-2],A[n-1])

Se realizan n − 1 comparaciones, por cada pareja (A[i],A[i+1]) se intercambian

los valores si A[i+1] < A[i]. Al final de la pasada, el elemento mayor de la lista

está situado en A[n-1].

• En la pasada 1 se realizan las mismas comparaciones e intercambios, terminando

con el elemento segundo mayor valor en A[n-2].

• El proceso termina con la pasada n − 1, en la que el elemento más pequeño se

almacena enA[0].

El algoritmo tiene una mejora inmediata, el proceso de ordenación puede terminar

en la pasada n − 1, o bien antes, si en una pasada no se produce intercambio

alguno entre elementos del vector es porque ya está ordenado, entonces no es

necesario más pasadas.

El ejemplo siguiente ilustra el funcionamiento del algoritmo de la burbuja con un

array de 5 elementos (A = 50, 20, 40, 80, 30), donde se introduce una variable

interruptor para detectar si se ha producido intercambio en la pasada.

En la pasada 3, se hace una única comparación de 20 y 30, y no se produce

intercambio:

En consecuencia, el algoritmo de ordenación de burbuja mejorado contempla dos

bucles anidados: el bucle externo controla la cantidad de pasadas (al principio de

la primera pasada todavía no se ha producido ningún intercambio, por tanto la

variable interruptor se pone a valor falso (0); el bucle interno controla cada pasada

individualmente y cuando se produce un intercambio, cambia el valor de interruptor

a verdadero (1).

El algoritmo terminará, bien cuando se termine la última pasada (n − 1) o bien

cuando el valor del interruptor sea falso (0), es decir, no se haya hecho ningún

intercambio. La condición para realizar una nueva pasada se define en la expresión

lógica

(pasada < n-1) && interruptor

2.2.4 Shell sort

La ordenación Shell debe el nombre a su inventor, D. L. Shell. Se suele denominar

también ordenación por inserción con incrementos decrecientes. Se considera que

el método Shell es una mejora de los métodos de inserción directa. En el algoritmo de inserción, cada elemento se compara con los elementos

contiguos de su izquierda, uno tras otro. Si el elemento a insertar es el más

pequeño hay que realizar muchas comparaciones antes de colocarlo en su lugar

definitivo.

El algoritmo de Shell modifica los saltos contiguos resultantes de las

comparaciones por saltos de mayor tamaño y con ello se consigue que la

ordenación sea más rápida. Generalmente se toma como salto inicial n/2 (siendo n el número de elementos), luego se reduce el salto a la mitad en cada

Repetición hasta que el salto es de tamaño 1. El Ejemplo 6.1 ordena una lista de

elementos siguiendo paso a paso el método de Shell.

Ejemplo 6.1

Obtener las secuencias parciales del vector al aplicar el método Shell para ordenar

en orden creciente la lista:

6 1 5 2 3 4 0

El número de elementos que tiene la lista es 6, por lo que el salto inicial es 6/2 =

3. La siguiente tabla muestra el número de recorridos realizados en la lista con los

saltos correspondiente.

Algoritmo de ordenación Shell

Los pasos a seguir por el algoritmo para una lista de n elementos son:

1. Dividir la lista original en n/2 grupos de dos, considerando un incremento o salto

entre los elementos de n/2.

2. Clarificar cada grupo por separado, comparando las parejas de elementos, y si

no están ordenados, se intercambian

3. Se divide ahora la lista en la mitad de grupos (n/4), con un incremento o salto

entre loselementos también mitad (n/4), y nuevamente se clasifica cada grupo por

separado.

4. Así sucesivamente, se sigue dividiendo la lista en la mitad de grupos que en el

recorrido anterior con un incremento o salto decreciente en la mitad que el salto

anterior, y luego clasificando cada grupo por separado.

5. El algoritmo termina cuando se consigue que el tamaño del salto es 1. Por

consiguiente, los recorridos por la lista están condicionados por el bucle,

En el código anterior se observa que se comparan pares de elementos indexados

por j y k, (a[j],a[k]), separados por un salto, intervalo. Así, si n = 8 el primer valor

de intervalo = 4, y los índices i =5, j =1, k =6. Los siguientes valores de los índices

son i = 6, j = 2, k = 7, y así hasta recorrer la lista.

Para realizar un nuevo recorrido de la lista con la mitad de grupos, el intervalo se

hace la mitad:

Intervalo v intervalo / 2 así se repiten los recorridos por la lista, mientras intervalo > 0.

2.2.5 Quick sort

El algoritmo conocido como quicksort (ordenación rápida) recibe el nombre de su

autor, Tony Hoare. La idea del algoritmo es simple, se basa en la división en

particiones de la lista a ordenar, por lo que se puede considerar que aplica la

técnica divide y vencerás. El método es, posiblemente, el más pequeño de código,

más rápido, más elegante, más interesante y eficiente de los algoritmos de

ordenación conocidos. El método se basa en dividir los n elementos de la lista a

ordenar en dos partes o particiones separadas por un elemento: una partición izquierda, un elemento central denominado pivote o elemento de partición, y una

partición derecha. La partición o división se hace de tal forma quetodos los

elementos de la primera sublista (partición izquierda) son menores que todos los

elementos de la segunda sublista (partición derecha). Las dos sublistas se ordenan

entonces independientemente.

Para dividir la lista en particiones (sublistas) se elige uno de los elementos de la

lista y seutiliza como pivote o elemento de partición. Si se elige una lista cualquiera

con los elementos en orden aleatorio, se puede seleccionar cualquier elemento de

la lista como pivote, por ejemplo, el primer elemento de la lista. Si la lista tiene

algún orden parcial conocido, se puede tomar otra

decisión para el pivote. Idealmente, el pivote se debe elegir de modo que se divida

la lista exactamente por la mitad, de acuerdo al tamaño relativo de las claves. Por

ejemplo, si se tiene una lista de enteros de 1 a 10, 5 o 6 serían pivotes ideales,

mientras que 1 o 10 serían elecciones «pobres» de pivotes.

Una vez que el pivote ha sido elegido, se utiliza para ordenar el resto de la lista

en dos sublistas: una tiene todas las claves menores que el pivote y la otra, todos

los elementos (claves) mayores que o iguales que el pivote (o al revés). Estas dos

listas parciales se ordenan recursivamente utilizando el mismo algoritmo; es decir,

se llama sucesivamente al propio algoritmo quicksort. La lista final ordenada se

consigue concatenando la primera sublista, el pivote y la segunda lista, en ese

orden, en una única lista. La primera etapa de quicksort es la división o

«particionado» recursivo de la lista

hasta que todas las sublistas constan de sólo un elemento.

2.2.6 Tree sort o Heap sort

El ordenamiento por montículos (heapsort en inglés) es

un algoritmo de ordenamiento no recursivo, no estable, concomplejidad

computacional

Este algoritmo consiste en almacenar todos los elementos del vector a ordenar en

un montículo (heap), y luego extraer el nodo que queda como nodo raíz del

montículo (cima) en sucesivas iteraciones obteniendo el conjunto ordenado. Basa

su funcionamiento en una propiedad de los montículos, por la cual, la cima contiene

siempre el menor elemento (o el mayor, según se haya definido el montículo) de

todos los almacenados en él. El algoritmo, después de cada extracción, recoloca

en el nodo raíz o cima, la última hoja por la derecha del último nivel. Lo cual

destruye la propiedad heap del árbol. Pero, a continuación realiza un proceso de

"descenso" del número insertado de forma que se elige a cada movimiento el mayor

de sus dos hijos, con el que se intercambia. Este intercambio, realizado

sucesivamente "hunde" el nodo en el árbol restaurando la propiedad montículo del

arbol y dejándo paso a la siguiente extracción del nodo raíz.

El algoritmo, en su implementación habitual, tiene dos fases. Primero una fase de

construcción de un montículo a partir del conjunto de elementos de entrada, y

después, una fase de extracción sucesiva de la cima del montículo. La

implementación del almacén de datos en el heap, pese a ser conceptualmente un

árbol, puede realizarse en un vector de forma fácil. Cada nodo tiene dos hijos y

por tanto, un nodo situado en la posición i del vector, tendrá a sus hijos en las

posiciones 2 x i, y 2 x i +1 suponiendo que el primer elemento del vector tiene un

índice = 1. Es decir, la cima ocupa la posición inicial del vector y sus dos hijos la

posición segunda y tercera, y así, sucesivamente. Por tanto, en la fase de

ordenación, el intercambio ocurre entre el primer elemento del vector (la raíz o

cima del árbol, que es el mayor elemento del mismo) y el último elemento del

vector que es la hoja más a la derecha en el último nivel. El árbol pierde una hoja

y por tanto reduce su tamaño en un elemento. El vector definitivo y ordenado,

empieza a construirse por el final y termina por el principio.

Descripción

He aquí una descripción en pseudocódigo del algoritmo. Se pueden encontrar

descripciones de las

operaciones insertar_en_monticulo y extraer_cima_del_monticulo en el artículo

sobre montículos.

2.2.7 Ordenamiento pot intercalation

En este método de ordenamiento existen dos archivos con llaves ordenadas, los

cuales se mezclan para formar un solo archivo.

1.-La longitud de los archivos puede ser diferente.

2.-El proceso consiste en leer un registro de cada archivo y compararlos, el menor

es almacenando en el archivo de resultado y el otro se compara con el siguiente

elemento del archivo si existe. El proceso se repite hasta que alguno de los

archivos quede vacío y los elementos del otro archivo se almacenan directamente

en el archivo resultado.

2.2.8 Ordenamiento por distribución

Un problema que se presenta con frecuencia es el siguiente: "Ordenar un archivo

con N registros cuyas llaves son enteros comprendidos entre 0 y M-1". SiM no es

muy grande, se puede usar el algoritmo de distribución por conteo. La idea básica

es contar el número de veces que se repite cada llave diferente y en una segunda

pasada utilizar el conteo para posicionar los registros en el archivo.

2.3 Ordenamiento externo

Ordenamiento externo es un término genérico para los algoritmos de

ordenamiento que pueden manejar grandes cantidades de información. El

ordenamiento externo se requiere cuando la información que se tiene que ordenar

no cabe en la memoria principal de una computadora (típicamente la RAM) y un

tipo de memoria más lenta (típicamente un disco duro) tiene que utilizarse en el

proceso.

Un ejemplo de ordenamiento externo es el algoritmo de ordenamiento por mezcla.

Supongamos que 900 MB de información deben ser ordenados utilizando

únicamente 100 MB de RAM.

1. Leanse 100MB de información en la memoria principal y ordenense

utilizando un algoritmo tradicional (típicamente quicksort).

2. Escríbase la información ordenada en el disco.

3. Repítanse los pasos 1 y 2 hasta que toda la información esté ordenada en

pedazos de 100 MB. Ahora se deben mezclar todos los pedazos ordenados.

4. Léanse los primeros 10MB de cada pedazo ordenado a la memoria principal

(total de 90 MB) y destínense los 10 MB restantes para el buffer de salida.

5. Ordénense los nueve pedazos mezclándolos y grábese el resultado en el

buffer de salida. Si el buffer de salida está lleno, escríbase al archivo destino

final. Si cualquiera de los 9 buffers leídos queda vacío, se llena con los

siguientes 10 MB de su pedazo original de 100 MB o se marca este como

completado si ya no hay registros remanentes.

Otro ejemplo es el algoritmo de ordenamiento por mezcla equilibrada, que es una

optimización del anterior.

2.3.1 El torneo de tenis para ordenamiento externo

La técnica de dividir para vencer tiene varias aplicaciones. No sólo en el diseño

de algoritmos. Si no también en el diseño de circuitos, construcción de

demostraciones matemáticas y en otros campos del quehacer humano. Se brinda

un ejemplo para ilustrar esto. Considérese el diseño del programa de un torneo de

tenis para n =Zk jugadores. Cada jugador debe enfrentarse a todos los demás. Y

debe tener un encuentro diario durante n - I días, que es el número mínimo de días

necesarios para completar el torneo. El programa del torneo es una tabla de n filas

por n - 1 columnas cuya posición en fila i y columna j es el jugador con quien debe

contender i el j-ksimo día. El enfoque dividir para vencer construye un programa

para la mitad de los jugadores. Que está diseñado por una aplicación recursiva del

algoritmo buscando un programa para una mitad de esos jugadores, y así

sucesivamente. Cuando se llega hasta dos jugadores, se tiene el caso base y

simplemente se emparejan. Supóngase que hay ocho jugadores. El programa para

los jugadores 1 a 4 ocupa la esquina superior izquierda (4 filas por 3 columnas)

del programa que se está consumiendo. La esquina inferior izquierda (4 filas por 3

columnas) debe enfrentar a los jugadores con numeración más alta (5 a 8). Este

subprograma se obtiene agregando 4 a cada entrada de la esquina superior

izquierda. Ahora se ha simplificado el problema, y lo único que falta es enfrentar

a los jugadores de baja numeración con los de alta numeración. Esto es fácil si los

jugad* res 1 a 4 contienden con los 5 a 8, respectivamente, en el día 4, y se

permutan cíclicamente 5 a 8 en los días siguientes. El proceso se ilustra en la

figura 10.4.

2.3.2 Interacción con lotes. Algoritmo balanceado

Los árboles AVL están siempre equilibrados de tal modo que para todos los nodos,

la altura de la rama izquierda no difiere en más de una unidad de la altura de la

rama derecha o viceversa. Gracias a esta forma de equilibrio (o balanceo), la

complejidad de una búsqueda en uno de estos árboles se mantiene siempre en

orden de complejidad O(log n).

2.3.3 El algoritmo poli fase para interacción por lote

La ordenación de datos por intercalación es un proceso muy frecuente en

programación. Esta operación es también un proceso que las personas encuentran

comúnmente en sus rutinas diarias. Por ejemplo, cada elemento de la colección de

datos de una agenda telefónica tiene un campo nombre, dirección y un número de

teléfono. Una colección de datos clasificados se puede almacenar en un archivo,

un vector o tabla, una lista enlazada o un árbol. Cuando los datos están

almacenados en vectores, tablas (arrays), listas enlazadas o árboles, la ordenación

se denomina ordenación interna. Cuando los datos a clasificar se encuentran

almacenados en archivos, en soporte de almacenamiento masivo (cintas o discos)

el proceso de ordenación se denomina ordenación externa.

Es un proceso utilizado en sistema de actualización, y en casos en que es necesario

varias listas ordenadas. También es la única forma que hay para el ordenamiento

de archivos, debido a la imposibilidad de almacenarlos en memoria y a limitaciones

en el tiempo, por la cantidad de elementos a ordenar.

El método de ordenación por intercalación es utilizado por los jugadores de cartas

o naipes para ordenar sus barajas. Consiste en mirar las cartas una a una y cuando

se ve cada nueva carta se inserta en el lugar adecuado. Para desarrollar el

algoritmo imaginemos que las cartas se encuentran situadas en una fila encima del

tapete; a medida que se ve una carta nueva, ésta se compara con la fila y se debe

empujar alguna de ellas a la derecha para dejar espacio e insertar la nueva.

Consideremos un vector de n posiciones. Comencemos con el subíndice i en la

segunda posición incrementando en 1, el elemento del subíndice del vector se

elimina de la secuencia y se reinserta en el vector en la posición adecuada.

2.3.4 El algoritmo de cascada

En numerosos casos en el desarrollo de la solución de problemas, encontramos

que luego de tomar una decisión y marcar el camino correspondiente a seguir, es

necesario tomar otra decisión. Luego de evaluar las condiciones, se señala

nuevamente la rama correspondiente a seguir y nuevamente podemos tener que

tomar otra decisión. El proceso puede repetirse numerosas veces. En el siguiente

ejemplo tenemos una estructura selectiva SI ENTONCES que contiene dentro de

ella otra estructura selectiva SI ENTONCES / SINO.

2.4 Árboles balanceados

2.4.1 Definiciones

Árboles en General

Un árbol se puede definir como una estructura jerárquica aplicada sobre una

colección de elementos u objetos llamados nodos, uno de los cuales es conocido

como raíz. Además se crea una relación o parentesco entre los nodos dando lugar

a términos como padre, hijo, hermano, antecesor, sucesor, ancestro, etc.

Formalmente se define un árbol de tipo T como una estructura homogénea

resultado de la concatenación de un elemento de tipo T con un número finito de

árboles disjuntos, llamados subárbols. Una forma particular de árbol es el árbol

vacío.

Los árboles son estructuras recursivas, ya que cada subárbol es a su vez un árbol.

Los árboles se pueden aplicar para la solución de una gran cantidad de problemas

Por ejemplo, se pueden utilizar para representar fórmulas matemáticas, para

registrar la historia de un campeonato de tenis, para construir un árbol

genealógico, para el análisis de circuitos eléctricos y para enumerar los capítulos

y secciones de un libro.

¿Balance?

Las operaciones de insertar y remover claves modifican la forma del árbol. La

garantía de tiempo de acceso O (log n ) está solamente válida a árboles

balanceados.

Balanceo perfecto

Un árbol está perfectamente balanceado si su estructura es óptima con respeto al

largo del camino de la raíz a cada hoja: Todas las hojas están en el mismo nivel,

es decir, el largo máximo de tal camino es igual al largo mínimo de tal camino

sobre todas las hojas. Esto es solamente posible cuando el número de hojas es 2

k para k ∈ Z +, en que caso el largo de todos los caminos desde la raíz hasta las

hojas es exactamente k.

Rotaciones

Necesitamos operaciones para “recuperar” la forma balanceada después de

inserciones y eliminaciones de elementos, aunque no cada operación causa una

falta de balance en el árbol. Estas operaciones se llaman rotaciones.

Rotaciones básicas

Elección de rotación

La rotación adecuada está elegida según las alturas de los ramos que están fuera

de balance, es decir, tienen diferencia de altura mayor o igual a dos. Si se balancea

después de cada inserción y eliminación siempre y cuando es necesario, la

diferencia será siempre exactamente dos.

¿Por qué dos?

Punto de rotación

Con esas rotaciones, ninguna operación va a aumentar la altura de un ramo, pero

la puede reducir por una unidad. La manera típica de encontrar el punto de rotación

t es regresar hacía la raíz después de haber operado con una hoja para verificar

si todos los vértices en camino todavía cumplan con la condición de balance.

Análisis de las rotaciones

2.4.2 Árboles AVL

La estructura de datos más vieja y mejor conocida para árboles balanceados es el

árbol AVL. Su propiedad es que la altura de los subárboles de cada nodo difiere

en no mas de 1. Para mantenerlo balanceado es necesario saber la altura o la

diferencia en alturas de todos los subárboles y eso provoca que tengamos que

guardar información adicional en cada nodo, un contador de la diferencia entre las

alturas de sus dos subárboles.

Los árboles AVL fueron nombrados por sus desarrolladores Adel'son-Vel'skii y

Landis.

Probablemente la principal característica de los árboles AVL es su excelente

tiempo de ejecución para las diferentes operaciones (búsquedas, altas y bajas).

En las siguientes dos figuras la primera es un árbol AVL y la segunda no lo es ya

que los subárboles del nodo 'L' difieren en altura por más de 1. }

Árbol AVL: El árbol a es un árbol AVL, mientras que el árbol b no lo es

Rotaciones simples de nodos

Los reequilibrados se realizan mediante rotaciones, en el siguiente punto veremos

cada caso.

Rotación simple a la derecha (SD):

Esta rotación se usará cuando el subárbol izquierdo de un nodo sea 2 unidades más

alto que el derecho, es decir, cuando su FE sea de -2. Y además, la raíz del

subárbol izquierdo tenga una FE de -1, es decir, que esté cargado a la izquierda.

Procederemos del siguiente modo:

Llamaremos P al nodo que muestra el desequilibrio, el que tiene una FE de -2. Y

llamaremos Q al nodo raíz del subárbol izquierdo de P. Además, llamaremos A al

subárbol izquierdo de Q, B al subárbol derecho de Q y C al subárbol derecho de P.

En el gráfico que puede observar que tanto B como C tienen la misma altura (n), y

A es una unidad mayor (n+1). Esto hace que el FE de Q sea -1, la altura del

subárbol que tiene Q como raíz es (n+2) y por lo tanto el FE de P es -2.

1. Pasamos el subárbol derecho del nodo Q como subárbol izquierdo de P. Esto

mantiene el árbol como ABB, ya que todos los valores a la derecha de Q siguen

estando a la izquierda de P.

2. El árbol P pasa a ser el subárbol derecho del nodo Q.

3. Ahora, el nodo Q pasa a tomar la posición del nodo P, es decir, hacemos que la

entrada al árbol sea el nodo Q, en lugar del nodo P. Previamente, P puede que

fuese un árbol completo o un subárbol de otro nodo de menor altura.

En el árbol resultante se puede ver que tanto P como Q quedan equilibrados en

cuanto altura. En el caso de P porque sus dos subárboles tienen la misma altura

(n), en el caso de Q, porque su subárbol izquierdo A tiene una altura (n+1) y su

subárbol derecho también, ya que a P se añade la altura de cualquiera de sus

subárboles.

Rotación simple a la izquierda (SI):

Se trata del caso simétrico del anterior. Esta rotación se usará cuando el subárbol

derecho de un nodo sea 2 unidades más alto que el izquierdo, es decir, cuando su

FE sea de 2. Y además, la raíz del subárbol derecho tenga una FE de 1, es decir,

que esté cargado a la derecha.

Procederemos del siguiente modo:

Llamaremos P al nodo que muestra el desequilibrio, el que tiene una FE de 2. Y

llamaremos Q al nodo raíz del subárbol derecho de P. Además, llamaremos A al

subárbol izquierdo de P, B al subárbol izquierdo de Q y C al subárbol derecho de

Q.

En el gráfico que puede observar que tanto A como B tienen la misma altura (n), y

C es una unidad mayor (n+1). Esto hace que el FE de Q sea 1, la altura del subárbol

que tiene Q como raíz es (n+2) y por lo tanto el FE de P es 2.

1. Pasamos el subárbol izquierdo del nodo Q como subárbol derecho de P. Esto

mantiene el árbol como ABB, ya que todos los valores a la izquierda de Q siguen

estando a la derecha de P.

2. El árbol P pasa a ser el subárbol izquierdo del nodo Q.

3. Ahora, el nodo Q pasa a tomar la posición del nodo P, es decir, hacemos que la

entrada al árbol sea el nodo Q, en lugar del nodo P. Previamente, P puede que

fuese un árbol completo o un subárbol de otro nodo de menor altura.

En el árbol resultante se puede ver que tanto P como Q quedan equilibrados en

cuanto altura. En el caso de P porque sus dos subárboles tienen la misma altura

(n), en el caso de Q, porque su subárbol izquierdo A tiene una altura (n+1) y su

subárbol derecho también, ya que a P se añade la altura de cualquiera de sus

subárboles.

2.4.3 Árboles tipo B

Arboles B ´ Los ´arboles B 14 constituyen una categoría muy importante de

estructuras de datos, que permiten una implementación eficiente de conjuntos y

diccionarios, para operaciones de consulta y acceso secuencial. Existe una gran

variedad de ´arboles B: los ´arboles B, B+ y B*; pero todas ellas están basadas en

la misma idea, la utilización de ´árboles de búsqueda no binarios y con condición

de balanceo. En concreto, los ´arboles B+ son ampliamente utilizados en la

representación de ́ índices en bases de datos. De hecho, este tipo de ́ arboles están

diseñados específicamente para aplicaciones de bases de datos, donde la

característica fundamental es la predominancia del tiempo de las operaciones de

entrada/salida de disco en el tiempo de ejecución total. En consecuencia, se busca

minimizar el número de operaciones de lectura o escritura de bloques de datos del

disco duro o soporte físico.

Árboles de búsqueda no binarios

En cierto sentido, los ´arboles B se pueden ver como una generalización de la idea

de árbol binario de búsqueda a árboles de búsqueda no binarios. Consideremos la

representación de árboles de búsqueda binarios y n-arios de la figura 4.23. En un

ABB (figura 4.23a) si un nodo x tiene dos hijos, los nodos del subárbol izquierdo

contienen claves menores que x y los del derecho contienen claves mayores que

x. En un árbol de búsqueda no binario (figura 4.23b), cada nodo interno puede

contener q claves x1, x2, ..., xq, y q+1 punteros a hijos que están “situados” entre

cada par de claves y en los dos extremos. Las claves estarán ordenadas de menor

a mayor: x1 < x2 <...< xq. Además, el hijo más a la izquierda contiene claves

menores que x1; el hijo entre x1 y x2 contiene claves mayores que x1 y menores

que x2; y as´ı sucesivamente hasta el hijo más a la derecha que contiene claves

mayores que xq.

Definición de árbol B.

Un árbol B de orden p es básicamente un árbol de búsqueda n-ario donde los nodos

tienen p hijos como máximo, y en el cual se añade la condición de balanceo de que

todas las hojas estén al mismo nivel. La definición formal de árbol B es la siguiente.

Definición 4.6 Un árbol B de orden p, siendo p un entero mayor que 2, es un árbol

con las siguientes características: 1. Los nodos internos son de la forma (p1, x1,

p2, x2, ..., xq−1, pq), siendo pi punteros a nodos hijos y xi claves, o pares (clave,

valor) en caso de representar diccionarios. 2. Si un nodo tiene q punteros a hijos,

entonces tiene q − 1 claves.

3. Para todo nodo interno, excepto para la raíz, p/2 ≤ q ≤ p. Es decir, un nodo

puede tener como mínimo p/2 hijos y como máximo p. El valor p/2 − 1 indicaría el

mínimo número de claves en un nodo interno y se suele denotar por d.

4. La raíz puede tener 0 hijos (si es el único nodo del ´árbol) o entre 2 y p.

5. Los nodos hoja tienen la misma estructura, pero todos sus punteros son nulos.

6. En todos los nodos se cumple: x1 < x2 <...< xq−1.

7. Para todas las claves k apuntadas por un puntero pi de un nodo se cumple:

8. Todos los nodos hoja están al mismo nivel en el ´árbol. Los ´arboles B+ son una

variante de los ´arboles B, que se utiliza en representación de diccionarios. La

estructura de los nodos hoja es distinta de la de los nodos internos. En esencia, la

modificación consiste en que en los nodos internos solo aparecen claves, mientras

en los nodos hoja aparecen las asociaciones (clave, valor). Por otro lado, tenemos

la variante de los ´arboles B*. Su principal característica es que si en los ´arboles

B –teniendo en cuenta la anterior definición– los nodos deben estar ocupados como

mínimo hasta la mitad, en los B* tienen que estar ocupados más de dos tercios del

máximo. En adelante nos centraremos en el estudio de los ´arboles B. En la figura

4.24 se muestra un ejemplo de árbol B de orden p = 5.

Representación del tipo árbol B

Pasando ahora a la implementación de ´arboles B de cierto orden p, lo normal es

reservar espacio de forma fija para p hijos y p − 1 elementos. La definición,

suponiendo que el tipo almacenado es T, podría ser como la siguiente. Tipo

Inserción en un árbol B

Además de mantener la estructura de árbol de búsqueda, el procedimiento de

inserción en un árbol B debe asegurar la propiedad que impone que todas las hojas

estén al mismo nivel. La nueva entrada debe insertarse siempre en un nodo hoja

15. Si hay sitio en la hoja que le corresponde, el elemento se puede insertar

directamente. En otro caso aplicamos un proceso de partición de nodos, que es

mostrado en la figura 4.25. El proceso consiste en lo siguiente: con las p − 1

entradas de la hoja donde se hace la inserción más la nueva entrada, se crean dos

nuevas hojas con (p − 1)/2 y (p−1)/2 entradas. La entrada m que está en la

mediana aparece como una nueva clave de nivel superior, y tiene como hijas las

dos hojas recién creadas. El proceso se repite recursivamente en el nivel superior,

en el que habrá que insertar m. Si m cabe en el nodo interno correspondiente, se

inserta. En otro caso, se parte el nodo interno y se repite el proceso hacia arriba.

Si se produce la partición a nivel de la raíz entonces tenemos el caso donde la

profundidad del árbol aumenta en uno. En definitiva, el esquema del algoritmo de

inserción de una clave x en un árbol B de orden p seria el siguiente.

1. Buscar el nodo hoja donde se debería colocar x, usando un procedimiento

parecido a la operación Miembro. Si el elemento ya está en el árbol, no se vuelve

a insertar.

2. Si la hoja contiene menos de p − 1 entradas, entonces quedan sitios libres.

Insertar x en esa hoja, en la posición correspondiente.

3. Si no quedan sitios libres, cogemos las p − 1 entradas de la hoja y x. La mediana

m pasa al nodo padre, así como los punteros a sus nuevos hijos: los valores

menores que m forman el nodo hijo de la izquierda y los valores mayores que m

forman el nodo hijo de la derecha.

4. Si el nodo padre está completo, se dividirá a su vez en dos nodos, propagándose

el proceso de partición hasta la raíz.

El algoritmo garantiza las propiedades de árbol B: todas las hojas están al mismo

nivel y los nodos internos (excepto, posiblemente, la raíz) están llenos como

mínimo hasta la mitad. Por otro lado, el tiempo de ejecución depende de la altura

del árbol. Pero, además, el tiempo en cada nivel no es constante; el proceso de

partición tardará un O(p) en el peor caso. No obstante, ya hemos visto que

realmente el factor a considerar es el número de nodos tratados, más que las

operaciones que se realicen dentro de cada nodo.

Eliminación en un árbol B

Igual que la inserción en un árbol B hace uso de la partición de un nodo en dos, la

eliminación se caracteriza por el proceso de unión de dos nodos en uno nuevo, en

caso de que el nodo se vacíe hasta menos de la mitad. No obstante, hay que tener

en cuenta todas las situaciones que pueden ocurrir en la supresión.

Figura 4.25: Inserción de claves en el árbol B de orden p = 5 de la figura 4.24. a)

Inserción sin necesidad de partición. b) La inserción de 21 obliga a partir una hoja.

c) Después de insertar 28, hay que partir la hoja, y después otra vez a nivel

superior.

Análisis de eficiencia de los ´arboles B

En el análisis de eficiencia del árbol B, el recurso crítico es el número de

lecturas/escrituras de bloques del disco duro. Típicamente, las operaciones de

acceso a disco son varios ´ordenes de magnitud más lentas que las que se realizan

en memoria. En las implementaciones reales y eficientes de ´arboles B, se hace

que cada nodo del árbol ocupe exactamente un bloque de disco, lo cual se consigue

ajustando el parámetro p. Por lo tanto, hasta cierto límite, el tiempo de las

instrucciones que se ejecutan dentro de cada nodo es despreciable y el factor

importante es el número de nodos tratados.

Figura 4.26: Eliminación de claves en el árbol B de orden p = 5 de la figura 4.24.

a) Eliminación en un nodo interno. b) La eliminación de 57 requiere un préstamo

del hermano. c) La eliminación de 9 produce una unión de hojas. d) Resultado final.

2.5 Dispersión al azar desmenuzamiento o hassing.

2.5.1 Algoritmos

CONCEPTO DE ALGORITMO:

El algoritmo trata de resolver problemas mediante programas.

Fases:

Análisis preliminar o evaluación del problema: Estudiar el problema en

general y ver que parte nos interesa.

Definición o análisis del problema: Ver que es lo que entra y que es lo que

sale, las posibles condiciones o restricciones, ...

Diseño del algoritmo: Diseñar la solución.

El programa: Codificación del algoritmo en un lenguaje de programación.

Ejecución del programa y las pruebas: Ver si el programa hace lo que

queríamos.

¿Qué es un algoritmo?:

Es una fórmula para resolver un problema. Es un conjunto de acciones o

secuencia de operaciones que ejecutadas en un determinado orden resuelven el

problema. Existen algoritmos, hay que coger el más efectivo.

Características:

Tiene que ser preciso.

Tiene que estar bien definido.

Tiene que ser finito.

La programación es adaptar el algoritmo al ordenador.

El algoritmo es independiente según donde lo implemente.

2.5.2 Funciones de dispersión

Una tabla hash, matriz asociativa, mapa hash, tabla de dispersión o tabla

fragmentada es una estructura de datos que

asocia llaves o claves con valores. La operación principal que soporta de

manera eficiente es la búsqueda: permite el acceso a los elementos

(teléfono y dirección, por ejemplo) almacenados a partir de una clave

generada (usando el nombre o número de cuenta, por ejemplo). Funciona

transformando la clave con una función hash en un hash, un número que

identifica la posición (casilla o cubeta) donde la tabla hash localiza el valor

deseado.

Un ejemplo práctico para ilustrar que es una tabla hash es el siguiente: Se

necesita organizar los periódicos que llegan diariamente de tal forma que

se puedan ubicar de forma rápida, entonces se hace de la siguiente forma

- se hace una gran caja para guardar todos los periódicos (una tabla), y se

divide en 31 contenedores (ahora es una "hash table" o tabla fragmentada),

y la clave para guardar los periódicos es el día de publicación (índice).

Cuando se requiere buscar un periódico se busca por el día que fue

publicado y así se sabe en que zócalo (bucket) está. Varios periódicos

quedarán guardados en el mismo zócalo (es decir colisionan al ser

almacenados), lo que implica buscar en la sub-lista que se guarda en cada

zócalo. De esta forma se reduce el tamaño de las búsquedas de O(n) a, en

el mejor de los casos, O(1) y, en el peor, a O(log(n)).

2.5.3 Manejo de colisiones

En informática, una colisión de hash es una situación que se produce

cuando dos entradas distintas a una función de hash producen la

misma salida.

Es matemáticamente imposible que una función de hash carezca de

colisiones, ya que el número potencial de posibles entradas es mayor que

el número de salidas que puede producir un hash. Sin embargo, las

colisiones se producen más frecuentemente en los malos algoritmos. En

ciertas aplicaciones especializadas con un relativamente pequeño número

de entradas que son conocidas de antemano es posible construir

una función de hash perfecta, que se asegura que todas las entradas

tengan una salida diferente. Pero en una función en la cual se puede

introducir datos de longitud arbitraria y que devuelve un hash de tamaño

fijo (como MD5), siempre habrá colisiones, debido a que un hash dado

puede pertenecer a un infinito número de entradas.

2.5.4 Manejo de sobre flujo

Un diagrama de flujo es una representación esquemática de los distintos

pasos de un programa. Constituyen pues, otra forma de representar

algoritmos distintos al pseudocódigo, pero que nos sirve de forma

complementaria en el proceso de creación de la estructura del programa

antes de ponernos delante del ordenador.

El diagrama de flujo goza de ventajas como el ser altamente intuitivo, fácil de

leer, claro y preciso. Su interés para nosotros, sin desdeñar su utilidad

profesional, radica en su valor didáctico. Lo consideraremos una herramienta

muy potente de cara a comenzar a programar ya que su contenido gráfico lo

hace menos árido que el pseudocódigo.

Las limitaciones principales de los diagramas de flujo derivan precisamente

de su carácter de dibujo. No resultan tan fáciles de crear o de mantener como

el texto del pseudocódigo (que podemos trabajar en un procesador de textos

cualquiera) y pueden requerir utilizar papeles tipo plano (más grande de lo

normal) cuando los programas son de cierta longitud. Gráficamente podemos

verlo de la siguiente manera: si tenemos por ejemplo siete páginas de

pseudocódigo bastará con numerarlas y ponerlas una detrás de otra.

2.5.5 Un corrector de ortografía

Implementación:

Podrías implementar un sencillo corrector ortográfico con un árbol binario de

búsqueda (ABB), aunque si te sientes con energía puedes implementar un árbol

balanceado (AVL). Generalmente en los árboles se suele buscar/insertar a partir

de una clave. Como te interesa buscar el nodo por la palabra no te servira el < >

=, pero puedes aprovechar la caracteristica del strcmp (cadena1, cadena2) que

devuelve <0 si cadena1 es menor que cadena2, >0 si cadena1 es mayor que

cadena2 y 0 si son iguales.

La búsqueda en árboles apenas son 3 líneas (ya q es un procedimiento recursivo)

por lo que no te costará implementarlo.

Idea general:

Podrías comenzar con el árbol vacío y a medida que escribes las palabras, al no

encontrarse, dar la opción de añadirla. Y si está no hace nada.

Otra manera:

Sería implementar un árbol trie o patricia, estos árboles tienen al menos 26

punteros (uno por cada letra del abecedario) como imagino que querrás contemplar

los acentos y la ñ pues más punteros. El orden de complejidad es O(n) tanto en la

inserción como en la busqueda. Los árboles ABB tienen una complejidad Ω(log n)

y Θ(log n) aunque podría tener O(n) (si por ejemplo si todas las claves son mayores

o menores que el nodo anterior, produciéndose una lista enlazada en vez de un

árbol) Los AVL son de O(log n) el inconveniente es que hay q usar un código más

elaborado y corregir los desbalanceo.

3. Programación de aplicaciones

3.1 Descripción del lenguaje a utilizar

La interfaz de programación de aplicaciones, abreviada como API (del inglés:

Aplication Programming interface). Es el conjunto de subrutinas, funciones y

procedimientos (o métodos, en la programación orientada a objetos) que ofrece

cierta biblioteca para ser utilizado por otro software como una capa de abstracción.

3.1.1 Estructura de un programa y reglas sintácticas

CONCEPTO DE PROGRAMA:

Un programa es un conjunto de instrucciones que al ser ejecutadas resuelven un

problema.

Un programa tiene 3 partes:

Entrada de datos: Normalmente se va a ejecutar a través de instrucciones de

lectura, y en lo que se le pide al usuario la información que el programa va a

necesitar para ejecutarse y se hace a través de lecturas.

Acciones de un algoritmo: Parte en la que se resuelve el problema usando los

datos de entrada.

Salida: Mostrar en un dispositivo de salida los resultados de las acciones

anteriormente realizadas. Son acciones de escritura.

En la parte de las acciones a ejecutar se distinguirán dos partes:

Declaración de variables.

Instrucciones del programa.

INSTRUCCIONES Y TIPOS:

Para que una instrucción se ejecute tiene que ser llevada a memoria. En cuanto al

orden de ejecución de las instrucciones, el programa puede ser de dos tipos:

Programas lineales: Se va ejecutando una instrucción más otra y el orden de

ejecución es igual al orden de escritura.

Programas no lineales: Las instrucciones no se ejecutan en el mismo orden

en el que aparecen escritas, sino que se realizan saltos que nos mandan de

unas instrucciones a otras.

Nunca se deben hacer saltos no lineales.

Tipos de instrucciones:

Inicio y fin.

es de bifurcación: Alternan el orden de ejecución del programa. Salto

a otra instrucción que no es la siguiente.

esa instrucción: Goto Ir a.

cutan un conjunto de instrucciones u otras

dependiendo del valor devuelto al evaluar una condición.

Es la que vamos a usar.

ELEMENTOS BÁSICOS DE UN PROGRAMA:

¿Qué es la sintaxis de un lenguaje?:

Conjunto de reglas que tenemos que seguir a la hora de escribir un programa en

ese lenguaje tal que si no seguimos esas reglas de sintaxis el compilador da

errores.

Elementos del lenguaje de programación:

Palabras reservadas: Son un conjunto de palabras especiales que nos sirven

para definir la estructura del programa, y solo se pueden usar para el fin para el

que están reservadas.

Identificadores: Son los nombres que aparecen en el programa dados por el

usuario. Son por tanto los nombres de variables, de constantes, de subprogramas

y nombres de tipos creados por el usuario.

Caracteres especiales: Sirven como separadores entre sentencias, por ejemplo

el ;.

Instrucciones: De 3 tipos, secuenciales, repetitivas y selectivas, y pueden

aparecer elementos especiales (bucles, contadores, interruptores y

acumuladores).

Bucle: Un conjunto de instrucciones que se repiten un número finito de

veces. Lleva asociado aparte de las instrucciones una condición que es la

que determina cuando se termina un bucle. Ejecución de un bucle

(iteración). Los bucles se pueden anidar unos dentro de otros, y puede

haber varios bucles al mismo nivel, pero nunca se entrelazan.

Contador: Un elemento cuyo valor se incrementa o decrementa en un valor

constante en cada iteración de un bucle, y se utiliza para controlar la

condición del bucle.

Acumulador: Es una variable que también se suele usar en los bucles y que

se incrementa o decrementa en cada iteración del bucle, pero no en una

cantidad constante.

Algoritmo ejemplo

Var cont, num, sum: entero

Inicio

Cont 0

Sum 0

Mientras cont <> 3

Leer num

Sum sum + num

Cont cont +1

Fin mientras

Escribir suma

End

Interruptor (marca, bandera o flag): Es una variable que sirve como

indicador de una determinada información y que solo puede tomar uno de

dos valores. El valor de la variable tiene asociado un signo y puede variar

a lo largo de la ejecución.

Algoritmo ejemplo:

Var cont, num, suma: entero

Neg: boolean

Inicio

Cont 0

Sum 0

Neg falso

Mientras cont <>3

Leer num

Si num < 0

Entonces neg verdadero

Fin si

Sum sum + num

Cont cont + 1

Fin mientras

Si neg=verdadero

Entonces escribir (“Se ha leído negativos”)

Sino escribir (“No negativos”)

Fin si

Fin

Si es leer un número negativo o hasta 3 números:

Mientras (cont <> 3) y (neg = verdadero)

3.1.2 Palabras reservadas

Las Palabras clave son palabras “reservadas” para utilizar dentro del

lenguaje que tienen un significado especial y no pueden ser utilizadas como

nombres de variables o identificadores (salvo que se fuerce mediante la

utilización de corchetes “[ ] “).

Rem: Nos permite incluir comentarios sobre el programa en medio del

código, la sintaxis es:

Rem Comentario

Además, se puede conseguir lo mismo sin necesidad de escribir Rem,

utilizando la comilla simple, es decir, la anterior orden es equivalente a:

'Comentario

Observaremos como el editor de código reconoce los comentarios ya que

les aplica como color del texto el verde.

Exit Sub: Nos permite acabar la ejecución del procedimiento en el que lo

pongamos, y en punto del mismo donde se halle situado.

End: Nos permite acabar la ejecución del programa en el punto del mismo

donde se halle situado.

3.1.3 Tipos de datos y variables

- Dato: Es un objeto o elemento que tratamos a lo largo de diversas

operaciones.

Tienen 3 características:

Un nombre que los diferencia del resto.

Un tipo que nos determina las operaciones que podemos hacer con ese dato.

Un valor que puede variar o no a lo largo de la operación.

Existen diferentes tipos de datos.

- Características de los tipos:

Cada tipo se representa o almacena de forma diferente en la computadora.

Bit:1/0; Byte=8 bits.

Un tipo agrupa a los valores que hacen las mismas operaciones.

Si tiene definida una relación de orden es un tipo escalar.

Cardinalidad de un tipo: Número de valores distintos que puede tomar un

tipo.

Pueden ser finitos (caracteres), y si son infinitos el ordenador los toma como

finitos porque está limitado por el tamaño de los bytes en el que la cifra es

almacenada.

- Los datos pueden ser:

Simples: Un elemento.

Compuestos: Varios elementos.

- Los tipos pueden ser:

Estándar: Que vienen en el sistema por defecto.

No estándar: Son los que crea el usuario.

- Los tipos simples más importantes son:

Numéricos.

Lógicos.

Caracteres.

Numéricos:

Entero: Subconjunto finito del conjunto matemático de los números enteros.

No tiene parte decimal. El rango de los valores depende del tamaño que se

les da en memoria.

Real: Subconjunto finito del conjunto matemático de los números reales.

Llevan signo y parte decimal. Se almacenan en 4 Bytes (dependiendo de los

modificadores). Si se utilizan números reales muy grandes, se puede usar

notación científica que se divide en mantisa, base y exponente; tal que el

valor se obtiene multiplicando la mantisa por la base elevada al exponente.

Lógicos o booleanos:

Aquel que sólo puede tomar uno de los dos valores, verdadero o falso (1/0).

Carácter:

Abarca al conjunto finito y ordenado de caracteres que reconoce la

computadora (letras, dígitos, caracteres especiales, ASCII).

Tipo de cadena o String: Conjunto de caracteres, que van a estar entre “”.

El propio lenguaje puede añadir más tipos, o se pueden añadir modificadores.

Entero : Int Long int

En algunos lenguajes se definen tipos especiales de fecha y hora, sobre todo

en los más modernos.

CONSTANTES Y VARIABLES:

Constantes: Tienen un valor fijo que se le da cuando se define la constante

y que ya no puede ser modificado durante la ejecución.

Variables: El valor puede cambiar durante la ejecución del algoritmo, pero

nunca varía su nombre y su tipo.

Antes de usar una variable hay que definirla o declararla, al hacerlo hay que

dar su nombre y su tipo. El nombre que le damos tiene que ser un nombre

significativo, va a ser un conjunto de caracteres que dependiendo del

lenguaje hay restricciones. Tiene que empezar por una letra, y el tamaño

depende del lenguaje.

Identificador: Palabra que no es propia del lenguaje.

El valor de la variable si al declararla no se la inicializa, en algunos lenguajes

toma una por defecto. En cualquier caso el valor de la variable podemos

darle uno inicial o podemos ir variándolo a lo largo de la ejecución.

Las constantes pueden llevar asociados un nombre o no, si no lo llevan, se

llaman literales. Su valor hay que darlo al definir la constante y ya no puede

cambiar a lo largo de la ejecución, y en cuanto al tipo, dependiendo de los

lenguajes en algunos hay que ponerlo, y en otros no hace falta ponerlo

porque toma el tipo del dato que se le asigna. Const PI=3,1416.

Hay que inicializar todas las variables.

< > Hay que poner algo obligatoriamente.

[ ] Puede llevar algo o no llevarlo.

La ventaja de usar constantes con nombre es que en cualquier lugar donde

quiera que vaya la constante, basta con poner su nombre y luego el

compilador lo sustituirá por su valor.

Las constantes sin nombres son de valor constante: 5, 6, `a', “hola”.

Cuando una cadena es de tipo carácter, se encierra entre `' `a'.

Relación entre variables y constantes en memoria:

Al detectar una variable o una constante con nombre, automáticamente se

reserva en memoria espacio para guardar esa variable o constante. El

espacio reservado depende del tipo de la variable.

En esa zona de memoria es en la que se guarda el valor asociado a la variable

o constante y cuando el programa use esa variable, ira a esa zona de

memoria a buscar su valor.

3.1.4 Instrucciones asociadas a:

3.1.4.1 Operaciones primitivas

Operaciones primitivas elementales. Son las acciones básicas que la

computadora “sabe hacer”, y que se ejecutan sobre los datos para darles

entrada, transformarlos y darles salida convertidos en información.

3.1.4.2 Estructuras de control

Estructuras de control. Son las formas lógicas de funcionamiento de la

computadora mediante las que se dirige el orden en que deben ejecutarse las

instrucciones del programa. Las estructuras de control son: La secuenciación,

que es la capacidad de ejecutar instrucciones secuenciales una tras otra. La

selección es la capacidad de escoger o seleccionar si algo se ejecuta o no, optar

por una de dos o más alternativas, y la repetición, que es la capacidad de realizar

en más de una ocasión (es decir, varias veces) una acción o conjunto de

acciones.

3.1.4.3 Operaciones aritméticas

Una expresión es una combinación de constantes, variables, signos de

operación, paréntesis y nombres especiales (nombres de funciones

estándar), con un sentido unívoco y definido y de cuya evaluación resulta un

único valor.

Toda expresión tiene asociada un tipo que se corresponde con el tipo del

valor que devuelve la expresión cuando se evalúa, por lo que habrá tantos

tipos de expresiones como tipos de datos. Habrá expresiones numéricas y

lógicas.

Numéricas: Operadores aritméticos.

Son los que se utilizan en las expresiones numéricas (una combinación de

variables y/o constantes numéricas con operadores aritméticos y que al

evaluarla devuelve un valor numérico.

+, -, *, /.

Operación resto: Lo que devuelve es el resto de una división entera.

Mod: Pascal. 5 mod 3 = 2

%: C.

División entera: Nos devuelve el cociente de una división entera (en la que

no se sacan decimales).

Div: Pascal. 5 div 3 = 1

\: C.

Potencia: ^ 5^2.

Todos estos operadores son binarios (el operador se sitúa en medio), el

menos también puede ser unario (lleva un único operando) y significa signo

negativo.

Reglas de precedencia:

El problema es cuando una expresión entera según como la evalué pueda

dar diferentes valores.

7*3+4 25

49

La solución es aplicar prioridad entre los operadores, de modo que ante la

posibilidad de usar varios siempre aplicaremos primero el de mayor

prioridad.

Cada lenguaje puede establecer sus propias reglas de prioridad o

precedencia de operadores. Si no nos acordamos, siempre podemos poner (

).

1ª) ^

2ª) * / div mod

3ª) + -

Entre dos operaciones que tienen la misma precedencia para resolver la

ambigüedad, hay que usar la regla de la asociatividad. La más normal es la

de la asociatividad a izquierdas (primero lo de la izquierda).

3.1.4.4 Funciones matemáticas

FUNCIONES INTERNAS:

Son funciones matemáticas diferentes de las operaciones básicas pero que

se incorporan al lenguaje y que se consideran estándar. Dependen del

lenguaje. Normalmente se encuentran en la librería de matemáticas del

lenguaje de programación.

Fórmulas:

Abs (x)

Arctan (x)

Cos (x)

Sen (x)

Exp (x)

Ln (x)

Log 10 (x)

Redondeo (x)

Trunc (x)

Cuadrado (x)

Raíz (x)

3.1.4.5 Manejo de caracteres

JUEGO DE CARACTERES:

En principio se programaba todo con 0 y 1, pero como esto costaba mucho,

apareció la necesidad de crear un lenguaje semejante al humano para

entendernos más fácilmente con la computadora, y para ello aparecen los

juegos de caracteres.

El juego de caracteres es una especie de alfabeto que usa la máquina.

Hay 2 juegos de caracteres principales:

ASCII: El que más se usa.

EBCDIC: Creado por IBM.

Hay 2 tipos de ASCII, el básico y el extendido.

En el ASCII básico, cada carácter se codifica con 7 bits, por lo que existen

2^7=128 caracteres.

En el ASCII extendido, cada carácter ocupa 8 bits (1 byte) por lo que

existirán 2^8= 256 caracteres, numerados del 0 al 255.

En el EBCDIC, cada carácter ocupa también 8 bits.

En cualquiera de los 2 juegos, existen 4 tipos de caracteres:

Alfabéticos: Letras mayúsculas y minúsculas.

Numéricos: Números.

Especiales: Todos los que no son letras y números, que vienen en el teclado.

Control: No son imprimibles y tienen asignados caracteres especiales.

Sirven para determinar el fin de línea, fin de texto. Van del 128 al 255.

Un juego de caracteres es una tabla que a cada número tiene asociado un

número.

CADENA DE CARACTERES:

Es un conjunto de 0 ó más caracteres. Entre estos caracteres puede estar

incluido el blanco.

En pseudocódigo, el blanco es el b. Las cadenas de caracteres se delimitan

con dobles comillas “ “, pero en algunos lenguajes se delimitan con ` `.

Las cadenas de caracteres se almacenan en posiciones contiguas de

memoria.

La longitud de una cadena es el número de caracteres de la misma. Si

hubiese algún carácter que se utilizara como especial para señalar el fin de

cadena, no se consideraría en la longitud.

Si una cadena tiene longitud 0, la llamamos cadena nula por lo que no tiene

ningún carácter, pero esto no quiere decir que no tenga ningún carácter

válido, por que puede haber algún carácter especial no imprimible que forme

parte de la cadena.

Una subcadena es una cadena extraída de otra.

DATOS DE TIPO CARÁCTER:

Constantes: Una constante de tipo cadena es un conjunto de 0 o más

caracteres encerrados entre “ “.

Si dentro de la cadena quiero poner como parte de la cadena las “, las pongo

2 veces. Esto depende del lenguaje.

“Hola””Adios” Hola”Adios

En algunos lenguajes hay un carácter de escape. En C, el carácter de escape

es la \.

Una constante de tipo carácter es un solo carácter encerrado entre comillas

simples.

variable de tipo cadena, el contenido de una variable de tipo cadena es un

conjunto de 0 ó más caracteres encerrados entre “ “, mientras que una

variable de tipo carácter es un solo carácter encerrado entre ` `.

3.1.4.7 Estructura de datos

Estructuras de datos. Son las formas de representación interna de la

computadora. Los hechos reales, representados en forma de datos, pueden

estar organizados de diferentes maneras llamadas estructuras de datos.

3.1.4.7 Operaciones especiales

Cadenas de caracteres, Operaciones muy especiales

Las cadenas de caracteres como ya mencionamos, son tipos de datos muy

especiales, ya que se trata de caracteres arreglados con un orden específico

para formar las palabras. Por este motivo es que muchos lenguajes de

programación dedican una serie de operaciones muy especiales para

manejar estas cadenas de caracteres, en los manuales de usuario de cada

lenguaje explican si disponen de funciones especiales para el manejo de este

tipo de variables.

Carátula del Programa, Formatos de Entrada y Salida

Al estructurar un programa hay un momento en el que es necesario mostrar

o pedir información al usuario, es necesario definir dos situaciones:

La computadora espera datos por parte del usuario, se dice que la

computadora espera leer datos del usuario

La computadora muestra datos al usuario, se dice que la

computadora escribe datos al usuario.

Estas dos situaciones tienden a confundir a los programadores novatos, un

ejemplo de esta confusión es cuando se requiere que la computadora lea

datos por parte del usuario colocan escribir datos, es cierto que el usuario

tiene que escribir datos, pero la computadora debe leer los datos que le

suministra usuario. El programa de aplicación es un conjunto de

instrucciones para la computadora, no para el usuario. Es buena costumbre

que en el momento de solicitar datos al usuario se le muestre un mensaje

de que es lo que debe introducir, esto hace que nuestro programa tenga una

carátula amena al usuario y despierte interés en continuar el uso de nuestro

programa.

3.1.5 Subrutinas / procedimientos

INTRODUCCIÓN A LOS SUBPROGRAMAS O SUBALGORITMOS:

La programación modular es una de las técnicas fundamentales de la programación.

Se apoya en el diseño descendente y en la filosofía de “divide y vencerás”, es

decir se trata de dividir el problema dado, en problemas más simples en que cada

uno de los cuales lo implementaremos en un módulo independiente. A cada uno de

estos módulos es a lo que llamamos subalgoritmos o subprogramas.

Siempre existirá un módulo o programa principal que es con el que comienza la

ejecución de todo el programa, y a partir de él iremos llamando al resto.

Cada vez que se llama a un subprograma se le pasa la información que necesita en

la llamada, a continuación comienza a ejecutarse el subprograma llamado, y cuando

termine su ejecución, devuelve el control a la siguiente instrucción a la de llamada

en el programa que lo llamó.

En cuanto a la estructura de un subprograma es igual a la estructura de un

programa, va a tener una información de entrada que es la que le pasamos al hacer

la llamada y que se coloca junto al nombre del subprograma. Después va a tener

un conjunto de acciones, declarar otras variables propias del subprograma, y al

terminar la ejecución puede que devuelva o no resultados al programa que lo llamó.

Hay dos tipos fundamentales de subprogramas: Funciones y procedimientos.

3.2.1 Funciones

Desde el punto de vista matemático, una función es una operación que toma uno o

varios operando, y devuelve un resultado. Y desde el punto de vista algorítmico,

es un subprograma que toma uno o varios parámetros como entrada y devuelve a

la salida un único resultado.

Pascal: En las funciones se puede devolver más de un único resultado mediante

parámetros.

C: Se devuelve todo por parámetros.

Este único resultado irá asociado al nombre de la función. Hay dos tipos de

funciones:

Internas: Son las que vienen definidas por defecto en el lenguaje.

Externas: Las define el usuario y les da un nombre o identificador.

Para llamar a una función se da su nombre, y entre paréntesis van los argumentos

o parámetros que se quieren pasar.

Declaración de una función:

La estructura de una función es semejante a la de cualquier subprograma. Tendrá

una cabecera (con el nombre y los parámetros) y un cuerpo (con la declaración de

los parámetros de la función y las instrucciones).

Sintaxis:

Función <nombre_funcion> (n_parametro: tipo, n_parametro: tipo): tipo función

Var <variables locales función>

Inicio

<acciones>

retorno <valor>

fin <nombre_funcion>

La lista de parámetros es la información que se le tiene que pasar a la función. Los

parámetros luego dentro de la función los podemos utilizar igual que si fueran

variables locales definidas en la función y para cada parámetro hay que poner su

nombre y tipo.

El nombre de la función lo da al usuario y tiene que ser significativo.

En las variables locales se declaran las variables que se pueden usar dentro de la

función.

Entre las acciones tendrá que existir entre ellas una del tipo retorno <valor>. Esta

sentencia pondrá fin a la ejecución de la función y devolverá el valor de la función,

es decir, como valor asociado al nombre de mismo tipo que el tipo de datos que

devuelve a la función, este valor por tanto tiene que ser del mismo tipo que el tipo

de datos que devuelve la función, que es el que habremos indicado al declarar la

función en la parte final de la cabecera.

No se permiten funciones que no devuelvan nada.

Los parámetros que aparecen en la declaración de la función se denominan

parámetros formales, y los parámetros que yo utilizo cuando llamo a la función se

denominan parámetros actuales o reales.

Invocación de una función:

Para llamar a una función se pone el nombre de la función, y entre paréntesis los

parámetros reales, que podrán ser variables, expresiones, constantes,... pero

siempre del mismo tipo que los parámetros normales asociados

<nombre_funcion> (parámetros reales)

La función puede ser llamada desde el programa principal o desde cualquier otro

subprograma.

Para llamar a la función desde cualquier parte, implica el conocimiento previo de

que ésta función existe.

A través de los parámetros reales de la llamada se proporciona a la función la

información que necesita, para ello, al hacer la llamada lo que se produce es una

asociación automática entre parámetros reales y parámetros formales. Esta

asociación se realiza según el orden de la aparición y de izquierda y derecha.

Si el parámetro formal y real no es del mismo tipo, en Pascal se produce un error,

y en C se transforman los tipos si es posible.

La llamada a una función, siempre va a formar parte de una expresión, de cualquier

expresión en la que en el punto en la que se llama a la función, pudiera ir colocado

cualquier valor del tipo de datos que devuelve la función, esto se debe a que el

valor que devuelve una función está asociado a su nombre.

Pasos para hacer la llamada a una función:

cada parámetro real a cada parámetro formal asociado, siempre por orden de

aparición y de izquierda a derecha, por lo que siempre que no coincidan los tipos

y el número de parámetros formales y reales, se produce un error.

a una de tipo retorno <valor> que pondrá fin a la ejecución. Pueden existir varias

sentencias de retorno en la misma función, pero en cada llamada solo se podrá

ejecutar uno.

al subprograma que hizo la llamada pero sustituyendo el nombre de la función por

el valor devuelto.

Otra forma de especificar el retorno de una función:

Se le asigna el valor devuelto al nombre de la función.

Función valor

3.2 Estructura de los datos internos

Operaciones Con Arreglos

Las operaciones en arreglos pueden clasificarse de la siguiente forma: • Lectura •

Escritura • Asignación • Actualización • Ordenación • Búsqueda

a) LECTURA Este proceso consiste en leer un dato de un arreglo y asignar un

valor a cada uno de sus componentes. La lectura se realiza de la siguiente manera:

para i desde 1 hasta N haz x<--arreglo[i]

b) ESCRITURA Consiste en asignarle un valor a cada elemento del arreglo. La

escritura se realiza de la siguiente manera: para i desde 1 hasta N haz arreglo[i]<-

-x

c) ASIGNACIÓN No es posible asignar directamente un valor a todo el arreglo, por

lo que se realiza de la manera siguiente: para i desde 1 hasta N haz arreglo[i]<--

algún_valor

d) ACTUALIZACIÓN Dentro de esta operación se encuentran las operaciones de

eliminar, insertar y modificar datos. Para realizar este tipo de operaciones se debe

tomar en cuenta si el arreglo está o no ordenado.

3.2.1 Vectores

3.2.2 Matrices

3.2.3 Poliedros