You are on page 1of 78

MIGUEL .

TOLEDO MARTNEZ

CONTENIDO DE LA LECCIN 18
ALMACENAMIENTO DE DATOS EN ARREGLOS
1. Introduccin 2. Estructura de un arreglo
2.1. Elementos del arreglo 2.2. ndice del arreglo

3 3
5 5

3. Examen breve 34 4. Definicin de arreglos unidimensionales en C++


4.1. Formato para un arreglo unidimensional 4.2. Ejemplo 18.1

76 5
5 6

5. Examen breve 35 6. El acceso a los arreglos


6.1. Insercin de elementos en los arreglos unidimensionales
6.1.1. Asignacin directa 6.1.1.1. Formato de asignacin directa (insercin de elementos en un arreglo) 6.1.2. Sugerencia de depuracin 6.1.3. Lectura de los elementos del arreglo 6.1.4. Insercin de elementos del arreglo con el uso de ciclos 6.1.4.1. Insercin dentro de un arreglo unidimensional con el uso de un ciclo for

76 6
6
6 6 7 7 8 8

7. Extraccin de elementos de los arreglos unidimensionales


7.1. Asignacin directa
7.1.1. 7.1.2. 7.1.3. 7.1.4. Formato de asignacin directa (extraccin de elementos del arreglo) Escritura de elementos del arreglo Extraccin de elementos del arreglo con el uso de ciclos Sugerencia de depuracin

9
9
9 10 10 11

8. Examen breve 36 9. Ejemplos 18.2, 18.3, 18.4, 18.5, 18.6, 18.7, 18.8, 18.9, 18.10, 18.11, 18.12, 18.13, 18.14,
18.15, 18.16, 18.17.

76 12 21
21

10. Paso de arreglos y elementos de arreglos a las funciones


10.1. Ejemplos 18.18, 18.19, 18.20, 18.21, 18.22, 18.23, 18.24, 18.25

11. Examen breve 37 12. Ordenamiento de arreglos


12.1. Ejemplos 18.26, 18.27, 18.28, 18.29, 18.30, 18.31, 18.32

76 31
32

13. Bsqueda en arreglos: Bsqueda lineal y bsqueda binaria


13.1. Ejemplos 18.33, 18.34, 18.35

40
40

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-1

MIGUEL . TOLEDO MARTNEZ

14.

Solucin de problemas en accin: Bsqueda en un arreglo con iteracin


(bsqueda secuencial) 14.1. Problema 14.2. Definicin del problema 14.3. Planeacin de la solucin 14.4. Codificacin del programa

45
45 45 46 46

15. Solucin de problemas en accin: Como ordenar un arreglo con iteracin (ordenacin por insercin) 15.1. Problema 15.2. Definicin del problema 15.3. Planeacin de la solucin 15.4. Codificacin del problema

47
47 47 48 50

16. Solucin de problemas en accin: Bsqueda en un arreglo con recursin


(bsqueda binaria) 16.1. Problema 16.2. Definicin del problema 16.3. Planeacin de la solucin 16.4. Codificacin del problema

51
51 51 52 55

17. Ejemplos 18.36, 18.37 18. Iniciacin de arreglos


18.1. Iniciacin predeterminada de arreglos globales y estticos
19. Examen breve 38 20. Arreglos que rebasan los 64 kbytes de memoria

56 61
63

77 65
65

20.1. Ejemplos 18.38 y 18.39

21. Lo que necesita saber 22. Preguntas y problemas


22.1. Preguntas 22.2. Problemas 22.3. Problemas de recursividad

66 68
68 70 75

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-2

MIGUEL . TOLEDO MARTNEZ

LECCIN 18
ALMACENAMIENTO DE DATOS EN ARREGLOS
INTRODUCCIN Esta leccin tratar un tema muy importante en cualquier lenguaje de programacin: los arreglos. No es posible enfatizar sobremanera la importancia de los arreglos, pues ellos mismos dan origen a muchas aplicaciones. En muchas ocasiones, sus programas requerirn almacenar varios valores, tales como 50 calificaciones, 10 ttulos de libros, 1000 nombres de archivos, etc. Cuando sus programas necesitan almacenar varios valores, entonces define un arreglo, especificando su clase de datos, nombre y nmero de elementos que el arreglo almacenar.
Un arreglo es una estructura de datos indexados que se utiliza para almacenar elementos de datos de la misma clase.

Los arreglos simplemente proporcionan un medio organizado para localizar y almacenar datos, as como el apartado postal en el correo de su oficina postal local proporciona un medio organizado de localizar y clasificar el correo. Por esto a un arreglo se le conoce como una estructura de datos que se usa para almacenar cualquier clase de datos, incluyendo enteros, flotantes, caracteres, arreglos, apuntadores, y registros (structs) Adems, los arreglos son tan verstiles que se pueden usar para implementar otras estructuras de datos, como pilas, colas, listas ligadas y rboles binarios, de hecho en algunos lenguajes corno FORTRAN, el arreglo es la nica estructura de datos disponible para el programador, porque, por medio del uso de arreglos es posible implementar la mayor parte de otras estructuras.
Los objetivos de esta leccin son: Presentar la estructura de datos de arreglo. Declarar un arreglo dentro de su programa. Comprender cmo se declaran e inicializan los arreglos y de qu manera se hace referencia a los elementos de un arreglo. Aprender a pasar los arreglos a las funciones Aprender a utilizar los arreglos para almacenar, ordenar y hacer bsquedas en listas y tablas de valores. Discernir las tcnicas bsicas para el ordenamiento.

ESTRUCTURA DE UN ARREGLO Un arreglo es una estructura de datos. En otras palabras, un arreglo consta de elementos de datos organizados o estructurados en una forma particular. Esta estructura de datos proporciona un medio conveniente para almacenar grandes cantidades de datos en la memoria primaria o del usuario. Existen arreglos unidimensionales o listas y multidimensionales. En esta leccin revisaremos los arreglos unidimensionales; en la leccin 19 estudiaremos los arreglos multidimensionales.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-3

MIGUEL . TOLEDO MARTNEZ

Para obtener la idea de un arreglo, observe la ilustracin de la figura 18.1. En esta figura se puede ver una sola lnea de cajas de apartados postales como se encuentran en cualquier oficina de correos. Como se sabe, cada caja tiene un nmero de apartado postal (A. P.) En la figura 18.1, los nmeros del A. P. empiezan con cero y van hasta un nmero finito n. Cmo se localiza una determinada caja? Por medio del nmero de apartado postal, correcto? Sin embargo, el nmero del A. P. no tiene nada que ver con lo que contiene la caja. Simplemente se usa para localizar una caja determinada. Desde luego, el contenido es la correspondencia enviada a esta caja. La razn por la que el servicio postal usa el mtodo de apartado postal es que proporciona un mtodo conveniente y bien organizado para almacenar y tener acceso a la correspondencia de sus clientes. Un arreglo hace lo mismo en un programa de computadora; proporciona un mtodo conveniente y bien organizado para almacenar y tener acceso a los datos para usted, el programador. De modo que, cuntos apartados postales hay en la figura 18.1? Debido a que el primer nmero del apartado es 0 y el ltimo es n, habr n + 1 apartados. ...

...
APARTADO POSTAL 0 APARTADO POSTAL 1 APARTADO POSTAL 2 APARTADO POSTAL 3 APARTADO POSTAL n

Figura 18.1.Un arreglo unidimensional o lista es como una fila de buzones de apartados en la oficina de correos.

Imagine que un arreglo unidimensional, como el que se muestra en la figura 18.2, es similar a una lnea de cajas de apartados postales. El arreglo unidimensional consiste en una sola fila de lugares de almacenamiento, cada una etiquetada con un nmero que se conoce con el nombre de ndice. Cada localizacin del ndice se utiliza para almacenar una clase de datos determinada. Los datos almacenados en una localizacin de ndice determinada se conoce como elemento del arreglo. De esta manera, un arreglo unidimensional es una lista secuencial de lugares de almacenamiento que contiene elementos de datos individuales que se localizan o accedan por medio de ndices.

Elemento 0 [0]

Elemento 1 [1]

Elemento 2 [2]

Elemento 3 [3]

Elemento n [n]

NDICES Figura 18.2 Un arreglo unidimensional, tambin llamado lista, es una lista secuencial de localizaciones de almacenamiento que contiene los elementos de datos que se localizan por medio de los ndices.

Los dos componentes principales de un arreglo son los elementos almacenados en el arreglo y los ndices que localizan los elementos almacenados. No se confunda con estos dos componentes del arreglo! Aunque los elementos del arreglo y los ndices se relacionan, son cantidades completamente separadas, al igual que el contenido de una caja de apartado postal es diferente de su nmero de apartado. Con esto presente, vamos a explorar los elementos e ndices del arreglo un poco ms a fondo.
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-4

MIGUEL . TOLEDO MARTNEZ

ELEMENTOS DEL ARREGLO

Los elementos de un arreglo son los datos almacenados en ste y pueden ser de cualquier clase de datos que se hayan visto. De esta manera, un arreglo dado puede almacenar elementos enteros, elementos de punto flotante, caracteres, y elementos booleanos. Adems, de estos elementos de clase de datos estndar, un arreglo tambin es til para almacenar elementos de datos enumerados. De hecho, aun los elementos de un arreglo pueden ser otros arreglos. Sin embargo, existe una restriccin importante que se aplica a los elementos del arreglo: todos los elementos de un arreglo determinado debern ser de la misma clase de datos. Como se ver en breve, es necesario definir los arreglos en un programa C++. Parte de la definicin es especificar la clase de los elementos que el arreglo almacenar. Una vez que se ha definido un arreglo determinado para cierta clase de datos, slo los elementos de esa clase de datos se almacenarn en ese arreglo.
NDICES DEL ARREGLO

Los ndices del arreglo localizan a los elementos del arreglo, en C++, el compilador en forma automtica asigna ndices enteros a la lista de elementos del arreglo empezando con el ndice 0. Por lo tanto, el primer elemento del arreglo en la figura 18.2 se localiza en el ndice 0, y el ltimo elemento se localiza en el ndice n. Los ndices empiezan con 0 y van a n, por tanto habr n + 1 elementos en el arreglo. Tambin, debido a que es un arreglo unidimensional, o lista, decimos que tiene una dimensin de 1 (n + 1) lo cual significa que hay un rengln de n + 1 elementos. La dimensin de un arreglo indica el tamao del arreglo, justo como la dimensin de una pieza de madera indica su tamao. EXAMEN BREVE 34 DEFINICIN DE ARREGLOS UNIDIMENSIONALES EN C++ En C++ todos los arreglos debern estar definidos. Para definir un arreglo, especifique 3 cosas:
1. 2. 3. La clase de datos de los elementos del arreglo. El nombre del arreglo. El tamao del arreglo.

El formato general es como sigue:


FORMATO PARA UN ARREGLO UNIDIMENSIONAL
<clase de datos del elemento> <nombre del arreglo> [<nmero de elementos del arreglo>];

Lo primero que se ve en la definicin es la clase de datos de los elementos del arreglo. La clase de datos del arreglo es seguida por el identificador del arreglo, su nombre, el cual es seguido por el nmero de elementos que almacena el arreglo dentro de los corchetes, [] La definicin termina con un punto y coma. Por ejemplo, la siguiente es una definicin de un arreglo de 10 caracteres cuyo nombre es caracteres.
char caracteres [10];

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-5

MIGUEL . TOLEDO MARTNEZ

Ejemplo 18.1
Escriba las definiciones para los siguientes arreglos: a. b. c. d. Un arreglo llamado enteros que almacenar 10 enteros. Un arreglo llamado reales que almacenar 5 valores de punto flotante. Un arreglo llamado caracteres que almacenar 11 caracteres. Un arreglo llamado clase que almacenar calificaciones de 25 estudiantes. Suponga que las calificaciones A, B, C, D y R se definen en una clase de datos enumerados denominada calificaciones.

Qu ndice localiza el ltimo elemento en cada uno de los arreglos anteriores?

Solucin
a. b. c. d. e. int enteros[10]; float reales[5]; char caracteres[11]; enum calificaciones {R, D, C, B, A}; calificaciones clase[25]; El ndice que localiza el ltimo elemento en cada uno de los arreglos anteriores es uno menos que el tamao definido del arreglo. En cada una de las definiciones anteriores se menciona primero la clase de datos del elemento, seguida por el identificador del arreglo, despus el tamao del arreglo encerrado en corchetes. Cada una de las definiciones es muy obvia, excepto quiz la definicin del arreglo clase. En esta definicin, la clase de datos del arreglo es la clase de datos enumerada llamada calificaciones, que deber anunciarse antes de la definicin del arreglo. Por tanto, diremos que el arreglo clase puede almacenar elementos cuya clase de datos sean calificaciones. De esta manera, los elementos que se pueden almacenar en el arreglo clase se limitan a los elementos de la clase de datos enumerados de R, D, C, B y A. Observe que el compilador no los considera como caracteres, sino como elementos de una clase de datos enumerados llamada calificaciones.

EXAMEN BREVE 35 EL ACCESO A LOS ARREGLOS Tener acceso al arreglo significa insertar elementos dentro del arreglo para almacenar u obtener elementos almacenados desde el arreglo.
INSERCIN DE ELEMENTOS EN LOS ARREGLOS UNIDIMENSIONALES

Hay bsicamente 3 formas principales de insertar elementos dentro de un arreglo: mediante un enunciado de asignacin directa, mediante lectura o usando ciclos.
ASIGNACIN DIRECTA

El formato general para insertar un elemento, dentro un arreglo, con asignacin directa es como sigue:
FORMATO DE ASIGNACIN DIRECTA (INSERCIN DE ELEMENTOS EN UN ARREGLO) <nombre del arreglo> [ndice del arreglo] = valor del elemento;

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-6

MIGUEL . TOLEDO MARTNEZ

Con las siguientes definiciones de arreglos:


char caracteres[6]; int enteros[3];

las asignaciones directas pueden ser como estas:


caracteres [0] ='H'; caracteres [5] ='\0'; enteros [0] = 16; enteros [2] = -22;

En cada uno de estos ejemplos se coloca un elemento en la primera y en la ltima posicin de almacenamiento del arreglo respectivamente. El carcter 'H' se coloca en la primera posicin del arreglo caracteres y el terminador nulo se coloca en la ltima posicin de este arreglo. Recuerde que la primera posicin de este arreglo es siempre [0] y la ltima posicin del arreglo es siempre uno menos que el tamao del arreglo. El entero 16 se coloca en la primera posicin del arreglo enteros y el entero -22 se coloca en la ltima posicin de este arreglo. Observe que se menciona el nombre respectivo del arreglo, seguido por el ndice del arreglo dentro de corchetes. Entonces se usa un operador de asignacin (=) seguido por el elemento que se va a insertar. La clase de datos del elemento que se inserta deber ser la misma que aquella definida para los elementos del arreglo; de otra manera, se obtendrn resultados impredecibles cuando se trabaje con los elementos del arreglo.
SUGERENCIA DE DEPURACIN
Recuerde que los ndices de un arreglo en C++ son valores enteros. Esto significa que cualquier ndice especificado se convierte en su equivalente entero. Por ejemplo, es posible especificar un ndice como un carcter como este: arreglo['A]; sin embargo, C++ trata esto como arreglo[65], porque, desde el cdigo ASCII, el equivalente entero del carcter A es 65. De la misma manera, se puede especificar un ndice usando un valor de punto flotante, como este: arreglo[1.414], sin embargo, C++ lo ve como arreglo[1], porque la parte entera de 1.414 es 1. Los elementos de datos enumerados tambin se pueden usar como ndices, porque el compilador iguala los elementos enumerados a enteros, de acuerdo con el orden listado en el enunciado de la clase de datos enumerados. Para evitar confusin y problemas potenciales, se sugiere utilizar siempre valores enteros en los ndices, a menos que la aplicacin especficamente indique otra cosa. LECTURA DE LOS ELEMENTOS DEL ARREGLO

Tambin es posible usar cualquiera de las funciones u objetos de entrada de C o C++ para insertar los elementos del arreglo desde un teclado, como sigue:
cin > caracteres[1]; cin > enteros[0];

En este caso, el usuario deber escribir el valor del elemento del arreglo respectivo desde el teclado y oprimir la tecla ENTER para ejecutar cada enunciado. Deber escribir un carcter para el primer enunciado cin y un entero para el segundo cin. (Por qu?) El carcter escrito desde el teclado se almacenar en la segunda posicin (ndice[1]) del arreglo caracteres, mientras que el entero escrito desde el teclado se almacenar en la primera posicin (ndice[0]) del arreglo enteros.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-7

MIGUEL . TOLEDO MARTNEZ

INSERCIN ELEMENTOS DE ARREGLOS CON EL USO DE CICLOS

La desventaja obvia al usar asignaciones directas para insertar elementos de arreglos es que se requiere un enunciado de asignacin separado para llenar cada posicin del arreglo. Puede automatizar el proceso de insercin usando una estructura de ciclo. Aunque cualquiera de las tres estructuras de ciclo (while, do/while, for) se puede emplear, la estructura for es la ms comn. A continuacin est el formato general para el uso de un ciclo for:
INSERCIN DENTRO DE UN ARREGLO UNIDIMENSIONAL CON EL USO DE UN CICLO for for(int indice = 0; indice < tamao del arreglo; ++indice) <asigna o lee arreglo[indice]>

Considere el siguiente programa:


//LLENADO DE UN ARREGLO CON UN CICLO for #include <iostream.h> // Para cin y cout // DECLARA EL TAMAO DEL ARREGLO const int MAX = 10; void main(void) { int muestra[MAX]; // DEFINE UN ARREGLO ENTERO

cout << "Escriba una lista de" << MAX << " elementos y presione" " la tecla ENTER despus de cada entrada." << endl; for (int i = 0; i < MAX; ++i) cin >> muestra[i]; } // FINAL DE main()

Primero, observe la declaracin de la constante global de nombre MAX. Note dnde se utiliza MAX en el programa. ste es el valor del tamao del arreglo y el valor del contador final en el ciclo for. El uso de una constante como sta le permite cambiar el tamao del arreglo fcilmente. Aqu, el tamao del arreglo tiene 10 elementos. Para cambiar el tamao del arreglo, slo necesitar hacer un cambio en un lugar en el programa dentro del enunciado constante. Despus, vea la definicin del arreglo. El arreglo muestra se define en forma local como un arreglo de elementos enteros. Se le pide al usuario: "Escriba una lista de MAX elementos (donde MAX es 10) y presione la tecla ENTER despus de cada entrada.". Una vez que se muestra la pregunta, el programa entra a un ciclo for. La variable contador del ciclo es i, con rango desde 0 a MAX. Cuando el contador del ciclo alcance el valor MAX, el ciclo se rompe porque la verificacin del ciclo es i < MAX. Es importante usar la verificacin menor que (<) en lugar de usar la verificacin menor que o igual a (<=); de otra manera, el ciclo se ejecutar demasiadas veces. (Por qu?) El contador del ciclo se emplea como el valor del ndice para el arreglo. Con cada iteracin del ciclo, se ejecuta un solo enunciado cin para insertar un elemento dentro del arreglo en la posicin respectiva especificada por el contador del ciclo, i. Analicemos el enunciado cin. Primero, el identificador muestra se lista con la variable contador de ciclo i como el ndice del arreglo dentro de corchetes. Qu hace i con cada iteracin de ciclo? Se incrementa desde 0 a MAX, correcto? Como resultado, la primera iteracin de ciclo lee un valor dentro de muestra[0], la segunda iteracin lee un valor dentro de muestra[1] y as sucesivamente, hasta que la ltima iteracin de ciclo lee un valor dentro de la ltima posicin
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-8

MIGUEL . TOLEDO MARTNEZ

del arreglo muestra[MAX 1] Cuando el contador de ciclo se incremento al valor MAX al final de la ltima iteracin de ciclo, ste se rompe y no se insertan ms elementos dentro del arreglo. Eso es todo! El arreglo est lleno! Tambin puede usar ciclos para asignar valores a los elementos del arreglo. Por ejemplo, usando las definiciones anteriores, considere este ciclo:
for (int i = 0; i < MAX; ++i) muestra[i] = 2 * i;

Esta vez, los elementos del arreglo se asignan dos veces al valor del contador de ciclo con cada iteracin de ciclo. Qu valores se insertan realmente dentro del arreglo? Qu pasa con los 10 enteros pares de 0 a 18? EXTRACCIN DE ELEMENTOS DE LOS ARREGLOS UNIDIMENSIONALES Primero, se le advierte que la palabra extraer no es un buen trmino aqu. Por qu? Porque, en general, la palabra extraer significa eliminar algo, cuando extraemos un elemento de un arreglo, realmente no lo eliminamos! Simplemente copiamos su valor. El elemento permanece almacenado en el arreglo hasta que se reemplaza por otro valor usando una operacin de insercin. Como con la insercin, es posible extraer elementos del arreglo usando uno de los tres mtodos generales: asignacin directa, escritura o ciclo.
ASIGNACIN DIRECTA

La extraccin de los elementos del arreglo usando enunciados de asignacin es lo inverso de la insercin de elementos utilizando un enunciado de asignacin. ste es el formato general:
FORMATO DE ASIGNACIN DIRECTA (EXTRACCIN DE ELEMENTOS DEL ARREGLO)
<identificador del objeto variable> = <nombre del arreglo>[ndice del arreglo]

Como ejemplo, suponga que se hacen las siguientes definiciones:


const int MAX = 10; int muestra[MAX]; int x;

Como puede observar, el arreglo muestra[] consta de 10 elementos enteros. Ahora, suponga que el arreglo est lleno, Qu harn los siguientes enunciados?
x = muestra[0]; x = muestra[MAX - 1]; x = muestra[3] * muestra[5]; x = 2 * muestra[2] -3 * muestra[7];

El primer enunciado asigna el elemento almacenado en la primera posicin del arreglo a la variable x. El segundo enunciado asigna el elemento almacenado en la ltima posicin del arreglo a la variable x. El tercer enunciado asigna el producto de los elementos localizados en los ndices [3] y [5] a x. Por ltimo, el cuarto enunciado asigna a x dos veces el elemento localizado en el ndice[2] menos tres veces el elemento localizado en el ndice [7] Los ltimos dos
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-9

MIGUEL . TOLEDO MARTNEZ

enunciados muestran cmo se pueden realizar las operaciones aritmticas con los elementos del arreglo. En todos los casos anteriores, los valores de los elementos del arreglo no se afectan por las operaciones de asignacin. El principal requerimiento es que x debe estar definida como la misma clase de datos de los elementos del arreglo para no obtener resultados inesperados. Como ejemplo final, considere estos enunciados de asignacin:
muestra[0] = muestra[MAX - 1]; muestra[1] = Muestra[2] + Muestra[3];

Puede usted determinar qu pasa aqu? En el primer enunciado, el primer elemento del arreglo se reemplaza por medio del ltimo elemento del arreglo, se afecta el ltimo elemento del arreglo? No, porque aparece del lado derecho del operador de asignacin. En el segundo caso, el segundo elemento del arreglo en el ndice [1] se reemplaza por la suma del tercero y cuarto elementos del arreglo en los ndices [2] y [3] De nuevo, el tercero y cuarto elementos del arreglo no se afectan por esta operacin, porque aparecen del lado derecho del operador de asignacin.
ESCRITURA DE ELEMENTOS DEL ARREGLO

Los objetos cout se usan para mostrar los elementos del arreglo. Usemos el mismo arreglo para demostrar cmo escribir elementos del arreglo. Aqu est de nuevo la definicin del arreglo:
const int MAX = 10; int muestra[MAX];

Qu se supone que harn los siguientes enunciados?


cout << muestra[0] << endl; cout << muestra[MAX - 1] << endl; cout << muestra[1] / muestra[2] << endl; cout << sqrt(muestra[6]) << endl;

El primer enunciado mostrar el elemento contenido en el ndice [0] del arreglo. El segundo presentar el ltimo elemento del arreglo, localizado en el ndice [MAX 1] El tercer enunciado dividir el elemento localizado en el ndice [1] entre el elemento en el ndice [2] y mostrar el cociente entero. Por ltimo, el cuarto presentar la raz cuadrada del elemento localizado en el ndice [6] Ninguno de los valores del elemento del arreglo se afectar con estas operaciones.
EXTRACCIN DE ELEMENTOS DEL ARREGLO CON EL USO DE CICLOS

Al igual que en la insercin de elementos en un arreglo, la extraccin de elementos del arreglo con ciclos requiere menos codificacin, especialmente cuando se extraen elementos mltiples. De nuevo, se puede usar cualquier estructura de ciclo para este propsito, pero los ciclos for son los ms comunes. Considere el siguiente programa:

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-10

MIGUEL . TOLEDO MARTNEZ

// MUESTRA UN ARREGLO CON UN CICLO for #include <iostream.h> // Para cin y cout // ENUNCIA EL TAMAO DEL ARREGLO const int MAX = 10; void main(void) { int muestra[MAX]; // DEFINE UN ARREGLO ENTERO for(int i = 0; i < MAX; ++i) muestra[i] = i * i; for (int i = 0; i < MAX; ++i) cout << muestra[i] <<\t; } // FINAL DE main()

De nuevo, el arreglo se define localmente como un arreglo de valores enteros MAX[10] Su nombre es muestra. Observe que se usa la variable contador de ciclo i como el ndice del arreglo en ambos ciclos for. El primer ciclo llenar los lugares del arreglo con el cuadrado del contador de ciclo. Entonces, el segundo ciclo mostrar cada uno de los elementos del arreglo localizados desde el ndice [0] hasta el ndice [MAX 1] Se usa un enunciado cout para mostrar los elementos del arreglo en forma horizontal a travs de la pantalla. Observe tambin que cada vez que se muestra un elemento, se escribe un tabulador despus del elemento para separarlo del siguiente elemento de la secuencia. Esto es lo que ver en la pantalla: 0 1 4 9 16 25 36 49 64 81

SUGERENCIA DE DEPURACIN Procure no especificar un ndice del arreglo fuera de rango. Tal ndice puede ser uno que sea menor que 0 o mayor que el valor mximo del ndice. Por ejemplo, suponga que define un arreglo como ste: const int MAX = 10; char arreglo[MAX]; Un error comn al usar esta definicin sera intentar tener acceso al elemento arreglo[MAX] Sin embargo, recuerde que los ndices de los arreglos en C++ empiezan con 0; por tanto, MAX especifica una posicin ms all del valor del ndice mximo del arreglo. El valor del ndice mximo en este arreglo es MAX - 1. En una situacin de ciclo, el siguiente enunciado de ciclo dar origen al mismo problema: for (int i = 0; i <= MAX, ++i) cout << A[i]; De nuevo, la ltima iteracin de ciclo especifica un ndice del arreglo de MAX, que est fuera de rango del ndice. Para evitar este error, la verificacin ser i < MAX o i <= MAX - 1. Cuando un ndice de arreglo est fuera de rango, no se obtendr un error de compilacin. En el mejor de los casos se obtendr basura. En la peor situacin, se destruir algo en la memoria que requiera su programa o sistema operativo, lo que dara origen a la cada del sistema o programa. Errores como ste son muy difciles de localizar. As que asegrese de que sus ndices siempre estn dentro de su rango especificado.

EXAMEN BREVE 36

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-11

MIGUEL . TOLEDO MARTNEZ

A continuacin se darn varios ejemplos en los que se utilicen los conocimientos antes adquiridos. Ejemplo 18.2
El siguiente programa, INICIALIZA.CPP, utiliza una estructura de repeticin for para inicializar a cero los elementos de un arreglo de enteros llamado arreglo de diez elementos; luego imprime dicho arreglo en formato de tabla. /* El siguiente programa: INICIALIZA.CPP, inicializa a ceros a un arreglo de 10 elementos, posteriormente imprime el contenido de dicho arreglo. */ #include <iostream.h> #include <iomanip.h> void main(void) { int i, arreglo[10]; for(i = 0; i < 10; i++) arreglo[i] = 0; //Para cout y cin //Para setw()

//Inicializa el arreglo

cout << "Elemento" << setw(13) << "Valor" << endl; for(i= 0; i < 10; i++) // Imprime el arreglo cout << setw(7) << i << setw(13) << arreglo[i] << endl; }//Fin de main()

Ejemplo 18.3
El siguiente programa DECLARA.CPP, inicializa los elementos de un arreglo al declararse. Observe como se utilizan el signo de igualdad y una lista de valores separados por coma (encerrados entre corchetes) /* El siguiente programa: DECLARA.CPP, inicializa los elementos de un arreglo mediante una declaracin. Mediante un for se muestra el contenido de dicho arreglo. */ #include <iostream.h> #include <iomanip.h> void main(void) { int i, arreglo[10] = {32, 27, 64, 18, 95, 14, 90, 70, 60, 37}; cout << "Elemento" << setw(13) << "Valor" << endl; for(int i = 0; i < 10; i++) cout << setw(7) << i << setw(13) << arreglo[i] << endl; }//Fin de main() Si hubiera menos valores que elementos en el arreglo, los elementos restantes se inicializaran automticamente a cero. Por ejemplo, los elementos del arreglo arreglo[10], del programa INICIALIZA.CPP, se podran haber inicializado a cero con la declaracin: int arreglo[10] = {0};
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

//Para cout y cin //Para setw()

18-12

MIGUEL . TOLEDO MARTNEZ

que explcitamente inicializa a cero el primer elemento e implcitamente inicializa a cero a los otros nueve elementos, pues hay menos valores que elementos en el arreglo. Recuerde que los arreglos automticos no se inicializan implcitamente a cero. El programador debe inicializar a cero cuando menos el primer elemento para que los dems se inicialicen a cero de manera automtica. La siguiente declaracin de arreglo: int arreglo[5] = {32, 27, 64, 18, 95, 14}; provocara un error de sintaxis, pues hay 6 inicializadores y nicamente 5 elementos en el arreglo. Si se omite el tamao del arreglo en la declaracin por medio de una lista de inicio, el numero de elementos del arreglo ser el nmero de elementos de dicha lista. Por ejemplo: int arreglo[] = {1, 2, 3, 4, 5}; crear un arreglo de cinco elementos.

Ejemplo 18.4
El siguiente programa, ELEMENTS.CPP, inicializa el arreglo llamado calificaciones y luego visualiza sus elementos. /* El siguiente programa: ELEMENTS.CPP, inicializa el arreglo calificaciones y luego visualiza sus elementos. */ #include <iostream.h> void main(void) { int calificaciones[5] = {80, 70, 90, 85, 80}; cout << "Valores del arreglo" << endl << endl; cout << "calificaciones[0] = " << calificaciones[0] << endl; cout << "calificaciones[1] = " << calificaciones[1] << endl; cout << "calificaciones[2] = " << calificaciones[2] << endl; cout << "calificaciones[3] = " << calificaciones[3] << endl; cout << "calificaciones[4] = " << calificaciones[4] << endl; }//Fin de main() //Para cout y cin

Ejemplo 18.5
El siguiente programa MSTARRE.CPP, utiliza el ciclo for para mostrar el contenido del arreglo calificaciones. /* El siguiente programa: MSTARRE.CPP, utiliza la variable i y el ciclo for para visualizar los elementos del arreglo llamado calificaciones. */ #include <iostream.h> //Para cout y cin

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-13

MIGUEL . TOLEDO MARTNEZ

void main(void) { int calificaciones[5] = {80, 70, 90, 85, 80}; int i; cout << "Valores del arreglo" << endl << endl; for (i = 0; i < 5; i++) cout << "calificaciones[" << i << "] = " << calificaciones[i] << endl; }//Fin de main()

Ejemplo 18.6
El siguiente programa, 5VALORES.CPP, muestra 5 valores de un arreglo mediante una ciclo for. /* El siguiente programa: 5VALORES.CPP, declara un arreglo con cinco valores y luego utiliza el ciclo for para visualizar los valores del arreglo. */ #include <iostream.h> void main(void) { int valores[5] = {80, 70, 90, 85, 80}; int i; for (i = 0; i < 5; i++) cout << "Valores[" << i << "] = " << valores[i] << endl; }//Fin de main() //Para cout y cin

Ejemplo 18.7
El siguiente programa 5CONSTANTES.CPP, ilustra como declarar un arreglo utilizando una constante. /* El siguiente programa: 5CONSTANTES.CPP, declara un arreglo basado en la constante TAMANO_ARREGLO. */ #include <iostream.h> #define TAMANO_ARREGLO 5 void main(void) { int valores[TAMANO_ARREGLO] = {80, 70, 90, 85, 80}; int i; for (i = 0; i < TAMANO_ARREGLO; i++) cout << "valores[" << i << "] = " << valores[i] << endl; }//Fin de main() //Para cout y cin

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-14

MIGUEL . TOLEDO MARTNEZ

Ejemplo 18.8
El siguiente programa, PARES.CPP, inicializa los elementos de un arreglo llamado arreglo de diez elementos a los enteros 2, 4, 6, ... , 20, e imprime el arreglo en formato de tabla. Estos nmeros se generan multiplicando por 2 cada valor consecutivo del contador del ciclo y sumndole 2. /* Este programa: PARES.CPP inicializa un arreglo con los enteros pares comprendidos entre 2 y 20 inclusive. */ #include <iostream.h> #include <iomanip.h> void main(void) { const int TAMANO_ARREGLO = 10; int j, arreglo[TAMANO_ARREGLO]; for(j = 0; j < TAMANO_ARREGLO;j++) //Inicializa arreglo arreglo[j] = 2 + 2 * j; cout << "Elemento" << setw(13) << "Valor" << endl; for(j = 0; j < TAMANO_ARREGLO; j++) //Imprime los valores cout << setw(7) << j << setw(13) << arreglo[j] << endl; }//Fin de main() //Para cout y cin //Para setw()

Ejemplo 18.9
El siguiente programa, TAMARRE.CPP, utiliza el operador sizeof() para visualizar la cantidad de memoria utilizada por los diferentes tipos de arreglos. /* El siguiente programa: TAMARRE.CPP, utiliza el operador sizeof() para visualizar la cantidad de memoria utilizada por los diferentes tipos de arreglos. */ #include <iostream.h> void main(void) { int calificaciones[100]; float salarios[100]; char cadena[100]; cout << "Bytes utilizados en el arreglo calificaciones[100] = " << sizeof(calificaciones)<< endl; cout << "Bytes utilizados en el arreglo salarios[100] sizeof(salarios) << endl; cout << "Bytes utilizados en el arreglo cadena[100] sizeof(cadena) << endl; }//Fin de main() = " << //Para cout y cin

= " <<

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-15

MIGUEL . TOLEDO MARTNEZ

Ejemplo 18.10
El siguiente programa, SUMAVALORES.CPP, suma los valores contenidos en el arreglo de enteros de doce elementos. /* El siguiente programa: SUMAVALORES.CPP, Calcula la suma de los elementos de un arreglo. */ #include <iostream.h> void main(void) { const int TAMANO_ARREGLO = 12; int arreglo[TAMANO_ARREGLO] = {1, 3, 5, 4, 7, 2, 99, 16, 45, 67, 89, 45}; int total = 0; for(int i = 0; i < TAMANO_ARREGLO; i++) total += arreglo[i]; cout << "El total de los elementos del arreglo es: " << total << endl; }//Fin de main() //Para cout y cin

Ejemplo 18.11
El siguiente programa, FRECUENCIA.CPP, se vale de arreglos para resumir los resultados de la informacin recolectada en una encuesta. Considere el planteamiento del problema: Se pidi a cuarenta estudiantes que calificaran la calidad de la comida de la cafetera estudiantil en escala del 1 al 10 (1 significa terrible y 10 excelente) Ponga las cuarenta respuestas en un arreglo de enteros y resuma el resultado de la encuesta (cuantos calificaron por cada valor de la escala) /* El siguiente programa: FRECUENCIA.CPP, ilustra una encuesta realizada entre estudiantes. */ #include <iostream.h> #include <iomanip.h> void main(void) { const int TAMANO_RESPUESTA = 40, TAMANO_FRECUENCIA = 11; int respuestas[TAMANO_RESPUESTA] = {1, 2, 6, 4, 8, 5, 9, 7, 8, 10, 1, 6, 3, 8, 6, 10, 3, 8, 2, 7, 6, 5, 7, 6, 8, 6, 7, 5, 6, 6, 5, 6, 7, 5, 6, 4, 8, 6, 8, 10}; int frecuencia[TAMANO_FRECUENCIA] = {0}; for(int numeroRespuestas = 0; numeroRespuestas < TAMANO_RESPUESTA; numeroRespuestas++) ++frecuencia[respuestas[numeroRespuestas]]; cout << "Calidad" << setw(17) << "Frecuencia" << endl; for(int calidad = 1; calidad < TAMANO_FRECUENCIA; calidad++) cout << setw(6) << calidad << setw(17) << frecuencia[calidad] << endl; }//Fin de main() //Para cout y cin //Para setw()

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-16

MIGUEL . TOLEDO MARTNEZ

Ejemplo 18.12
El siguiente programa, PROMEDIO1.CPP, calcula el promedio de los elementos de un arreglo. Los elementos del arreglo son preasignados. /* El siguiente programa: PROMEDIO1.CPP, calcula el valor promedio de un arreglo. Los elementos del arreglo estn preasignados. */ #include <iostream.h> //Para cout y cin

const int TAMANO_ARREGLO = 10; void main(void) { double arreglo[TAMANO_ARREGLO] = { 12.2, 45.4, 67.2, 12.2, 34.6, 87.4, 83.6, 12.3, 14.8, 55.5 }; double suma = 0; for (int ix = 0; ix < TAMANO_ARREGLO; ++ix) { suma += arreglo[ix]; cout << "arreglo[" << ix << "]: " << arreglo[ix] << endl; }//Fin de for cout << endl << "Promedio: " << suma / TAMANO_ARREGLO << endl; }//Fin de main()

Ejemplo 18.13
El siguiente programa, PROMEDIO2.CPP, calcula el promedio de los elementos de un arreglo. Los valores del arreglo son solicitados por el teclado. /* El siguiente programa: PROMEDIO2.CPP, calcula el valor promedio del arreglo que es inicializado desde el teclado */ #include <iostream.h> //Para cout y cin

const int TAMANO_ARREGLO = 30; void main(void) { double arreglo[TAMANO_ARREGLO]; int numeroElementos; // Obtiene la cantidad de puntos de datos do { cout << "Introduzca el nmero de puntos de datos [2 a " << TAMANO_ARREGLO << "]: "; cin >> numeroElementos; cout << endl; } while (numeroElementos < 2 || numeroElementos > TAMANO_ARREGLO); // Pide datos al usuario for (int ix = 0; ix < numeroElementos; ix++) { cout << "arreglo[" << ix << "]: "; cin >> arreglo[ix]; }//Fin de for ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-17

MIGUEL . TOLEDO MARTNEZ

// Ahora obtiene el promedio double suma = 0; for (int ix = 0; ix < numeroElementos; ++ix) suma += arreglo[ix]; cout << endl << "Promedio: " << suma / numeroElementos << endl; }//Fin de main()

Ejemplo 18.14
Nuestro siguiente programa, HISTOGRAMA.CPP, lee los nmeros de un arreglo llamado arreglo y traza la informacin en forma de un grfico de barras o histograma; cada nmero se imprime, seguido de una barra consistente en la misma cantidad de asteriscos. /* El siguiente programa: HISTOGRAMA.CPP, imprime un histograma. */ #include <iostream.h> #include <iomanip.h> void main(void) { const int TAMANO_ARREGLO = 10; int arreglo[TAMANO_ARREGLO] = {19, 3, 15, 7, 11, 9, 13, 5, 17, 1}; cout << "Elemento" << setw(13) << "Valor" << setw(17) << "Histograma" << endl; //Para cout y cin //Para setw()

for(int i = 0; i < TAMANO_ARREGLO; i++) { cout << setw(7) << i << setw(13) << arreglo[i] << setw(9); for(int j = 0; j < arreglo[i]; j++) cout << '*'; cout << endl; }//Fin del for }//Fin de main() //Imprime una barra

Ejemplo 18.15
El siguiente programa, FRECUENCIA2.CPP, ilustra una nueva forma de codificar el problema del lanzamiento de un dado 6000 veces, determinando la frecuencia de cada cara. /* El siguiente programa: FRECUENCIA2.CPP, ilustra la frecuencia de cada cara de un dado al lanzarse 6000 veces. */ #include <iostream.h> #include <iomanip.h> #include <stdlib.h> #include <time.h> //Para cout y cin //Para setw() //Para srand() y rand() //Para time()

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-18

MIGUEL . TOLEDO MARTNEZ

void main(void) { const int TAMANO_ARREGLO = 7; int cara, frecuencia[TAMANO_ARREGLO] = {0}; srand(time(0)); for(int tirada = 1; tirada <= 6000; tirada++) ++frecuencia[1 + rand() % 6]; //Reemplaza el switch cout << "Cara" << setw(13) << "Frecuencia" << endl; //Ignora el elemento 0 del arreglo frecuencia[] for(cara = 1; cara < TAMANO_ARREGLO; cara++) cout << setw(4) << cara << setw(13) << frecuencia[cara] << endl; }//Fin de main()

Ejemplo 18.16
El siguiente programa, CARACTERES.CPP, muestra la inicializacin de un arreglo de caracteres con una literal de cadena; la lectura de una cadena para dejarla en un arreglo de caracteres; la impresin de un arreglo de caracteres como cadena y el acceso a los caracteres individuales de una cadena. /* El siguiente programa: CARACTERES.CPP, ilustra el manejo de arreglos de caracteres como cadenas. */ #include <iostream.h> void main(void) { char cadena1[20], cadena2[] = "Cadena literal de caracteres"; cout << "Introduzca una cadena de caracteres: "; cin >> cadena1; //Para estudiar lo que ocurre, escriba: Hola all. cout << "La cadena1 es: " << cadena1 << "\nLa cadena2 es: " << cadena2 << "\nLa cadena1 con espacios entre caracteres es: "; //Para cout y cin

for(int i = 0; cadena1[i] != '\0'; i++) cout << cadena1[i] << ' '; cin >> cadena1; //Lee all cout << "\nLa cadena es: " << cadena1 << endl; }//Fin de main()

Ejemplo 18.17
El siguiente programa. ESTAUTO.CPP, ilustra el uso de dos arreglos, uno static y el otro automtico; en ambos casos se analiza su contenido visualizando en la pantalla.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-19

MIGUEL . TOLEDO MARTNEZ

/* El siguiente programa: ESTAUTO.CPP, ilustra el uso de arreglos estticos y automticos. */ #include <iostream.h> void arregloEstatico(void); void arregloAutomatico(void); void main(void) { cout << "Primera llamada a cada funcin:\n"; arregloEstatico(); arregloAutomatico(); cout << "\n\nSegunda llamada a cada funcin:\n"; arregloEstatico(); arregloAutomatico(); cout << endl; }//Fin de main() //Funcin que muestra un arreglo esttico local void arregloEstatico(void) { static int arreglo1[3]; int i; cout << "\nValores al entrar a arregloEstatico():\n"; for(i = 0; i < 3; i++) cout << "arreglo1[" << i << "] = " << arreglo1[i] << " "; cout << "\nValores al salir de arregloEstatico():\n"; for(i = 0; i < 3; i++) cout << "arreglo1[" << i << "] = " << (arreglo1[i] += 5) << " "; }//Fin de arregloEstatico() void arregloAutomatico(void) { int i, arreglo2[3] = {1, 2, 3}; cout << "\n\nValores al entrar a arregloAutomatico():\n"; for(i = 0; i < 3; i++) cout << "arreglo2[" << i << "] = " << arreglo2[i] << " "; cout << "\nValores al salir de arregloAutomatico():\n"; for(i = 0; i < 3; i++) cout << "arreglo2[" << i << "] = " << (arreglo2[i] += 5) << " "; }//Fin de arregloAutomatico() //Para cout y cin

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-20

MIGUEL . TOLEDO MARTNEZ

PASO DE ARREGLOS Y ELEMENTOS DE ARREGLOS A LAS FUNCIONES Es posible pasar un arreglo completo a una funcin o pasar slo elementos de un arreglo a una funcin. Lo importante de recordar es que para pasar un arreglo completo, deber pasar la direccin del arreglo. En C y C++, el nombre del arreglo es la direccin del primer elemento (ndice[0]) del arreglo. Empecemos viendo el encabezado de la funcin. ste es el prototipo para pasar un arreglo unidimensional a una funcin:
void raro(char arreglo[TAMANO_ARREGLO]); o lo que es ms correcto void raro(char arreglo[], int tamanoArreglo);

Observe el prototipo, vea que la funcin no regresa un valor. Hay un parmetro de caracteres llamado arreglo[TAMANO_ARREGLO] La nica serie de corchetes despus del identificador del parmetro implica que el parmetro es un arreglo unidimensional con un tamao TAMANO_ARREGLO. Cuando se pasan los arreglos a una funcin, la funcin deber saber qu tan grande es el arreglo que aceptar. Ahora, el identificador del arreglo hace referencia a la direccin del arreglo, as el arreglo pasa por referencia a la funcin. De esta manera, cualquier operacin en el arreglo dentro de la funcin afectar el contenido original del arreglo en el programa llamador. Asimismo, dado que el parmetro es la direccin del arreglo, no se requiere ningn smbolo ampersand, (&), para pasar el arreglo por referencia. De hecho, el uso de un smbolo ampersand antes del parmetro del arreglo originar un error de compilacin. Despus, para llamar esta funcin y pasar el arreglo, simplemente utilice el siguiente enunciado:
raro(nombreArreglo); o lo que es ms correcto raro(nombreArreglo, tamanoArreglo);

Desde luego, esta llamada supone que nombreArreglo es la denominacin del arreglo en el programa llamador. (Recuerde que el identificador del argumento real y el identificador del parmetro formal pueden ser diferentes.) La llamada a nombreArreglo da referencia de la direccin del arreglo, de manera que, la direccin del arreglo pasa a la funcin ms que una copia del arreglo. As, cualquier operacin en el arreglo dentro de la funcin afectar los elementos originales del arreglo. Un programa completo es como sigue:
Ejemplo 18.18
/* El siguiente programa: PASARRE.CPP, ilustra como se pasa un arreglo a una funcin. */ #include<iostream.h> // Para cin y cout

// DECLARA EL TAMAO DEL ARREGLO const int TAMANO_ARREGLO = 3;

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-21

MIGUEL . TOLEDO MARTNEZ

// FUNCIN PROTOTIPO void raro(char arreglo[TAMANO_ARREGLO]); void main(void) { //DEFINE UN ARREGLO DE CARACTERES char nombre[TAMANO_ARREGLO]; //LLENE EL ARREGLO nombre CON CARACTERES nombre[0] ='I'; nombre[1] ='B'; nombre[2] ='M'; //MUESTRA EL ARREGLO nombre cout << El contenido de nombre[] antes de raro() es: ; for (int i = 0; i < TAMANO_ARREGLO; ++i) cout << nombre[i]; //LLAMA A LA FUNCIN raro() raro(nombre); //MUESTRA EL ARREGLO nombre cout << \n\nEl contenido de nombre[] despus de raro() es: ; for (int i = 0; i < TAMANO_ARREGLO; ++i) cout << nombre[i]; } // Fin de main() // ESTA FUNCIN DECREMENTA CADA UNO DE LOS ELEMENTOS DEL ARREGLO void raro(char arreglo[TAMANO_ARREGLO]) { for (int i = 0; i < TAMANO_ARREGLO; ++i) --arreglo[i]; } // Fin de raro() El arreglo nombre[] se define como un arreglo de caracteres y se llena en main() usando la asignacin directa, con los caracteres 'I', 'B', 'M'. Los caracteres que se almacenan en el arreglo se muestran en la pantalla utilizando un ciclo for. Luego, se llama a la funcin raro() usando el nombre del arreglo, nombre, como su argumento. Con esto se pasa la direccin del arreglo a la funcin raro(), en donde se decrementa cada uno de los elementos del arreglo. Qu se supone que ver el usuario en la pantalla despus de ejecutar el programa? Bien, las cosas parecen raras porque: El contenido de nombre[] antes que raro() es: IBM El contenido de nombre[] despus de raro() es: HAL Lo interesante aqu es que la operacin decremento dentro de la funcin afecta a los elementos originales del arreglo. De esta manera, la palabra IBM se convirti en la palabra HAL. Hay algo raro aqu? Recuerde que HAL fue la computadora con inteligencia artificial en el libro y la pelcula 2001: Odisea en el espacio. Hay un mensaje aqu o slo es una coincidencia? Tendr que preguntar al autor, Arthur Clarke, para descubrirlo. Por ltimo, no es posible pasar el arreglo completo por valor a una funcin. Si no quiere que las operaciones de la funcin afecten a los elementos del arreglo, deber pasar el arreglo a la funcin, hacer una copia local temporal del arreglo dentro de la funcin y despus operar sobre este arreglo temporal. Por otra parte, es posible pasar por valor los elementos individuales del arreglo a una funcin. Vea la siguiente funcin prototipo:
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-22

MIGUEL . TOLEDO MARTNEZ

void pasaPorValor(int elementoArreglo); El encabezado dice que la funcin no regresa ningn valor y espera recibir un valor entero desde el programa llamador. Suponga que se hace un llamado a la funcin como sigue: pasaPorValor(registros[0]); Observe que el argumento real en la llamada de la funcin es registros[0] Esto genera una copia del elemento almacenado en el ndice [0] en el arreglo registros[] que ser transferido a la funcin por valor. Como resultado, cualquier operacin en este elemento dentro de la funcin no afectar el valor del elemento en el arreglo registros[] original. Si quiere que el elemento manifieste algn cambio dentro de la funcin, deber pasarla por referencia usando el smbolo ampersand en la funcin prototipo, como sta: void pasaPorReferencia(int &elementoArreglo); Ahora, cualquier llamada a la funcin pasar la direccin del elemento a la funcin, pasando de esta manera el elemento por referencia.

Ejemplo 18.19
El siguiente programa muestra cmo los elementos de un arreglo pasan por valor o por referencia. /* El siguiente programa: PASVALREF.CPP, ilustra el uso de paso de elementos de un arreglo por valor y por referencia. */ #include <iostream.h> // Para cin y cout

//ENUNCIA EL TAMAO DEL ARREGLO const int TAMANO_ARREGLO = 3; //FUNCIONES PROTOTIPO void pasaPorValor(int elementoArreglo); void pasaPorReferencia(int &elementoArreglo); void main(void) { int registros[TAMANO_ARREGLO]; registros[0] = 10; registros[1] = 20; registros[2] = 30; cout << El valor del elemento en registros[0] antes de pasaPorValor es << registros[0] << endl; :

pasaPorValor(registros[0]); cout << El valor del elemento en registros[0] despus de pasaPorValor es << registros[0] << endl; :

cout

<< "El valor del elemento en registros[0] antes de pasaPorReferencia es: << registros[0] << endl;

pasaPorReferencia(registros[0]); << Elemento en registros[0] despus de pasaPorReferencia es << registros[0] << endl; } // FINAL DE main()
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

cout

18-23

MIGUEL . TOLEDO MARTNEZ

void pasaPorValor(int elementoArreglo) { ++elementoArreglo; } // Final de pasaPorValor() void pasaPorReferencia(int &elementoArreglo) { ++elementoArreglo; } // Final de pasaPorReferencia() La salida que produce el programa manifiesta el efecto de las dos funciones en el elemento del arreglo. El valor del elemento en registro[0] antes de pasaPorValor() es : 10 El valor del elemento en registro[0] despus de pasaPorValor() es : 10 El valor del elemento en registro[0] antes de pasaPorReferencia() : 10 El valor del elemento en registro[0] despus de pasaPorReferencia(): 11

Estudie los dos programas siguientes para asegurarse que comprende cmo pasan a las funciones los arreglos completos y los elementos individuales del arreglo.
Ejemplo 18.20
El siguiente programa, PASOARRE2.CPP, muestra la diferencia entre pasar un arreglo completo y pasar un elemento del arreglo. /* El siguiente programa: PASOARRE2.CPP, pasa un arreglo y elementos del arreglo a funciones. */ #include <iostream.h> #include <iomanip.h> void modificarArreglo(int[], int); void modificarElemento(int); void main(void) { const int TAMANO_ARREGLO = 5; int i, arreglo[TAMANO_ARREGLO] = {0, 1, 2, 3, 4}; cout << "Efectos de pasar un arreglo completo mediante llamada por referencia:" << "\n\nLos valores del arreglo original son:\n"; //Para cout y cin //Para setw()

for(i = 0; i < TAMANO_ARREGLO; i++) cout << setw(3) << arreglo[i]; cout << endl; //Se pasa el arreglo mediante llamada por referencia modificarArreglo(arreglo, TAMANO_ARREGLO); cout << "Los valores del arreglo modificado son:\n"; for(i = 0; i < TAMANO_ARREGLO; i++) cout << setw(3) << arreglo[i];

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-24

MIGUEL . TOLEDO MARTNEZ

cout

<< "\n\n\n" << "Efectos de pasar un elemento del arreglo mediante llamada por valor:" << "\n\nEl valor de arreglo[3] es " << arreglo[3] << '\n';

modificarElemento(arreglo[3]); cout << "El valor de arreglo[3] es " << arreglo[3] << endl; }//Fin de main() void modificarArreglo(int b[], int tamanoArreglo) { for(int j = 0; j < tamanoArreglo; j++) b[j] *= 2; }//Fin de modificarArreglo() void modificarElemento(int e) { cout << "El valor en modificarElemento() es " << (e *= 2) << endl; }//Fin de modificarElemento()

Ejemplo 18.21
El siguiente programa, ARRFUNCT.CPP, ilustra el uso de paso de un arreglo a una funcin. /* El siguiente programa: ARRFUNCT.CPP, utiliza la funcin mostrarArreglo(), para visualizar los valores de un arreglo. */ #include <iostream.h> //Para cout y cin

void mostrarArreglo(int valores[], int numeroElementos) { int i; for (i = 0; i < numeroElementos; i++) cout << "valores[" << i << "] = " << valores[i] << endl; }//Fin de mostrarArreglo() void main(void) { int calificaciones[5] = {70, 80, 90, 100, 90}; mostrarArreglo(calificaciones, 5); }//Fin de main()

Ejemplo 18.22
El siguiente programa, ARRPARAM.CPP, pasa tres arreglos diferentes (de diferentes tamaos) a la funcin mostrarValores()

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-25

MIGUEL . TOLEDO MARTNEZ

/* El siguiente programa: ARRPARAM.CPP, pasa tres arreglos diferentes (de diferentes tamaos) a la funcin mostrarValores(). */ #include <iostream.h> //Para cout y cin

void mostrarValores(int valores[], int numeroElementos) { int i; cout << endl << "Nmero de elementos visualizados: " << numeroElementos << endl << endl;

for (i = 0; i < numeroElementos; i++) cout << "valores[" << i << "] = " << valores[i] << endl; }//Fin de mostrarValores() void main(void) { int calificaciones[5] int contador[10] int pequeno[2] = {70, 80, 90, 100, 90}; = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; = {-33, -44};

mostrarValores(calificaciones, 5); mostrarValores(contador, 10); mostrarValores(pequeno, 2); }//Fin de main()

Ejemplo 18.23
El siguiente programa, MINMAX.CPP, determina los valores mximo y mnimo de un arreglo. /* El siguiente programa: MINMAX.CPP, determina los elementos ms grandes y ms pequeos de un arreglo. */ #include <iostream.h> const int MIN = 2; const int MAX = 10; int obtenNumPuntos(int menor, int mayor) { int numPuntos; do { << "Introduzca el nmero de puntos de datos [" << menor << " a " << mayor << "]: "; cin >> numPuntos; } while (numPuntos < menor || numPuntos > mayor); return numPuntos; }//Fin de obtenNumPuntos() cout //Para cout y cin

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-26

MIGUEL . TOLEDO MARTNEZ

int buscaMinimo(int arreglo[], int tamano) { int pequeno = arreglo[0]; for (int i = 1; i < tamano; i++) if (arreglo[i] < pequeno) pequeno = arreglo[i]; return pequeno; }//Fin de buscaMinimo() int buscaMaximo(int arreglo[], int tamano) { int grande = arreglo[0]; for (int i = 1; i < tamano; i++) if (arreglo[i] > grande) grande = arreglo[i]; return grande; }//Fin de buscaMaximo() void main(void) { int arreglo[MAX], numElementos; numElementos = obtenNumPuntos(MIN, MAX); // Pide datos al usuario for (int i = 0; i < numElementos; i++) { cout << "arreglo[" << i << "]: "; cin >> arreglo[i]; }//Fin de for cout << "El valor ms pequeo en el arreglo es " << buscaMinimo(arreglo, numElementos) << endl << "El valor ms grande en el arreglo es " << buscaMaximo(arreglo, numElementos) << endl;

}//Fin de main()

Ejemplo 18.24
Escriba un programa que use un arreglo para almacenar un mximo de 25 calificaciones de exmenes y calcule el promedio. Use una funcin para llenar el arreglo con las calificaciones, una segunda funcin para calcular el promedio y una tercera funcin para mostrar todas las calificaciones junto con el promedio calculado.

Solucin
Comencemos con un verdadero estilo estructurado y desarrollemos las interfaces paras las funciones requeridas. Llamaremos a las tres funciones obtenerCalificaciones(), promedio() y mostrarResultados() La funcin obtenerCalificaciones() deber obtener del usuario los registros de las calificaciones y las colocar en un arreglo. De esta manera, la funcin deber aceptar la estructura del arreglo y regresar el arreglo que contenga las calificaciones de los exmenes. Esto da origen a la siguiente descripcin de la interfaz de la funcin:
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-27

MIGUEL . TOLEDO MARTNEZ

Funcin obtenerCalificaciones():

Obtiene del usuario los registros de los exmenes y los coloca en un arreglo. El nmero de calificaciones y el arreglo de las calificaciones con un tamao mximo de MAX. El nmero de calificaciones y el arreglo que llena el usuario con las calificaciones.

Acepta:

Regresa:

Es necesario que la interfaz de la funcin acepte y regrese la estructura del arreglo. Supongamos que las calificaciones son valores decimales y, por lo tanto, se necesita un arreglo de punto flotante. La funcin prototipo ser: void obtenerCalificaciones(int &numero, float calificaciones[MAX]) A partir de esto, es fcil la escritura de la funcin. Emplearemos un enunciado cin dentro de un ciclo for en el cuerpo de la funcin para llenar el arreglo con las calificaciones. A continuacin la funcin completa: void obtenerCalificaciones(int &numero, float calificaciones[MAX]) { cout << Cuntas calificaciones quiere promediar? ; cin >> numero; cout << Escriba cada calificacin y presione ENTER despus de cada entrada. << endl; for(int i = 0; i < numero; ++i) { cout << Escriba el registro # << i + 1 << : ; cin >> calificaciones[i]; } // Fin del for } // Fin de obtenerCalificaciones Dentro del cuerpo de la funcin se pide al usuario que escriba la cantidad de calificaciones y cada calificacin individual. Las calificaciones se ingresan y se colocan en el arreglo por medio de un enunciado cin dentro de un ciclo for. Observe que los valores escritos por el usuario para numero se emplean para terminar el ciclo for. Tambin observe que numero es un parmetro por referencia. Como resultado, ste regresar al programa llamador para que otras funciones lo utilicen. Despus se escribir una funcin llamada promedio para obtener el promedio de las calificaciones que se encuentran en el arreglo. Esta funcin deber aceptar el arreglo, obtendr las calificaciones y regresar un valor sencillo de punto flotante que es el promedio de las calificaciones. Por lo tanto, la descripcin de la interfaz de la funcin es como sigue: Funcin promedio(): Acepta: Calcula el promedio de las calificaciones. El nmero de las calificaciones que se van a promediar y el arreglo de las calificaciones. Un solo valor que es el promedio de las calificaciones.

Regresa:

Esta vez, el arreglo pasar a la funcin y la funcin regresar un solo valor. De esta manera, la funcin prototipo se convierte en: float promedio(int numero, float calificaciones[MAX]);

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-28

MIGUEL . TOLEDO MARTNEZ

El cuerpo de la funcin simplemente suma todas las calificaciones del arreglo y los divide entre su nmero. A continuacin se ve la funcin completa: float promedio(int numero, float calificaciones[MAX]) { float total = 0.0; for (int i = 0; i < numero; ++i) total +=calificaciones[i]; return total/numero; } // Fin de promedio() Hay dos variables locales de funcin definidas: total e i. total actuar como una variable temporal para acumular la suma de las calificaciones y la variable i es la variable contador del ciclo. Primero, la variable total se inicializa a 0. Despus se usa el ciclo para obtener los elementos del arreglo, uno por uno y adicionarlos a total. Observe que el contador de ciclo (i) acta como el ndice del arreglo dentro del ciclo. De esta manera se extraen los elementos del arreglo, desde el ndice [0] hasta [numero 1], en forma secuencial con cada ciclo de iteracin y se adicionan a total. La ltima calificacin se localiza en el ndice [numero 1]. Una vez que el ciclo calcula la suma total de todas las calificaciones, se usa un enunciado return para regresar el promedio calculado. Por ltimo, la funcin mostrarResultado() mostrar las calificaciones individuales obtenidas del usuario junto con sus promedios. Para hacer esto, el arreglo deber pasar a la funcin para obtener las calificaciones. Aqu est la descripcin de la funcin: Funcin mostrarResultado(): Muestra las calificaciones individuales y su promedio. El nmero de calificaciones para mostrarlas en pantalla y el arreglo de las calificaciones. Nada.

Acepta:

Regresa:

Para mostrar el promedio, slo se llamar a la funcin promedio() dentro de esta funcin como parte de un enunciado cout. La funcin completa entonces se convierte en: void mostrarResultado(int numero, float calificaciones[MAX]) { cout << endl << endl; cout << Muestra calificaciones << endl; cout << --------------------------- << endl; cout.setf(ios::fixed); cout.precision(2); for(int i = 0; i < numero; ++i) cout << calificaciones[i] << endl; cout << \nEl promedio de los registros anteriores es: << promedio(calificaciones) << endl; } // Fin de mostrarResultados() De nuevo se emplea un ciclo for para mostrar las calificaciones individuales. Observe cmo la funcin promedio() se llama al final del enunciado cout para calcular el promedio de las calificaciones.

Ejemplo 18.25
Ahora, reuniendo todo, se obtiene el siguiente programa: ARREGLOS.CPP.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-29

MIGUEL . TOLEDO MARTNEZ

/* El siguiente programa: ARREGLOS.CPP muestra el uso de los arreglos. */ /******************************************************************************* Este programa calcular un promedio de calificaciones desde registros escritos por el usuario en un arreglo. *******************************************************************************/ #include <iostream.h> // Constante global const int MAX = 25; // Para cin y cout

// Nmero mximo de registros.

// Funciones prototipo void obtenerCalificaciones(int &numero, float calificaciones[MAX]); float promedio(int numero, float registros[MAX]); void mostrarResultados(int numero, float calificaciones[MAX]); void main(void) { // Define la variable numero y el arreglo int numero = 0; // Nmero de calificaciones float calificaciones[MAX]; // Definicin del arreglo // LLama a las funciones para obtener las calificaciones y mostrar resultados obtenerCalificaciones(numero, calificaciones); mostrarResultados(numero, calificaciones); } // Fin de main() /******************************************************************************* Esta funcin obtiene los registros del usuario y los coloca en el arreglo calificaciones. *******************************************************************************/ void obtenerCalificaciones(int &numero, float calificaciones[MAX]) { cout << "Cuntas calificaciones quiere promediar?" << endl; cin >> numero; cout << "Escriba cada calificacion y presione ENTER despus de cada entrada" << endl; for(int i = 0; i < numero; ++i) { cout << "Escriba la calificacin #" << (i+1) << ": "; cin >> calificaciones[i]; }// Fin del for } // Fin de obtenerCalificaciones() /******************************************************************************* Esta funcin calcular el promedio de los registros en el arreglo. *******************************************************************************/ float promedio(int numero, float calificaciones[MAX]) { float total = 0.0; for(int i = 0; i < numero; ++i) total += calificaciones[i]; return total/numero; } // Fin de promedio()

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-30

MIGUEL . TOLEDO MARTNEZ

/******************************************************************************* Esta funcin muestra las calificaciones del arreglo y el promedio final. *******************************************************************************/ void mostrarResultados(int numero, float calificaciones[MAX]) { cout << endl << endl; cout << "Muestra calificaciones" << endl; cout << "----------------------" << endl; cout.setf(ios::fixed); cout.precision(2); for(int i = 0; i < numero; ++i) cout << calificaciones[i] << endl; cout << "\nEl promedio de los registros anteriores es: " << promedio(numero,calificaciones) << endl; } // Fin de mostrarResultados() Como puede ver, primero se enuncia una constante global (MAX) Esta ser el nmero mximo de elementos del arreglo. Despus de definir la constante global, se listan las tres funciones prototipo. Ahora, mire la seccin de enunciados de main() Se sorprende de su simplicidad? La funcin main() es relativamente corta, porque todo el trabajo se hace en las otras funciones. Esto es lo fascinante de la programacin estructurada! Todo lo que hace main() es llamar a las otras dos funciones en el orden que se necesitan. Observe que al principio de main() se defina una variable denominada numero para saber el nmero de las calificaciones escritas por el usuario. Esta variable pasar a las funciones y desde stas cuando se necesiten. Despus, el arreglo, de nombre calificaciones[], se define como un arreglo de MAX, o 25 elementos de punto flotante. El nombre del arreglo es calificaciones, por lo tanto se utilizar este identificador cuando se quiera tener acceso al mismo. Despus que se define el arreglo, se llama a la funcin obtenerCalificaciones() seguida por la funcin mostrarResultados() Observe que, en ambos casos, numero y el arreglo calificaciones pasan a la funcin por medio de una lista de argumentos. Primero se llama a la funcin obtenerCalificaciones() para obtener del usuario las calificaciones e insertarlas en el arreglo. Despus se llama a la funcin mostrarResultados() De nuevo el nmero de calificaciones, numero, y el arreglo de calificaciones, calificaciones, pasan a la funcin por medio de una lista de argumentos en la funcin llamadora. Esta funcin muestra los registros de las calificaciones desde el arreglo y llama a la funcin promedio() para calcular el promedio de las calificaciones.

EXAMEN BREVE 37 ORDENAMIENTO DE ARREGLOS El ordenamiento de informacin (es decir, la colocacin de los datos en algn orden particular, por ejemplo, ascendente o descendente) es una de las aplicaciones ms importantes en computacin. Un banco ordena todos los cheques por nmero de cuenta para poder preparar los estados de cuenta al cierre del mes. Las compaas telefnicas ordenan sus listas de cuentas por apellido y luego por nombre, para hacer ms fcil la localizacin de los nmeros telefnicos. Prcticamente todas las organizaciones deben ordenar informacin y, en muchos casos volmenes masivos de datos. El ordenamiento de datos es un problema interesante que ha provocado algunos de los esfuerzos de investigacin ms intensos en las ciencias de la computacin.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-31

MIGUEL . TOLEDO MARTNEZ

Ejemplo 18.26
El siguiente programa, BURBUJA1.CPP, ordena los valores del arreglo de diez elementos arreglo en orden ascendente. La tcnica de la que nos valemos se llama ordenamiento de burbuja u ordenamiento por hundimiento(dependiendo si se ordena en orden descendente o ascendente), pues los valores ms pequeos gradualmente burbujean hacia la parte alta del arreglo como las burbujas de aire que ascienden en el agua, mientras que los valores ms grandes se hunden al fondo del arreglo. La tcnica es pasar varias veces por el arreglo. En cada pasada, se comparan pares sucesivos de elementos. Si uno de los pares est en orden ascendente (o son idnticos los valores), se queda tal cual. Si est en orden descendente, se intercambian sus valores en el arreglo. /* El siguiente programa: BURBUJA1.CPP, ordena los valores de un arreglo en orden ascendente utilizando el mtodo de la burbuja. */ #include <iostream.h> #include <iomanip.h> void main(void) { const int TAMANO_ARREGLO = 10; int arreglo[TAMANO_ARREGLO] = {2, 6, 4, 8, 10, 12, 89, 68, 45, 37}; int i, temporal; cout << "Datos en el orden original\n"; for(i = 0; i < TAMANO_ARREGLO; i++) cout << setw(4) << arreglo[i]; for(int pasada = 0; pasada < TAMANO_ARREGLO - 1; pasada++) for(i = 0; i < TAMANO_ARREGLO - 1; i++) if(arreglo[i] > arreglo[i+1]) { temporal = arreglo[i]; arreglo[i] = arreglo[i+1]; arreglo[i+1] = temporal; }//Fin de if cout << "\nDatos en orden ascendente\n"; for(i = 0; i < TAMANO_ARREGLO; i++) cout << setw(4) << arreglo[i]; cout << endl; }//Fin de main() Primero el programa compara arreglo[0] con arreglo[1], luego arreglo[1] con arreglo[2], luego arreglo[2] con arreglo[3], y as hasta que completa la pasada comparando arreglo[8] con arreglo[9] Aunque hay 10 elementos, slo se efectan nueve comparaciones. Debido a la manera en que se realizan las comparaciones sucesivas, un valor grande puede moverse hacia abajo del arreglo muchas posiciones con una sola pasada, pero un valor pequeo se mover hacia arriba una sola posicin. Durante la primera pasada, se garantiza que el valor mayor se hunda hasta arreglo[9] En la novena pasada, el noveno valor mayor se hunde a arreglo[1] Esto deja en arreglo[0] el valor ms pequeo, por lo que slo se necesitan nueve pasadas para ordenar un arreglo de 10 elementos. //Para cout y cin //Para setw()

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-32

MIGUEL . TOLEDO MARTNEZ

Ejemplo 18.27
El problema anterior puede mejorarse solicitando el nmero de datos a ordenar, llamaremos a este programa, BURBUJA2.CPP. Es importante que observe algunos cambios que hicimos en la funcin clasifBurbuja() /* El siguiente programa: BURBUJA2.CPP, ordena arreglos usando el mtodo de ordenamiento de la burbuja. */ #include <iostream.h> const int MIN = 2; const int MAX = 10; int obtenNumPuntos(int minimo, int maximo) { int numPuntos; do { << "Introduzca el nmero de puntos de datos [" << minimo << " a " << maximo << "]: "; cin >> numPuntos; } while (numPuntos < minimo || numPuntos > maximo); return numPuntos; }//Fin de obtenNumPuntos() void entradaArreglo(int intArr[], int num) { // Pide datos al usuario for (int i = 0; i < num; i++) { cout << "arreglo[" << i << "]: "; cin >> intArr[i]; }//Fin de for }//Fin de entradaArreglo() void mostrarArreglo(int intArr[], int num) { for (int i = 0; i < num; i++) { cout.width(5); cout << intArr[i] << " "; }//Fin de for cout << endl; }//Fin de mostrarArreglo() void clasifBurbuja(int intArr[], int num) { for (int i = 1; i < num; ++i) for (int j = 0; j <= i; ++j) if (intArr[i] < intArr[j]) cout //Para cout y cin

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-33

MIGUEL . TOLEDO MARTNEZ

{ int temp = intArr[i]; intArr[i] = intArr[j]; intArr[j] = temp; }//Fin de for }//Fin de clasifBurbuja() void main(void) { int arr[MAX]; int numElementos; numElementos = obtenNumPuntos(MIN, MAX); entradaArreglo(arr, numElementos); cout << "El arreglo desordenado es:" << endl; mostrarArreglo(arr, numElementos); clasifBurbuja(arr, numElementos); cout << endl << "El arreglo ordenado es:" << endl; mostrarArreglo(arr, numElementos); }//Fin de main()

Ejemplo 18.28
El problema anterior, puede variarse una vez ms, generando valores aleatorios. Llamemos a este problema, BURBUJA3.CPP /* El siguiente programa: BURBUJA3.CPP, utiliza el mtodo de la burbuja para ordenar un arreglo que contiene 30 valores creados en forma aleatoria. */ #include <iostream.h> #include <stdlib.h> //Para cout y cin //Para rand()

void metodoBurbuja(int arreglo[], int tamano) { int temp, i, j; for (i = 0; i < tamano; i++) for (j = 0; j < tamano; j++) if (arreglo[i] < arreglo[j]) { temp = arreglo[i]; arreglo[i] = arreglo[j]; arreglo[j] = temp; }//Fin de if }//Fin de metodoBlurbuja() void main(void) { int valores[30], i; for (i = 0; i < 30; i++) valores[i] = rand() % 100;
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-34

MIGUEL . TOLEDO MARTNEZ

metodoBurbuja(valores, 30); for (i = 0; i < 30; i++) cout << valores[i] << ' '; }//Fin de main()

Ejemplo 18.29
El mtodo de la burbuja, puede mejorarse disminuyendo el nmero de elementos en cada pasada, a este mtodo se le conoce con el nombre de seleccin. El siguiente programa, SELECCIN.CPP, ilustra este mtodo. /* El siguiente programa: SELECCION.CPP, utiliza el mtodo de seleccin para ordenar un arreglo que contiene 30 valores creados en forma aleatoria. */ #include <iostream.h> #include <stdlib.h> //Para cout y cin //Para rand()

void metodoSeleccion(int arreglo[], int tamano) { int temp, actual, j; for (actual = 0; actual < tamano; actual++) for (j = actual + 1; j < tamano; j++) if (arreglo[actual] > arreglo[j]) { temp = arreglo[actual]; arreglo[actual] = arreglo[j]; arreglo[j] = temp; }//Fin de if }//Fin de metodoSeleccion() void main(void) { int valores[30], i; for (i = 0; i < 30; i++) valores[i] = rand() % 100; metodoSeleccion(valores, 30); for (i = 0; i < 30; i++) cout << valores[i] << ' '; }//Fin de main()

Ejemplo 18.30
El siguiente programa: METSHELL.CPP, utiliza el mtodo Shell para ordenar un arreglo que contiene 50 elementos generados aleatoriamente. Estudie el programa y elabore el seudocdigo para dicho mtodo.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-35

MIGUEL . TOLEDO MARTNEZ

/* El siguiente programa: METSHELL.CPP, utiliza el mtodo Shell para ordenar un arreglo que contiene 50 elementos generados aleatoriamente. */ #include <iostream.h> #include <stdlib.h> //Para cout y cin //Para rand()

void ordenarShell(int arreglo[], int tamano) { int temp, espacio, i, banderaCambio; espacio = tamano / 2; do { do { banderaCambio = 0; for (i = 0; i < tamano - espacio; i++) if (arreglo[i] > arreglo[i + espacio]) { temp = arreglo[i]; arreglo[i] = arreglo[i + espacio]; arreglo[i + espacio] = temp; banderaCambio = 1; }//Fin de if } while (banderaCambio); } while (espacio = espacio / 2); }//Fin de ordenarShell() void main(void) { int valores[50], i; for(i = 0; i < 50; i++) valores[i] = rand() % 100; ordenarShell(valores, 50); for (i= 0; i < 50; i++) cout << valores[i] << ' '; }//Fin de main()

Ejemplo 18.31
El siguiente programa: RAPIDO.CPP, utiliza el mtodo de ordenamiento rpido, para ordenar un arreglo que contiene 100 elementos generados en forma aleatoria. Estudie el mtodo y elabore un seudocdigo de su algoritmo.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-36

MIGUEL . TOLEDO MARTNEZ

/* El siguiente programa: RAPIDO.CPP, utiliza el mtodo de clasificacin ordenamiento rpido, para ordenar un arreglo que contiene 100 elementos generados en forma aleatoria. */ #include <iostream.h> #include <stdlib.h> //Para cout y cin //Para rand()

void ordenarRapido(int arreglo[], int primero, int ultimo) { int temp, bajo, alto, separadorLista; bajo = primero; alto = ultimo; separadorLista = arreglo[(primero + ultimo) / 2]; do { while (arreglo[bajo] < separadorLista) bajo++; while (arreglo[alto] > separadorLista) alto--; if (bajo <= alto) { temp = arreglo[bajo]; arreglo[bajo++] = arreglo[alto]; arreglo[alto--] = temp; }//Fin de if } while (bajo <= alto); if (primero < alto) ordenarRapido(arreglo, primero, alto); if (bajo < ultimo) ordenarRapido(arreglo, bajo, ultimo); }//Fin de ordenarRapido() void main(void) { int valores[100], i; for (i = 0; i < 100; i++) valores[i] = rand() % 100; ordenarRapido(valores, 0, 99); for (i = 0; i < 100; i++) cout << valores[i] << ' '; }//Fin de main()

Ejemplo 18.32
El siguiente programa, ESTADSTICA.CPP, muestra un ejemplo en los que se utiliza la computadora para recolectar y analizar los resultados de las encuestas y sondeos de opinin. Utiliza el arreglo respuestas, inicializado con 99 respuestas (representadas por la constante TAMANO_RESPUESTAS de una encuesta.
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-37

MIGUEL . TOLEDO MARTNEZ

Cada una de las respuestas es un nmero del 1 al 9. El programa calcula la media, la mediana y la moda de los 99 valores. /* El siguiente programa: ESTADISTICA.CPP, presenta el tema del anlisis de informacin de una encuesta. Calcula la media, la mediana y la moda de los datos. */ #include <iostream.h> #include <iomanip.h> //Para cout y cin //Para setw(w)

void media(const int [], int); void mediana(int [], int); void moda(int [], int [], int); void burbuja(int [], int); void escribirArreglo(const int[], int); void main(void) { const int TAMANO_RESPUESTAS = 99; int frecuencia[10] = {0}, respuestas[TAMANO_RESPUESTAS] = {6, 7, 8, 9, 8, 7, 8, 9, 8, 9,7, 8, 9, 5, 9, 8, 7, 8, 7, 8, 6, 7, 8, 9, 3, 9, 8, 7, 8, 7, 7, 8, 9, 8, 9, 8, 9, 7, 8, 9, 6, 7, 8, 7, 8, 7, 9, 8, 9, 2, 7, 8, 9, 8, 9, 8, 9, 7, 5, 3, 5, 6, 7, 2, 5, 3, 9, 4, 6, 4, 7, 8, 9, 6, 8, 7, 8, 9, 7, 8, 7, 4, 4, 2, 5, 3, 8, 7, 5, 6, 4, 5, 6, 1, 6, 5, 7, 8, 7}; media(respuestas, TAMANO_RESPUESTAS); mediana(respuestas, TAMANO_RESPUESTAS); moda(frecuencia, respuestas, TAMANO_RESPUESTAS); }//Fin de main() void media(const int contestacion[], int tamanoArreglo) { int total = 0; cout << "********\n Media\n********\n"; for(int j = 0; j < tamanoArreglo; j++) total += contestacion[j]; cout << "La media es el valor promedio de los datos.\n" << "La media es igual al total de todos\n" << "los datos divididos entre el nmero\n" << "de datos (" << tamanoArreglo << "). La media para\nesta corrida es: " << total << " / " << tamanoArreglo << " = " << setprecision(5) << (float) total / tamanoArreglo << "\n\n";

}//Fin de media() void mediana(int contestacion[], int tamano) { cout << "\n********\n Mediana\n********\n" << "El arreglo de respuestas desordenado es: ";

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-38

MIGUEL . TOLEDO MARTNEZ

escribirArreglo(contestacion, tamano); burbuja(contestacion, tamano); cout << "\n\nEl arreglo ordenado es:"; escribirArreglo(contestacion, tamano); << "\n\nLa mediana es el elemento " << tamano /2 << " del\narreglo ordenado de " << tamano << " elementos.\nPara esta corrida la mediana es " << contestacion[tamano /2] << "\n\n"; }//Fin de mediana void moda(int freq[], int contestacion[], int tamano) { int apariciones, masGrande = 0, valorModal = 0; cout << "\n********\n Moda\n********\n"; for(apariciones = 1; apariciones <= 9; apariciones++) freq[apariciones] = 0; for(int j = 0; j < tamano; j++) ++freq[contestacion[j]]; cout << "Respuesta" << setw(11) << "Frecuencia" << setw(19) << "Histograma\n\n" << setw(53) << "1 1 2 2\n" << setw(54) << "5 0 5 0 5\n\n"; cout

for(apariciones = 1; apariciones <= 9; apariciones++) { cout << setw(9) << apariciones << setw(11) << freq[apariciones] << " "; if(freq[apariciones] > masGrande) { masGrande = freq[apariciones]; valorModal = apariciones; }//Fin de if for(int h = 1; h <= freq[apariciones]; h++) cout << '*'; cout << '\n'; }//Fin del for externo cout << "La moda es el valor ms frecuente.\n" << "Para esta corrida la moda es " << valorModal << " que ocurri " << masGrande << " veces." << endl;

}//Fin de moda() void burbuja(int a[], int tamano) { int temporal; for(int pasada = 1; pasada < tamano; pasada++) for(int j = 0; j < tamano - 1; j++) if(a[j] > a[j + 1])

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-39

MIGUEL . TOLEDO MARTNEZ

{ temporal = a[j]; a[j] = a[j + 1]; a[j + 1] = temporal; }//Fin de if }//Fin de burbuja() void escribirArreglo(const int a[], int tamano) { for(int j = 0; j < tamano; j++) { if(j %20 == 0) cout << endl; cout << setw(2) << a[j]; }//Fin de for }//Fin de imprimirArreglo()

BSQUEDA EN ARREGLOS: Bsqueda lineal y bsqueda binaria Con frecuencia el programador trabajar con grandes cantidades de informacin almacenada en arreglos. Podra ser necesario determinar si algn arreglo contiene un valor que sea igual a cierto valor clave. El proceso para encontrar un elemento particular en un arreglo se llama bsqueda. En esta seccin estudiaremos dos tcnicas de bsqueda: la tcnica simple de bsqueda lineal y la tcnica ms eficiente de bsqueda binaria. La bsqueda lineal compara todos los elementos del arreglo con la clave de bsqueda. Debido a que el arreglo no est en ningn orden en particular, existe la misma posibilidad de que el valor est en el primer elemento o en el ltimo. Por lo tanto, para encontrar un valor en el arreglo, en promedio el programa debe comparar la clave de bsqueda con la mitad de los elementos del arreglo. Para determinar que un valor no est en el arreglo, el programa de comparar la clave de bsqueda con todos los elementos de dicho arreglo.
Ejemplo 18.33
El siguiente programa BUSLINEAL.CPP, ilustra el mtodo de bsqueda lineal.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-40

MIGUEL . TOLEDO MARTNEZ

/* El siguiente programa: BUSLINEAL.CPP, ilustra el mtodo de bsqueda lineal en un arreglo. */ #include <iostream.h> //Para cout y cin

int busquedaLineal(const int[], int, int); void main(void) { const int TAMANO_ARREGLO = 100; int a[TAMANO_ARREGLO], claveBusqueda, elemento; for(int x = 0; x < TAMANO_ARREGLO; x++) a[x] = 2 * x; //Crea algunos datos

cout << "Introduzca una clave entera de bsqueda: "; cin >> claveBusqueda; elemento = busquedaLineal(a, claveBusqueda, TAMANO_ARREGLO); if(elemento != -1) cout << "Se encontr el valor en el elemento " << elemento << endl; else cout << "Valor no encontrado" << endl; }//Fin de main() int busquedaLineal(const int arreglo[], int clave, int tamanoArreglo) { for(int n = 0; n < tamanoArreglo; n++) if(arreglo[n] == clave) return n; return -1; }//Fin de busquedaLineal() El mtodo de bsqueda lineal funciona bien con arreglos pequeos y con los no ordenados. Sin embargo, en los arreglos mayores la bsqueda lineal no es eficiente. Si el arreglo est ordenado, se puede emplear la tcnica de bsqueda binaria, que es de alta velocidad. El algoritmo de bsqueda binaria elimina, tras cada comparacin, la mitad de los elementos del arreglo en los que se efecta la bsqueda. Primero localiza el elemento central del arreglo y luego lo compara con la clave de bsqueda. Si son iguales, se ha encontrado dicha clave y se devuelve el ndice de ese elemento. De otro modo, el problema se reduce a buscar en una mitad del arreglo. Si la clave de bsqueda es menor que el elemento central del arreglo, se busca en la primera mitad; de otro modo, se busca en la segunda mitad. Si la clave de bsqueda no est en el elemento central del subarreglo especificado (parte del arreglo original), se repite el algoritmo en un cuarta parte del arreglo original. La bsqueda contina hasta que la clave de bsqueda sea igual al elemento central de un subarreglo o hasta que el subarreglo consista de un elemento, el cual no es igual a la clave de bsqueda (es decir, no se encuentra la clave de bsqueda) En el peor caso, la bsqueda en un arreglo de 1024 elementos slo se llevar 10 comparaciones mediante la bsqueda binaria. La divisin repetida de 1024 entre 2 (dado que tras cada comparacin se puede descartar la mitad del arreglo) nos da los valores 512, 256, 128, 64, 32, 16, 8, 4, 2, y 1. El nmero 1024 (210) se divide entre 2 slo diez veces para llegar al valor 1. La divisin entre 2 es equivalente a una comparacin en el algoritmo de bsqueda binaria. Un arreglo de 1048576 (220) elementos tarda un mximo de 20 comparaciones en encontrar la clave de bsqueda. Un arreglo de mil millones de elementos necesita un mximo de 30 comparaciones. Esta es una mejora enorme en relacin con la bsqueda lineal, que requerira comparar la clave de bsqueda con un promedio de la mitad de los elementos del arreglo. Para un arreglo de mil millones de elementos, esta diferencia es entre un promedio de 500 millones de comparaciones y un mximo de 30!. La cantidad mxima de comparaciones necesarias para la

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-41

MIGUEL . TOLEDO MARTNEZ

bsqueda binaria de cualquier arreglo ordenado puede determinarse encontrando la primera potencia de 2 mayor que el nmero de elementos del arreglo.

Ejemplo 18.34
El siguiente programa, BUSBIN.CPP, presenta la versin iterativa de la funcin busquedaBinaria() La funcin recibe cuatro argumentos: un arreglo de enteros b, un entero claveBusqueda, el ndice bajo del arreglo y el ndice alto del arreglo. Si la clave de bsqueda no es igual al elemento de la mitad de un subarreglo, se ajusta el ndice bajo o alto para poder hacer la bsqueda en un subarreglo ms pequeo. Si la clave de bsqueda es menor que el elemento central, el ndice alto se establece a mitad 1 y se contina la bsqueda en los elementos de bajo a mitad 1. Si la clave de bsqueda es mayor que el elemento central, el ndice bajo se establece a mitad + 1 y se contina la bsqueda en los elementos de mitad + 1 a alto. El programa emplea un arreglo de 15 elementos. La primera potencia de 2 mayor que la cantidad de elementos de este arreglo es 16 (24), por lo que se necesitan un mximo de 4 comparaciones para encontrar la clave de bsqueda. La funcin imprimirEncabezado() enva a la salida los ndices del arreglo y la funcin imprimirFila() enva a la salida cada subarreglo generado durante el proceso de bsqueda binaria. El elemento central de cada subarreglo se marca con un asterisco (*), para indicar el elemento con el que se compara la clave de bsqueda. /* El siguiente programa: BUSBIN.CPP, ilustra el uso de la bsqueda binaria en un arreglo. */ #include <iostream.h> #include <iomanip.h> //Para cout y cin //Para setw()

int busquedaBinaria(int[], int, int, int, int); void imprimirEncabezado(int); void imprimirFila(int[], int, int, int, int); void main(void) { const int TAMANO_ARREGLO = 15; int a[TAMANO_ARREGLO], clave, resultado; for(int i = 0; i < TAMANO_ARREGLO; i++) a[i] = 2 * i; //Crea los elementos del arreglo cout << "Introduzca un nmero entre 0 y 28: "; cin >> clave; imprimirEncabezado(TAMANO_ARREGLO); resultado = busquedaBinaria(a, clave, 0, TAMANO_ARREGLO - 1, TAMANO_ARREGLO); if(resultado != -1) cout << '\n' << clave << " encontrado en el elemento del arreglo nmero " << resultado << endl; else cout << '\n' << clave << " no encontrado" << endl; }//Fin de main() //Busqueda binaria int busquedaBinaria(int b[], int claveBusqueda, int bajo, int alto, int tamano) { int mitad; while(bajo <= alto)

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-42

MIGUEL . TOLEDO MARTNEZ

{ mitad = (bajo + alto) / 2; imprimirFila(b, bajo, mitad, alto, tamano); if(claveBusqueda == b[mitad]) //coincidencia return mitad; else if(claveBusqueda < b[mitad]) alto = mitad - 1; //Busca en la parte baja del arreglo else bajo = mitad + 1; //Busca en la parte alta del arreglo }//Fin de while return -1; }//Fin de busquedaBinaria() //No se encontr claveBusqueda

//Imprime el encabezado para la salida void imprimirEncabezado(int tamano) { cout << "\nIndices:\n"; for(int i = 0; i < tamano; i++) cout << setw(3) << i << ' '; cout << '\n'; for(int i = 1; i <= 4 * tamano; i++) cout << '-'; cout << endl; }//Fin de imprimirEncabezado() //Imprime una fila de la salida, indicando la parte del arreglo que se est procesando. void imprimirFila(int b[], int bajo, int mit, int alto, int tamano) { for(int i = 0; i < tamano; i++) if(i < bajo || i > alto) cout << " "; else if(i == mit) //Marca el valor central cout << setw(3) << b[i] << '*'; else cout << setw(3) << b[i] << ' '; cout << endl; }//Fin de imprimirFila()

Ejemplo 18.35
Una solucin ligeramente diferente al mismo problema es el siguiente programa, BINARIO.CPP, el cual utiliza una bsqueda binaria para localizar valores en el arreglo llamado contador, que contiene los valores del 1 a 100. La funcin busquedaBinaria() imprime mensajes que describen el proceso.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-43

MIGUEL . TOLEDO MARTNEZ

/* El siguiente programa: BINARIO.CPP, utiliza una bsqueda binaria para localizar valores en el arreglo llamado contador, el cual contiene los valores de 1 a 100. La funcin busquedaBinaria imprime mensajes que describen el proceso. */ #include <iostream.h> //Para cout y cin

int busquedaBinaria(int arreglo[], int valor, int tamano) { int encontrado = 0; int alto = tamano, bajo = 0, enmedio; enmedio = (alto + bajo) / 2; cout << endl << endl << "Buscando el nmero: " << valor << endl; while ((! encontrado) && (alto >= bajo)) { cout << "Bajo: " << bajo << ' ' << "Enmedio: " << enmedio << ' ' << "Alto: " << alto << endl; if (valor == arreglo[enmedio]) encontrado = 1; else if (valor < arreglo[enmedio]) alto = enmedio - 1; else bajo = enmedio + 1; enmedio = (alto + bajo) / 2; }//Fin de while return((encontrado) ? enmedio: -1); }//Fin de busquedaBinaria() void main(void) { int arreglo[100], i; for (i = 0; i < 100; i++) arreglo[i] = i; cout cout cout cout }//Fin de main() << "Resultado de la bsqueda: " << busquedaBinaria(arreglo, 33, 100) << endl; << "Resultado de la bsqueda: " << busquedaBinaria(arreglo, 75, 100) << endl; << "Resultado de la bsqueda: " << busquedaBinaria(arreglo, 1, 100) << endl; << "Resultado de la bsqueda: " << busquedaBinaria(arreglo, 1001, 100) << endl;

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-44

MIGUEL . TOLEDO MARTNEZ

SOLUCIN DE PROBLEMAS EN ACCIN: Bsqueda en un arreglo con iteracin


(Bsqueda secuencial)
Diversas aplicaciones requieren de un programa para buscar un determinado elemento en un arreglo. Para realizar esta tarea se usan dos algoritmos comunes que son bsqueda secuencial o serial y bsqueda binaria. Por lo comn, la bsqueda secuencial se utiliza para arreglos no ordenados y la bsqueda binaria en arreglos ordenados. En el siguiente problema veremos la bsqueda secuencial; en un problema posterior veremos la bsqueda binaria.

PROBLEMA
Desarrolle una funcin que busque, en forma secuencial, en un arreglo de enteros, el valor de un elemento dado y que regrese el ndice del elemento si ste se encuentra en el arreglo.

DEFINICIN DEL PROBLEMA


Debido a que se trata de una funcin, la definicin del problema se enfocar a la interfaz de la funcin. Por consiguiente, se debe considerar que la funcin aceptar y regresar algo. Llamaremos a la funcin busquedaSec() A partir del enunciado del problema, la funcin deber buscar en un arreglo de enteros un valor de un elemento determinado. De esta manera, la funcin necesita dos cosas para realizar este trabajo: (1) el arreglo y (2) el elemento que se va a buscar. Estos sern los parmetros de la funcin, debern ser de valor o de referencia? Bueno, la funcin no cambiar ni al arreglo ni al elemento a buscar, es correcto? Por lo tanto, los parmetros sern por valor. Despus, necesitamos determinar que va a regresar la funcin al programa llamador. A partir del enunciado del problema, se observa que la funcin necesita regresar el ndice del elemento buscado, si se encuentra en el arreglo. En C++ todos los ndices de los arreglos son enteros, por lo tanto la funcin regresar un valor entero. Pero, qu pasa si el elemento que se busca no se encuentra en el arreglo? Se regresar algn valor entero que aclare esta situacin. Dado que, en C++ los ndices de los arreglos se encuentran en un rango de 0 a algn entero positivo finito, si el elemento no se encuentra en el arreglo, regresar el entero -1. De esta manera usaremos 1 para indicar la condicin no encontrado, porque en C++ ningn ndice de arreglo tiene este valor. La descripcin de la interfaz de la funcin ser: Funcin busquedaSec(): Busca en un arreglo entero un valor de elemento dado. Un arreglo de enteros y el elemento que se busca. El ndice del arreglo del elemento, si se encuentra, o el valor 1 si no se encuentra el elemento.

Acepta: Regresa:

La descripcin de interfaz de la funcin anterior proporciona toda la informacin necesaria para escribir la interfaz de la funcin, como sigue: int busquedaSec(int arreglo[MAX], int elemento) La interfaz indica que la funcin aceptar dos cosas: (1) un arreglo de elementos enteros MAX y (2) un valor entero, llamado elemento, que ser el valor que se busca. La siguiente tarea es desarrollar el algoritmo de bsqueda secuencial.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-45

MIGUEL . TOLEDO MARTNEZ

PLANEACIN DE LA SOLUCIN
Qu quiere decir exactamente bsqueda secuencial? Rastreo en el arreglo en forma secuencial, de un elemento al siguiente, empezando en la primera posicin del arreglo y detenindose al encontrar el elemento o al llegar al final del arreglo. De esta manera, el algoritmo deber verificar el elemento almacenado en la primera posicin del arreglo, despus en la segunda posicin del arreglo, enseguida en la tercera y as sucesivamente, hasta que encuentre el elemento o hasta que se agoten los elementos del arreglo. Desde luego, sta es una tarea repetitiva de verificacin de un elemento en el arreglo, luego moverse al siguiente elemento y verificar otra vez y as sucesivamente. Considere el siguiente algoritmo que emplea un ciclo while para realizar la operacin de verificacin repetitiva: Algoritmo busquedaSec() busquedaSec() INICIO encuentra = falso. indice = primer ndice del arreglo. while(elemento no se Encuentra) AND (Indice <= ltimo ndice del arreglo) Inicio si (arreglo[indice] == elemento) entonces encuentra = verdadero. sino incremente indice. Fin. si(encuentra == verdadero) entonces regresar indice sino regresar 1 FIN. Aqu, la idea es emplear una variable booleana, llamada encuentra, para indicar si el elemento se encontr durante la bsqueda. La variable encuentra se inicializa a falso y una variable de nombre indice se inicializa para el ndice del primer elemento en el arreglo. Observe la verificacin del ciclo while. Debido al uso de un operador AND, el ciclo continuar en tanto no se encuentre el elemento y el valor de indice sea menor o igual al ltimo valor de ndice del arreglo. Otra forma de decir esto es que el ciclo se repetir hasta que se encuentre el elemento o el valor de indice exceda el ltimo valor del ndice del arreglo. Dentro del ciclo, el valor almacenado en la localidad [indice] se compara al valor de elemento, recibido por medio de la funcin. Si los dos valores son iguales, la variable booleana encuentra se establece a verdadero. De otra manera, el valor de indice se incrementa para moverse a la siguiente posicin del arreglo. Si el elemento fue encontrado o no, el ciclo termina. Si se trata del primer caso, el valor de encuentra ser verdadero y el valor de indice ser la posicin del arreglo, o ndice, en el cual se encontr el elemento. De esta manera si encuentra es verdadero, el valor indice regresa al programa llamador. Si el elemento no fue encontrado, el valor de encuentra se mantendr en falso desde su estado inicial y se regresar el valor 1 al programa llamador.

CODIFICACIN DEL PROGRAMA


A continuacin se escribe el cdigo C++ que refleja el algoritmo anterior:
int

busquedaSec(int a[MAX], int elemento) { enum boolean {Falso, Verdadero}; boolean encuentra = Falso; int i = 0;

// Define Falso = 0 y Verdadero = 1 // Inicializa encuentra a Falso // Variable ndice del arreglo 18-46

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

MIGUEL . TOLEDO MARTNEZ

// Busca en el arreglo hasta encontrar o alcanzar el final del arreglo while((!encuentra) && (i < MAX)) { if (a[i] == elemento) // Verifica el elemento del arreglo encuentra = Verdadero; // Si es igual, establece else // encuentra a Verdadero ++i; } // Fin del while // Si se encuentra el elemento, regresa la posicin del elemento en el arreglo // Si no regresa 1 if(encuentra) return i; else return 1; } // Fin de busquedaSec() No debe haber sorpresas en este cdigo. En la parte superior de la funcin, ver el encabezado que es idntico a la interfaz de la funcin desarrollada anteriormente. Despus ver una clase de datos enumerada creada para definir Falso y Verdadero. Recuerde que los valores predeterminados para elementos de datos enumerados son enteros, empezando con 0. De esta manera, Falso se define con el valor 0 y Verdadero se define con el de 1. Esto permite la utilizacin de los identificadores Falso y Verdadero dentro del programa para representar los valores enteros 0 y 1 respectivamente. Adems, las verificaciones booleanas se pueden hacer contra estos valores, porque C++ interpreta un 0 como un Falso lgico y 1 como un Verdadero lgico. La variable encuentra se define como un objeto de clases de datos booleanos enumerados y se establece a Falso. Utilizaremos la variable i como variable ndice del arreglo. Esta variable se define como un entero y establece a 0 el primer ndice del arreglo. Recuerde que los arreglos en C++ siempre empiezan con el ndice 0. El ciclo while emplea el operador AND (&&) para verificar los valores de encuentra e i. El ciclo se repetir hasta que se encuentre el elemento (encuentra) y el valor de i sea menor que el tamao MAX del arreglo. Recuerde que cuando el tamao del arreglo es MAX, el ltimo ndice del arreglo es MAX 1. Por lo tanto, cuando i excede el ndice mximo del arreglo, MAX 1, el ciclo se rompe. Cuando el ciclo se rompe, el valor de encuentra se verifica. Si encuentra es Verdadero, se regresa el valor de i; si encuentra es Falso, el valor 1 se regresa para indicar que el elemento no se encontr en el arreglo.

SOLUCIN DE PROBLEMAS EN ACCIN: Como ordenar un arreglo con iteracin


(Ordenacin por insercin)
Ordenar un arreglo significa colocar los elementos del arreglo en orden ascendente o descendente desde el principio al final del arreglo. Hay muchos algoritmos comunes utilizados para ordenacin. Hay clasificacin por insercin, clasificacin por burbuja, clasificacin por seleccin, clasificacin rpida, clasificacin combinada y clasificacin apilada, slo por mencionar algunas. En un curso de estructura de datos, es muy probable que aprenda y analice todos estos algoritmos de ordenacin. En este problema se desarrollar el algoritmo de clasificacin por insercin y se codificar como una funcin en C++.

PROBLEMA
Desarrolle una funcin que se pueda llamar para ordenar un arreglo de caracteres en orden ascendente utilizando el algoritmo clasificacin por insercin.

DEFINICIN DEL PROBLEMA


De nuevo, codificaremos el algoritmo como una funcin C++, as la definicin del problema se enfocar en la interfaz de la funcin, guindonos a la funcin prototipo. Llamaremos a la funcin clasifPorInser() Piense que necesita clasifPorInser() para hacer un trabajo. Bueno, deber recibir un arreglo de caracteres no clasificados y regresar el mismo arreglo como un arreglo clasificado, correcto? Necesita algo ms? No, la funcin no requiere datos adicionales, porque lo nico que se opera es el arreglo mismo.
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-47

MIGUEL . TOLEDO MARTNEZ

Qu hay de los valores de regreso? Necesita regresar la funcin un valor sencillo o una serie de valores? La funcin no necesita regresar ningn valor sencillo, deber regresar el arreglo ordenado. Por lo tanto, la clase de valor regresado ser void y el arreglo ser un parmetro de referencia, correcto? Recuerde que cuando se pasan los arreglos a las funciones C++, siempre son tratados como parmetros de referencia porque el nombre del arreglo representa una direccin en memoria. Por lo tanto, aqu est la descripcin de la interfaz de la funcin clasifPorInser(): Funcin clasifPorInser(): Acepta: Regresa: Clasifica un arreglo de caracteres en orden ascendente. Un arreglo de caracteres sin clasificar. Un arreglo de caracteres clasificados.

De la descripcin anterior, la interfaz de la funcin se codifica fcilmente como: void clasifPorInser(char arreglo[MAX]) La interfaz dice que clasifPorInser() recibir un arreglo de caracteres de tamao MAX. El tipo regresado es void, porque no se regresa ningn valor sencillo. Sin embargo, debido a que el arreglo completo se pasa a la funcin, cualquier operacin de clasificacin sobre el arreglo dentro de la funcin se reflejar en el programa llamador.

PLANEACIN DE LA SOLUCIN
Antes de establecer el algoritmo, vamos a ver cmo trabaja la clasificacin por insercin. Vea la figura 18.3. Suponga que vamos a clasificar un arreglo de 5 caracteres en orden ascendente. Antes de entrar en detalle, vea la figura de arriba abajo y de izquierda a derecha. El arreglo sin ordenar se muestra en la parte superior de la figura 18.3 y el arreglo ordenado se muestra en la parte inferior de la figura 18.3. Observe que el sombreado se emplea en la figura para mostrar el proceso de clasificacin de arriba a abajo. Conforme procedemos desde el arreglo sin clasificar en la parte superior, el sombreado se incrementa, mostrando la porcin del arreglo que est clasificado, hasta que el arreglo completo est sombreado en la parte inferior de la figura 18.3. La secuencia descendente muestra que se harn cuatro pasos a lo largo del arreglo para obtener al arreglo clasificado mostrado en la parte inferior de la figura. Con cada paso, un elemento se coloca dentro de su posicin clasificada relativa a los elementos que se encuentran antes en el arreglo. El primer paso empieza con el primer elemento E, clasificado como se indica por medio del sombreado. Se considera que el carcter individual E se clasifica por s mismo, porque no tiene ningn elemento antes que l. De esta manera, la tarea en este primer paso es clasificar el segundo elemento, D, relativo al carcter E que lo precede. El segundo paso empieza con los caracteres clasificados D y E, como se indica por medio del sombreado. La tarea en este paso es clasificar el tercer carcter, C, en relacin con estos dos caracteres. En el tercer paso se empieza con los caracteres clasificados C, D y E, y la tarea es clasificar el carcter B en relacin con estos caracteres. Recuerde, en cada paso, la tarea es clasificar el primer carcter de la parte no clasificada del arreglo en relacin con los caracteres que le preceden. El proceso contina hasta que se clasifican todos los caracteres, como se muestra en la parte inferior de la figura 18.3. En cada paso se repite prcticamente lo que se hizo en el paso anterior. Como resultado, es posible identificar un proceso de repeticiones paso a paso, de arriba hacia debajo de la figura 18.3. Esta repeticin dar origen a una estructura de ciclo en nuestro algoritmo. Ahora, la pregunta es: qu sucede durante cada paso para clasificar finalmente al arreglo completo? Bueno, durante cada paso, el primer elemento en la parte no clasificada (sin sombrear) del arreglo se examina comparndolo a la secuencia clasificada de los elementos que le preceden. Si este elemento es menor que el anterior, estos dos elementos se intercambian y de nuevo el elemento anterior se compara con su predecesor, si es menor se intercambian y as sucesivamente.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-48

MIGUEL . TOLEDO MARTNEZ

E D C B A
[0] [1] [2] [3] [4]

Paso 1

E D C B A
[0] [1] [2] [3] [4]

D E C B A
[0] [1] [2] [3] [4]

Paso 2

D E C B A
[0] [1] [2] [3] [4]

D C E B A
[0] [1] [2] [3] [4]

C D E B A
[0] [1] [2] [3] [4]

CICLO EXTERNO

Paso 3

C D E B A
[0] [1] [2] [3] [4]

C D B E A
[0] [1] [2] [3] [4]

C B D E A
[0] [1] [2] [3] [4]

B C D E A
[0] [1] [2] [3] [4]

Paso 4

B C D E A
[0] [1] [2] [3] [4]

B C D A E
[0] [1] [2] [3] [4]

B C A D E
[0] [1] [2] [3] [4]

B A C D E
[0] [1] [2] [3] [4]

A B C D E
[0] [1] [2] [3] [4]

A B C D E
[0] [1] [2] [3] [4]

ARREGLO CLASIFICADO CICLO INTERNO Figura 18.3. La clasificacin por insercin es un proceso de repeticiones anidadas Este proceso se repite hasta que sucede una de dos cosas: (1) el elemento es mayor o igual a su predecesor, o (2) el elemento est en la primera posicin del arreglo (ndice [0]) En otras palabras, el proceso de comparacin o intercambio de izquierda a derecha que se muestra en la figura 18.3 termina cuando el elemento examinado se ha insertado en su posicin adecuada en la parte clasificada del arreglo. Este proceso de comparacin o intercambio que representa la repeticin de izquierda a derecha en la figura 18.3 dar como resultado otra estructura de ciclo en nuestro algoritmo. Por lo tanto, es posible identificar dos procesos repetitivos en la figura 18.3, uno de arriba hacia abajo y otro de izquierda a derecha. Cmo se relacionan los dos procesos repetitivos? Bien, parece que por cada paso de arriba abajo a travs del arreglo, el proceso de comparacin o intercambio se ejecuta de izquierda a derecha. De esta manera, el proceso de izquierda a derecha deber anidarse dentro del proceso de arriba abajo. Esto se reflejar en nuestro algoritmo por medio de dos estructuras de ciclo: una controla el proceso de comparacin o intercambio de izquierda a derecha que deber anidarse dentro del segundo ciclo que controla el proceso de arriba abajo. Observe de nuevo la figura 18.3 para asegurarse que ve esta repeticin anidada. Ahora que tiene una idea de cmo funciona la ordenacin por insercin, analice el algoritmo formal:
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-49

MIGUEL . TOLEDO MARTNEZ

Algoritmo clasifPorInser() clasifPorInser() INICIO Establece i = segundo ndice del arreglo. mientras(i <= ltimo ndice del arreglo) Inicio Establece j = i. mientras(j > primer ndice del arreglo) AND (A[j] < A[j 1])) Inicio Intercambia A[j] y A[j 1]. Decrementa j. Fin. Incrementa i. Fin. FIN. La variable i controla el ciclo externo y j controla el ciclo interno. Observe que i empieza en el segundo ndice del arreglo. Por qu no en el primer ndice del arreglo? Porque el primer elemento en el arreglo se clasifica siempre relativo a cualquier elemento precedente, correcto? Por lo tanto, el primer paso comienza con el segundo elemento del arreglo. El primer enunciado en el ciclo externo establece a j = i. De esta manera, i y j localizan el primer elemento en la parte no clasificada del arreglo al principio de cada paso. Ahora, el ciclo interno intercambiar al elemento localizado por j, el cual es A[j], con su elemento predecesor, el cual es A[j 1], siempre y cuando j sea mayor que el primer ndice del arreglo y el elemento A[j] sea menor que el elemento A[j 1] Una vez que se hace el intercambio, se decrementa j. Esto obliga a j a seguir siendo el elemento insertado dentro de la parte del arreglo ordenado. El intercambio contina hasta que no hay ningn elemento que preceda al elemento A[j] que sea menor que el A[j] Una vez que se rompe el ciclo interno, el elemento A[j] se inserta en su posicin correcta con relacin con los elementos que le preceden. Despus, se hace otro paso incrementando la variable externa para el control del ciclo i, estableciendo j a i, y ejecutando de nuevo el ciclo interno. Este proceso de ciclo anidado contina hasta que i se incrementa ms all de la ltima posicin del arreglo. Estudie el algoritmo anterior y comprelo con la figura 18.3 hasta que est seguro que comprende clasifPorInser() A continuacin el cdigo en C++.

CODIFICACIN DEL PROBLEMA


Hemos desarrollado la interfaz de la funcin clasifPorInser() En C++, el algoritmo se codifica fcilmente como una funcin semejante a sta: // Funcin de intercambio() void interCambio(char &x, char &y) { char temp; temp = x; x = y; y = temp; } // Fin de interCambio() // Funcin clasificacin por insercin void clasifPorInser(char A[MAX]) { int i; int j; i = 1; while(i < MAX)
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

// Crea una variable temporal

// Variable que controla el ciclo exterior // Variable que controla el ciclo interior // Establece i al ndice del segundo elemento

18-50

MIGUEL . TOLEDO MARTNEZ

{ j = i; // Localiza el primer elemento del arreglo no clasificado

while((j > 0) && (A[j] < A[j 1])) { interCambio(A[j], A[j 1]); --j; // Hace que j siga al elemento insertado } // Final del while interno ++i; // Hace que i localice el primer elemento de la parte no clasificada. } // Fin del while externo } // Fin de clasifPorInser() En este caso se pueden ver dos funciones codificadas en C++. Recuerde que el algoritmo clasifPorInser() requiere una operacin de intercambio. Para llevar a cabo esta tarea se ha codificado una funcin llamada interCambio() Observe que esta funcin tiene dos parmetros de referencia que son caracteres. De esta manera, la funcin recibe dos caracteres que se intercambian utilizando la variable local temporal (temp) dentro de la funcin. Los caracteres de intercambio se envan de regreso al programa llamador por medio de los parmetros de referencia. Desde luego, el programa llamador ser la funcin clasifPorInser() El cdigo de clasifPorInser() debe ser directo a partir del algoritmo que se analiz. Estudie el cdigo y comprelo con el algoritmo. Encontrar que son idnticos desde un punto de vista lgico y estructural. Debe notar cmo se llama a la funcin intercambio() dentro de clasifPorInser() Los elementos del arreglo A[j] y A[j 1] se pasan a la funcin. Estos elementos son caracteres sencillos, correcto? Por lo tanto, la funcin recibe dos caracteres y los intercambia. Los caracteres respectivos en el arreglo reflejan la operacin de intercambio, porque intercambio() emplea parmetros de referencia.

SOLUCIN DE PROBLEMAS EN ACCIN: Bsqueda en un arreglo con recursin


(Bsqueda binaria)
En este problema desarrollaremos otro popular algoritmo de bsqueda, llamado bsqueda binaria. El algoritmo de bsqueda binaria que desarrollaremos emplear recursividad, aunque tambin se puede hacer utilizando iteracin. Una de las principales diferencias entre bsqueda binaria y bsqueda secuencial es que la primera requiere que el arreglo se ordene antes de la bsqueda, mientras que la segunda no tiene este requerimiento. Sin embargo, si va a empezar con un arreglo ordenado, la bsqueda binaria es mucho ms rpida que la secuencial, especialmente para arreglos grandes. Por ejemplo, si fuera a aplicar una bsqueda secuencia a un arreglo de 1000 enteros, el algoritmo de bsqueda secuencial har un promedio de 500 comparaciones para encontrar el elemento deseado. Peor an, si el elemento deseado est en la ltima posicin del arreglo, la bsqueda secuencial har mil comparaciones para encontrar el elemento. Por otra parte, la bsqueda binaria requerir un mximo de 10 comparaciones para encontrar el elemento, an si est en la ltima posicin del arreglo! Desde luego, se debe pagar un precio por esta mayor eficiencia. El precio que se paga es un algoritmo ms complejo. Por lo tanto, cuando busque en un arreglo ordenado, la ventaja de la bsqueda secuencial es simplicidad, mientras que la ventaja de la bsqueda binaria es eficiencia.

PROBLEMA
Desarrolle una funcin en C++ que se pueda llamar para buscar en un arreglo ordenado de enteros un elemento con determinado valor y que regrese el ndice del elemento si se encuentra en el arreglo. Utilice una bsqueda binaria recursiva para realizar esta tarea. Se desarrollar una funcin en C++, as la definicin del problema se enfocar de nuevo a la interfaz de la funcin. Sin embargo, antes de considerar la interfaz de la funcin, veamos cmo funciona una bsqueda binaria recursiva, porque el algoritmo de bsqueda dictar los parmetros de la funcin. Por lo tanto, primero trataremos el algoritmo y despus desarrollaremos la interfaz de la funcin.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-51

MIGUEL . TOLEDO MARTNEZ

PLANEACIN DE LA SOLUCIN
La bsqueda binaria representa una operacin recursiva natural. Recuerde que la idea detrs de la recursividad es dividir un problema en subproblemas. Dividir un problema en subproblemas ms simples de exactamente el mismo tipo hasta que ocurra una condicin primitiva. Esto no es lo mismo que el diseo de software descendente, que divide los problemas en subproblemas ms simples. La diferencia con la recursividad es que los subproblemas son exactamente del mismo tipo de problema que el problema original. Por ejemplo, suponga que est buscando un nombre en un directorio. Imagine que empieza al principio del directorio y ve cada nombre hasta que encuentra el correcto. Esto es exactamente lo que hace la bsqueda secuencial. No sera ms rpido, en promedio, abrir el directorio a la mitad? Despus, determinar qu mitad del directorio contiene el nombre que est buscando, dividir esta seccin del directorio a la mitad y as sucesivamente, hasta que obtiene la pgina en la cual aparece el nombre deseado. Aqu est un algoritmo que describe la bsqueda en el directorio como se describi. UN ALGORITMO DE BSQUEDA RECURSIVA EN UN DIRECTORIO buscaTel() INICIO si(el directorio telefnico slo tiene una pgina) entonces Busca el nombre en la pgina. sino Abre el libro a la mitad. si(el nombre est en la primera mitad) entonces buscaTel(primera mitad del directorio para el nombre) sino buscaTel(segunda mitad del directorio para el nombre) FIN. Observa cmo esta bsqueda es recursiva? Se mantiene realizando las mismas operaciones bsicas hasta que llega a la pgina que contiene el nombre que est buscando. En otras palabras, la funcin buscaTel() se mantiene llamndose a s misma en el enunciado anidado si/sino hasta que se encuentra la pgina correcta. La razn por la que se llama al proceso de bsqueda binaria es que deber dividir el directorio entre 2 (bi) cada vez que se llama a s mismo el algoritmo. Ahora, vamos a ver cmo se puede aplicar este proceso a la bsqueda en un arreglo de enteros. Se llamar a la funcin de bsqueda binaria recursiva busquedaBin() y se desarrollar el algoritmo en varios pasos. Aqu esta el primer nivel del algoritmo. Algoritmo busquedaBin(): Primer nivel busquedaBin() INICIO si(el arreglo tiene slo un elemento) entonces Determine si este elemento es el elemento buscado. sino Encuentre el punto medio del arreglo. si(el elemento est en la primera mitad) entonces busquedaBin(primera mitad) sino busquedaBin(segunda mitad) FIN. Observe cmo este algoritmo es casi idntico al algoritmo buscaTel() Aqu el proceso de bsqueda se contina hasta que el arreglo se reduce a un elemento que se verifica contra el elemento que se est buscando. Observa cmo la bsqueda se mantiene llamndose a s misma hasta que ocurre la condicin primitiva? Aunque este algoritmo proporciona una idea general de bsqueda binaria, se necesita mayor detalle para codificar el algoritmo. Para hacerlo, debemos preguntarnos que datos necesita busquedaBin() para realizar esta tarea. Bueno, al igual que la bsqueda secuencial, sta necesita un arreglo en dnde buscar y el elemento que se va a buscar correcto? Sin embargo, la bsqueda secuencial trata con
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-52

MIGUEL . TOLEDO MARTNEZ

un tamao de arreglo dado, mientras que la bsqueda binaria necesita tratar con arreglos de tamaos diferentes conforme sigue dividiendo al arreglo original a la mitad. No solamente son estos arreglos de diferente tamao, sino el primero y el ltimo ndices de cada mitad son diferentes. Como resultado, debemos proporcionar a busquedaBin() los lmites del arreglo que est tratando en cualquier momento dado. Esto se puede hacer pasando el primero y ltimo ndices del arreglo dado a la funcin. Llamemos a estos ndices primero y ultimo. Estamos listos para escribir la descripcin de la interfaz de la funcin: Funcin busquedaBin(): Busca en un arreglo de enteros ordenado un valor determinado. Un arreglo de enteros, un elemento de bsqueda, el primero y el ltimo ndices del arreglo en el cual se busca.

Acepta:

Regresa:

El ndice del elemento, si se encuentra, o el valor -1 si el elemento no se encuentra. Esta descripcin da suficiente informacin para escribir la interfaz de la funcin C++, como sigue: int busquedaBin(int A[], int elemento, int primero, int ultimo)

Aqu, busquedaBin() regresar un valor entero que representa el ndice del elemento que se busca. De nuevo, ver que regresar el valor -1 si el elemento no se encuentra en el arreglo. La funcin recibe el arreglo de enteros que se busca (A[]), el elemento que se busca (elemento), el primer ndice del arreglo (primero) y el ltimo ndice del arreglo (ultimo) Observe que ningn tamao se proporciona para el arreglo en que se busca porque la funcin buscar en forma recursiva en arreglos de diferentes tamaos. El siguiente problema es determinar qu valor de primero y ultimo se utilizarn para cualquier arreglo durante la bsqueda. Bueno, recuerde que se deber dividir cualquier arreglo dado a la mitad para producir dos nuevos arreglos cada vez que se hace una llamada recursiva busquedaBin() Dado cualquier arreglo donde el primer ndice es primero y el ltimo ndice es ultimo, se puede determinar el ndice medio, como sigue: mitad = (primero + ultimo) / 2 Con este clculo, la primera mitad del arreglo empieza en primero y finaliza en mitad - 1, y la segunda mitad del arreglo empieza en mitad + 1 y finaliza en ultimo. Esta idea se muestra en la figura 18.4. Pero, observe que ninguna mitad del arreglo contiene el elemento medio. Por me- dio de la utilizacin de esta tcnica, las dos mitades no hacen un todo, correcto? Por lo tanto, antes que se haga la divisin, suponga que verificamos el elemento medio para ver si es el elemento que se est buscando. La siguiente verificacin realiza el trabajo. si (A[mitad] == elemento) entonces regresar mitad. Si esta verificacin es verdadera antes de la divisin, se habr encontrado el elemento que se est buscando y es posible terminar las llamadas recursivas. De otra manera, el elemento almacenado en A[mitad] no es el elemento que se est buscando, y esta posicin del arreglo se puede ignorar durante el resto de la bsqueda. Si ste es el caso, se dividir el arreglo y continuar el proceso recursivo. Sin embargo, se tiene que adicionar una segunda condicin primitiva para el algoritmo recursivo. Aqu estn las dos condiciones primitivas que se han hecho: 1. 2. El arreglo que se busca tiene slo un elemento. A [mitad] == elemento.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-53

MIGUEL . TOLEDO MARTNEZ

mitad = (primero + ultimo) / 2

[primero]

[ultimo]

[primero]

[mitad 1]

[mitad + 1]

[ultimo]

Figura 18.4. La bsqueda binaria recursiva requiere que un arreglo sea dividido en mitades con cada llamada recursiva.

Cualquiera de estas condiciones primitivas har que termine la llamada recursiva. Ahora, vamos a considerar la primera condicin primitiva ms de cerca. Cmo saber si el arreglo que se busca tiene solamente un elemento? Bueno, conforme continan las llamadas recursivas sin encontrar el elemento, finalmente el arreglo se reducir a un elemento sencillo. Si ste es el que se est buscando, la verificacin si A[mitad] == elemento ser verdadera, y las llamadas recursivas se detendrn. Si no lo es, el valor de primero se har ms grande que el valor de ultimo en la siguiente divisin. Por qu? Porque si piensa en la accin de divisin del algoritmo, se dar cuenta que cada llamada recursiva hace que primero se incremento y ultimo se decremente. De esta manera, si el elemento no est en el arreglo, el valor de primero se hace finalmente ms grande que el valor de ultimo. Por lo tanto se puede usar esta idea para verificar que el elemento no est en el arreglo, tambin para usarlo como una condicin primitiva. De esta manera, se reemplazar la condicin primitiva original con el siguiente enunciado: si (primero > ultimo) entonces regresar 1 Si ocurre esta condicin, se regresa el valor -1, indicando que no se encontr el elemento y terminan las llamadas recursivas. Ahora, vamos a aplicar este conocimiento a un segundo nivel del algoritmo. Como sigue: Algoritmo busquedaBin(): Segundo nivel busquedaBin(A, elemento, primero, ultimo) INICIO si(primero > ultimo) entonces regresar -1. sino Establecer mitad = (primero + ultimo) / 2. si (A[mitad] == elemento) entonces regresar mitad. sino si (el elemento est en la primera mitad) entonces busquedaBin(A, elemento, primero, mitad - l) sino busquedaBin(A, elemento, mitad + 1, ultimo) FIN. Es evidente ahora que el algoritmo realiza la recursividad, porque se puede ver la funcin llamndose a s misma en uno o dos lugares, dependiendo de en qu mitad del arreglo dividido es probable que se encuentre el elemento. Tambin, observe en dnde se verifican los dos casos primitivos. Si, al inicio de una llamada recursiva, primero > ultimo, el elemento no est en el arreglo y las llamadas recursivas terminan. Adems, si despus de calcular mitad, se encuentra el elemento en A[mitad], terminar la llamada recursiva. En ambos casos, la funcin ha terminado su ejecucin y regresa un valor al programa llamador. Lo ltimo que
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-54

MIGUEL . TOLEDO MARTNEZ

necesita el algoritmo es una forma para determinar si el elemento que se busca es muy probable que se encuentre en la primera mitad o en la segunda mitad del arreglo dividido. Aqu es donde viene el requerimiento para un arreglo ordenado. Si el arreglo est ordenado, es muy probable que el elemento se encuentre en la primera mitad del arreglo cuando elemento < A[mitad]; de otra manera, es muy probable que el elemento se encuentre en la segunda mitad del arreglo. Observe que usamos el trmino es muy probable. Nosotros no podemos garantizar que el elemento se encuentre en cualquier mitad, ya que, inclusive, podra no estar en el arreglo! Todo lo que se puede hacer es dirigir la bsqueda a la mitad donde es muy probable que se encuentre el elemento, dependiendo del orden de clasificacin de los elementos. Por lo tanto, se puede completar el algoritmo usando esta idea. Aqu est el algoritmo final: Algoritmo busquedaBin() busquedaBin(A, elemento, primero, ultimo) INICIO si(primero > ultimo) entonces regresar -1. sino Establecer mitad = (primero + ultimo) / 2. si (A[mitad] == elemento) entonces regresar mitad. sino si (elemento < A[mitad]) entonces busquedaBin(A, elemento, mitad - l). sino busquedaBin(A, elemento, mitad + 1, ultimo) FIN. Observe qu elegante es el algoritmo. Por elegante se debe entender que ms que un proceso complicado de bsqueda binaria, se trata de slo unos cuantos enunciados. Se sabe que hay mucho por recorrer todava, pero la recursividad permite expresar todo este procedimiento en slo unos cuantos enunciados. Como puede ver, a menudo los algoritmos recursivos proporcionan soluciones simples a problemas de gran complejidad, en donde una solucin iterativa equivalente puede ser compleja. ste no es siempre el caso, porque algunas soluciones recursivas son relativamente poco prcticas para la eficiencia de velocidad y de memoria. Recuerde la siguiente regla cuando considere la recursividad: considere una solucin recursiva para un problema slo cuando no sea posible una solucin iterativa sencilla. Tome en cuenta que la bsqueda binaria tiene una solucin iterativa relativamente sencilla. Se codificar esta solucin para uno de los problemas al final de esta leccin.

CODIFICACIN DEL PROGRAMA


La funcin que requiere C++ ahora se puede codificar con facilidad a partir del algoritmo final. Como sigue: int busquedaBin(int[A], int elemento, int primero, int ultimo) { int mitad; // PUNTO MEDIO DEL ARREGLO if (primero > ultimo) // SI EL ELEMENTO NO EST EN EL ARREGLO return -l; // REGRESA -1, SI NO CONTINA LA BSQUEDA else { mitad = (primero + ultimo) / 2; // ENCUENTRA EL PUNTO // MEDIO DEL ARREGLO if (elemento == A[mitad]) // Si EL ELEMENTO EST EN // A[mitad] return mitad; // REGRESA mitad else // Si NO, BUSCA LA MITAD APROPIADA if (elemento < A[mitad]) return busquedaBin(A, elemento, primero, mitad - l); else
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-55

MIGUEL . TOLEDO MARTNEZ

return busquedaBin(A, elemento, mitad + 1, ultimo); } / /FINAL DE else EXTERNO } // FINAL DE busquedaBin() No deber tener ningn problema para comprender este cdigo, ya que refleja la interfaz de la funcin y al algoritmo que se desarroll. Aqu la nica diferencia es que las llamadas recursivas en busquedaBin() forman parte de un enunciado return. Recuerde que C++ requiere que todos los caminos de ejecucin de una funcin sin void den origen a un enunciado return.

Ejemplo 18.36
El siguiente programa, BSQUEDA.CPP, ilustra los mtodos de bsqueda lineal y binaria. Es bastante interesante la solucin que se propone, por lo que se le pide al lector que lea con detenimiento la codificacin. /* El siguiente programa: BUSQUEDA.CPP, busca en arreglos usando los mtodos de bsqueda lineal y binaria. */ #include <ctype.h> #include <iostream.h> #include <stdlib.h> typedef int (*funcBusqueda)(int,int[],int); const int MIN = 2; const int MAX = 10; const int NO_ENCONTRADO = -1; // Pide al usuario la cantidad de elementos del arreglo int obtenNumPuntos(int minimo, int maximo) { int numPuntos; do { cout << "Introduzca el nmero de puntos de datos [" << minimo << " a " << maximo << "]: "; cin >> numPuntos; } while (numPuntos < minimo || numPuntos > maximo); return numPuntos; }//Fin de obtenNumPuntos() // Pedir al usuario los datos del arreglo void entradaArreglo(int intArr[], int num) { for (int i = 0; i < num; i++) { cout << "arreglo[" << i << "]: "; cin >> intArr[i]; }//Fin del for }//Fin de entradaArreglo() // Desplegar el contenido de un arreglo void mostrarArreglo(int intArr[], int num)

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-56

MIGUEL . TOLEDO MARTNEZ

{ for (int i = 0; i < num; i++) { cout.width(5); cout << intArr[i] << " "; }//Fin del for cout << endl; }//Fin de mostrarArreglo() // Rutina de bsqueda lineal int busquedaLineal(int valorBuscar, int intArr[], int num) { for (int i = 0; i < num; ++i) if (valorBuscar == intArr[i]) return i; return NO_ENCONTRADO; }//Fin de busquedaLineal() // Subfuncin de bsqueda binaria recursiva int busquedaBinaria(int valorBuscar, int intArr[], int minimo, int maximo) { int mitad = (minimo + maximo) / 2; if (minimo > maximo) return NO_ENCONTRADO; else if (valorBuscar == intArr[mitad]) return mitad; else if (valorBuscar > intArr[mitad]) return busquedaBinaria(valorBuscar, intArr, mitad + 1, maximo); else return busquedaBinaria(valorBuscar, intArr, minimo, mitad - 1); }//Fin de busquedaBinaria() // Punto de entrada principal para la bsqueda binaria int busquedaBinaria(int valorBuscar, int intArr[], int n) { return busquedaBinaria(valorBuscar, intArr, 0, n - 1); }//Fin de busquedaBinaria // Revisin para la continuacin de la bsqueda bool debeBuscar(const char *tipoBusqueda) { char car; cout << "Buscar en el arreglo " << tipoBusqueda << "? (S/N) "; cin >> car; return tolower(car) == 's'; }//Fin de debeBuscar // Maneja la prueba de bsqueda void buscarArreglo( int intArr[], int num, const char *tipoBusqueda, funcBusqueda buscar ) { int valorBuscar, index; char car;

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-57

MIGUEL . TOLEDO MARTNEZ

while (debeBuscar(tipoBusqueda)) { cout << "Introduzca valor a buscar: "; cin >> valorBuscar; index = buscar(valorBuscar, intArr, num); if (index != NO_ENCONTRADO) cout << "Encontr el elemento en el ndice " << index << endl; else cout << "No encontr el elemento" << endl; }//Fin de while }//Fin de buscarArreglo() // Compara dos enteros int cmpEnt(const void *item1, const void *item2) { return *(int*)item1 - *(int*)item2; }//Fin de cmpEnt)= void main(void) { int arr[MAX]; int numElementos; numElementos = obtenNumPuntos(MIN, MAX); entradaArreglo(arr, numElementos); cout << "El arreglo desordenado es:" << endl; mostrarArreglo(arr, numElementos); buscarArreglo(arr, numElementos, "desordenado", busquedaLineal); qsort(arr, numElementos, sizeof(arr[0]), cmpEnt); cout << endl << "El arreglo ordenado es:" << endl; mostrarArreglo(arr, numElementos); buscarArreglo(arr, numElementos, "ordenado", busquedaBinaria); }//Fin de main()

Ejemplo 18.37
Una variante de solucin del programa BSQUEDA.BPP, es el programa siguiente, BUSQUEDA2.CPP. /* El siguiente programa: BUSQUEDA2.CPP, busca en arreglos usando los mtodos de bsqueda lineal y binaria. */ #include <ctype.h> #include <iostream.h> #include <search.h> #include <stdlib.h> typedef int* (*funcBusqueda)(int,int[],int); const int MIN = 2; const int MAX = 10;

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-58

MIGUEL . TOLEDO MARTNEZ

// Compara dos enteros int cmpEnt(const void *item1, const void *item2) { return *(int*)item1 - *(int*)item2; }//Fin de cmpEnt() // Pide al usuario el nmero de elementos del arreglo int obtenNumPuntos(int minimo, int maximo) { int numPuntos; do { cout << "Introduzca el nmero de puntos de datos [" << minimo << " a " << maximo << "]: "; cin >> numPuntos; } while (numPuntos < minimo || numPuntos > maximo); return numPuntos; }//Fin de obtenNumPuntos() // Pide al usuario los datos del arreglo void entradaArreglo(int intArr[], int num) { for (int i = 0; i < num; i++) { cout << "arreglo[" << i << "]: "; cin >> intArr[i]; }//Fin del for }//Fin de entradaArreglo() // Despliega el contenido de un arreglo void mostrarArreglo(int intArr[], int num) { for (int i = 0; i < num; i++) { cout.width(5); cout << intArr[i] << " "; }//Fin del for cout << endl; }//Fin de mostrarArreglo() // Rutina de bsqueda lineal int *busquedaLineal(int valorBuscar, int intArr[], int num) { return (int*)lfind(&valorBuscar, intArr, (size_t*)&num, sizeof(intArr[0]), cmpEnt); }//Fin de busquedaLineal() // Puntos de entrada principal para la bsqueda de datos int *busquedaBinaria(int valorBuscar, int intArr[], int n) { return (int*)bsearch(&valorBuscar, intArr, n, sizeof(intArr[0]), cmpEnt);
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-59

MIGUEL . TOLEDO MARTNEZ

}//Fin de busquedaBinaria() // Verificar la continuidad de bsqueda bool debeBuscar(const char *tipoBusqueda) { char ch; cout << "Buscar en el arreglo " << tipoBusqueda << "? (S/N) "; cin >> ch; return tolower(ch) == 's'; }//Fin de debeBuscar() // Manejar la prueba de bsqueda void buscarArreglo(int intArr[], int num, const char* tipoBusqueda, funcBusqueda buscar ) { int valorBuscar; int *indice; char ch; while (debeBuscar(tipoBusqueda)) { cout << "Introduzca el valor de bsqueda: "; cin >> valorBuscar; indice = buscar(valorBuscar, intArr, num); if (indice) cout << "El elemento se encontr en el ndice " << indice - intArr << endl; else cout << "No se encontr el elemento" << endl; }//Fin de while }//Fin de buscarArreglo() void main(void) { int arr[MAX]; int numElementos; numElementos = obtenNumPuntos(MIN, MAX); entradaArreglo(arr, numElementos); cout << "El arreglo desordenado es:" << endl; mostrarArreglo(arr, numElementos); buscarArreglo(arr, numElementos, "desordenado", busquedaLineal); qsort(arr, numElementos, sizeof(arr[0]), cmpEnt); cout << endl << "El arreglo ordenado es:" << endl; mostrarArreglo(arr, numElementos); buscarArreglo(arr, numElementos, "ordenado", busquedaBinaria); }//Fin de main()

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-60

MIGUEL . TOLEDO MARTNEZ

INICIACIN DE ARREGLOS Antes de terminar esta leccin, es necesario saber cmo inicializar los arreglos en el momento en que se definen. Los arreglos, como las variables, se pueden inicializar cuando se crean. Se pueden suministrar valores de iniciacin para cualquier arreglo, mientras est definido en el programa. Consideremos algn ejemplo de definicin de arreglo para mostrar cmo se inicializan los arreglos.
int enteros[3] = {10,20,30};

En esta definicin, se ha presentado un arreglo entero de tres elementos. Los tres elementos enteros se han inicializado con los valores 10, 20 y 30, respectivamente. Observe la sintaxis. La definicin del arreglo es seguida por un operador de asignacin, al cual le suceden los valores de inicializacin encerrados dentro de llaves. Esto es lo que ver si inspecciona al arreglo usando un depurador (debugger):
RESULTADOS DEL DEPURADOR

Inspeccin de enteros
[0] 10 [1] 20 [2] 30

Como puede ver, el primer valor de inicializacin, 10, se coloca en el ndice 0 del arreglo; el valor 20 se coloca en el ndice 1; y el valor 30 se coloca en la ltima posicin del ndice, que es 2. Ahora, qu se supone que sucedera si proporcionara menos valores de inicializacin que las posiciones en el arreglo? Bueno, suponga que define al arreglo como sigue:
int enteros[3] = {10,20};

Enseguida se presenta lo que encontrar cuando inspeccione al arreglo usando un depurador:


RESULTADOS DEL DEPURADOR

Inspeccin de enteros
[0] 10 [1] 20 [2] 00

Como puede observar, el compilador inicializ la ltima posicin del arreglo con cero. Cero es el valor de iniciacin predeterminado para arreglos de enteros cuando no se proporcionan suficientes valores para llenar al arreglo. La siguiente pregunta obvia es: qu sucede si proporciona demasiados valores de iniciacin? Por ejemplo, suponga que define el arreglo como sigue:
int enteros[3] = {10,20,30,40};

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-61

MIGUEL . TOLEDO MARTNEZ

En este caso, se obtendr un error de compilacin, demasiados inicializadores (too many initializers) Una forma de solucionar este problema es incrementar el tamao del arreglo. Otra forma preferida, es definir al arreglo sin ningn tamao especfico, como sigue:
int enteros[] = {10,20,30,40};

Con esta definicin, el compilador establecer suficiente lugar de almacenamiento para contener todos los valores de inicializacin. Aqu est lo que ver si inspecciona esta definicin de arreglo usando un depurador:
RESULTADOS DEL DEPURADOR

Inspeccin de enteros
[0] [1] [2] [3] 10 20 30 40

Ahora, vamos a considerar arreglos de caracteres. Suponga que define un arreglo de caracteres de tamao cinco, como ste:
char caracteres[5] = {H, E, L, L, O}

De nuevo se ve que los valores de inicio se encierran en llaves despus de un operador de asignacin. Esto mostrar el depurador:
RESULTADOS DEL DEPURADOR

Inspeccin de caracteres
[0] [1] [2] [3] [4] H E L L O

Aqu se ve que los cinco caracteres de inicio se colocan en el arreglo empezando en el ndice cero y finalizando en la ltima posicin del ndice, cuatro. Qu pasa si proporciona unos cuantos caracteres de iniciacin menos que los requeridos para llenar el arreglo? Bueno, suponga que define el arreglo de esta forma:
char caracteres[5] = {'H','E'};

El contenido del arreglo ahora ser corno sigue:


RESULTADOS DEL DEPURADOR

Inspeccin de caracteres
[0] [1] [2] [3] [4] H E \0 \0 \0

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-62

MIGUEL . TOLEDO MARTNEZ

Esta vez, el compilador ha insertado un carcter terminador nulo como un carcter predeterminado para llenar el arreglo. De otra manera, si proporciona demasiados caracteres, el compilador generar un mensaje de error demasiados inicializadores. De nuevo, la forma segura para manejar este problema es dejar que el compilador determine el tamao del arreglo para ajustar el nmero de valores inicializados. Por ltimo, vamos a considerar cmo se inicializa el arreglo de caracteres con valores de cadenas. Recuerde, una cadena no es ms que un arreglo de caracteres, terminada con un terminador nulo. As es como se puede inicializar un arreglo de caracteres con un valor de cadena:
char caracteres[6] = "HELLO";

Observe que la sintaxis es diferente. La cadena de iniciacin deber encerrarse entre comillas ms que entre llaves. Otra cosa que se ve es que el tamao del arreglo es uno ms grande que el nmero de caracteres en la cadena. La razn para esto parece obvia cuando inspecciona el arreglo usando un depurador. Aqu esta lo que ver:
RESULTADOS DEL DEPURADOR

Inspeccin de caracteres
[0] [1] [2] [3] [4] [5] H E L L O \0

Recuerde que una cadena terminar con un terminador nulo. Al hacer el tamao del arreglo uno ms grande que el nmero de caracteres en la cadena, permite espacio para que el compilador inserte el terminador nulo. Si no se deja espacio para el terminador nulo, ste quedar truncado (eliminado) del arreglo y no se obtendr un mensaje de error. De nuevo, la mejor manera de evitar este problema es permitir que el compilador determine el tamao del arreglo, como ste:
char caracteres[] = "HELLO";

Con esta definicin, el compilador crear suficientes posiciones en el arreglo para contener todos los caracteres de cadenas con el terminador nulo insertado como el ltimo carcter en el arreglo.
INICIACIN PREDETERMINADA DE ARREGLOS GLOBALES Y ESTTICOS

Se pueden definir e inicializar arreglos en cualquier parte del programa C++. El mbito de un arreglo funciona justo como el mbito de una variable o constante. Un arreglo definido antes de main() es visible en todo el archivo fuente en el cual se define. Un arreglo definido dentro de un bloque tiene mbito de bloque y, por lo tanto, es visible slo dentro del bloque en el cual se define. Si se define un arreglo en forma global o como un arreglo esttico y no se proporciona ningn valor de inicializacin, el compilador inicializar el arreglo con el valor predeterminado
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-63

MIGUEL . TOLEDO MARTNEZ

respectivo (ceros para arreglos de enteros y de punto flotante y terminadores nulos para arreglos de caracteres) El siguiente es un ejemplo:
int enteros[5]; void main(void) { static char caracteres[5]; } // FINAL DE main()

Se ha definido en forma global el arreglo enteros y tambin como un arreglo esttico local al arreglo caracteres dentro de main() La inspeccin de estos arreglos con un depurador revelar lo siguiente:
RESULTADOS DEL DEPURADOR

Inspeccin de enteros
[0] [1] [2] [3] [4] 0 0 0 0 0

Inspeccin de caracteres
[0] [1] [2] [3] [4] \0 \0 \0 \0 \0

El depurador muestra que el arreglo global de enteros se ha inicializado con ceros, mientras que el arreglo de caracteres esttico se ha inicializado con caracteres de terminador nulo. Si define un arreglo con mbito de bloque local que no es esttico y no lo inicializa, el compilador no suministrar ningn valor de inicializacin predeterminado. El arreglo contendr basura! De esta manera, si eliminramos la palabra clave static de la definicin anterior del arreglo caracteres, el depurador revelar valores arbitrarios de memoria en el arreglo.
Aqu est un resumen de la explicacin anterior: Los arreglos de enteros, de punto flotante y de caracteres se inicializan por medio de un operador de asignacin despus de la definicin del arreglo, seguido por una lista de valores individuales de inicializacin dentro de llaves. Menos valores de iniciacin darn como resultado valores predeterminados (ceros para arreglos de enteros y de punto flotante y terminadores nulos para arreglos de caracteres) insertados en las posiciones adicionales del arreglo. Ms valores de iniciacin provocan un error de compilacin. Los arreglos de caracteres se pueden inicializar encerrando una cadena con comillas dobles. El tamao de un arreglo de cadena deber ser uno ms grande que el nmero de caracteres dentro de la cadena para dejar espacio para el carcter terminador nulo. Si no se especifica un tamao en la definicin del arreglo, el compilador crear el suficiente espacio de almacenaje para los valores de inicializacin. Los arreglos globales y arreglos estticos se inicializan siempre con los valores predeterminados respectivos cuando ningn valor de iniciacin se suministra en la definicin del arreglo.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-64

MIGUEL . TOLEDO MARTNEZ

Los arreglos locales que no son estticos no se inicializarn con ningn valor especfico, a menos que se proporcionen en la definicin del arreglo.

EXAMEN BREVE 38 ARREGLOS QUE REBASAN LOS 64 KBYTES DE MEMORIA Si un arreglo rebasa los 64 kbytes de longitud, el mismo enviar un mensaje de error (Array size too large) en tiempo de compilacin.
Ejemplo 18.38
El siguiente programa, DEMGDE.CPP, ilustra esta situacin. /* El siguiente programa: DEMGDE.CPP, no se compila correctamente ya que el arreglo utiliza mas de 64 kbytes de memoria. */ void main(void) { char cadena[66000L]; int valores[33000L]; float numeros[17000]; }//Fin de main() // 66,000 bytes // 33,000 * 2 = 66,000 bytes // 17,000 * 4 = 68,000 bytes

Ejemplo 18.39
El siguiente programa ENORME.CPP, ilustra como resolver esta situacin. /* El siguiente programa: ENORME.CPP crea un arreglo de ms de 64 kbytes de datos de punto flotante. */ #include <iostream.h> #include <malloc.h> void main (void) { int i; float huge *valores; if ((valores = (float huge *) halloc (17000, sizeof(float))) == NULL) cout << "Error al reservar memoria para el arreglo" << endl; else { cout << "Llenando el arreglo" << endl; for (i = 0; i < 17000; i++) valores[i] = i * 1.0; //Para cout y cin //Para halloc()

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-65

MIGUEL . TOLEDO MARTNEZ

for (i = 0; i < 17000; i++) cout << valores[i] << ' '; hfree(valores); }//Fin de else }//Fin de main()

LO QUE NECESITA SABER Antes de continuar con la siguiente leccin, asegrese de haber comprendido los siguientes conceptos:
!"Un arreglo es una variable que puede almacenar uno o ms valores del mismo tipo. !"Un arreglo es una estructura de datos importante que se usa para localizar y almacenar elementos de una clase de datos dados. !"Los dos componentes de cualquier arreglo son los elementos que se almacenan en el arreglo y los ndices que localizan los elementos almacenados. !"Los elementos del arreglo pueden ser cualquier clase de datos y los ndices del arreglo son siempre enteros de rango desde [0] hasta [MAX - 1 ], en donde MAX es el tamao del arreglo. !"Hay arreglos unidimensionales y multidimensionales. Un arreglo unidimensional o lista es un rengln sencillo de elementos. Tiene dimensiones de 1 x n, donde n es el nmero de elementos de la lista. En C++, el ndice mximo en cualquier dimensin es el tamao de la dimensin (n) menos 1. !"Para declarar un arreglo debe especificar su tipo, el nombre del arreglo y el nmero de valores que el arreglo almacenar. !"Los arreglos se definen en C++ especificando la clase de datos del elemento, el nombre y el tamao del arreglo. !"Para tener acceso a los elementos del arreglo, se usan enunciados de asignacin directa, de lectura o escritura o ciclos. !"La estructura del ciclo for es la forma ms comn de tener acceso a los mltiples elementos de un arreglo. !"Los valores dentro del arreglo se llaman elementos del arreglo. !"El primer elemento del arreglo se almacena en el elemento 0 (arreglo[0]); el ltimo elemento es indexado por un valor menor en 1 que el tamao del arreglo. !"Los programas a menudo utilizan variables como ndice para acceder los elementos del arreglo. !"En los arreglos de C++ se almacenan listas de valores. Un arreglo es un conjunto de localidades consecutivas de memoria relacionadas. Estas localidades se relacionan por el hecho de que todas tienen el mismo nombre y la misma clase de datos. Para hacer referencia a una localidad particular o elementos de un arreglo, se especifica el nombre del arreglo y su ndice. !"Un ndice puede ser un entero o una expresin entera. Las expresiones de ndices se evalan para determinar el elemento particular del arreglo. !"Es importante notar la diferencia que hay entre referirse al sptimo elemento del arreglo e indicar el elemento siete del arreglo. El sptimo elemento tiene el ndice 6, mientras que el elemento siete del arreglo tiene el ndice 7 (de hecho, se trata del octavo elemento) Esto es fuente de errores por diferencia de uno. !"Los arreglos ocupan espacio en memoria. Para reservar 100 elementos para el arreglo de enteros b y 27 elementos para el arreglo x, el programador escribe int b[100], x[27];
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-66

MIGUEL . TOLEDO MARTNEZ

!"Es posible utilizar un arreglo de clase char para almacenar una cadena de caracteres. !"Los elementos de un arreglo pueden inicializarse por declaracin, por asignacin o por entrada. !"Si hay menos inicializadores que elementos en el arreglo, los elementos restantes se inicializan a cero. !"C++ no evita que se haga referencia a elementos que estn fuera de los lmites de un arreglo. !"Es posible inicializar un arreglo de caracteres por medio de una literal de cadena. !"Todas las cadenas terminan con el carcter nulo (\0) !"Los arreglos de caracteres se pueden inicializar con constantes de carcter en una lista de iniciacin. !"Es posible acceder a los caracteres de una cadena almacenada en un arreglo por medio de la notacin de ndices. !"Para pasar un arreglo a una funcin, hay que pasar su nombre. Para pasar un solo elemento del arreglo a una funcin, simplemente hay que pasar el nombre del arreglo seguido por el ndice (entre corchetes cuadrados) de dicho elemento. !"Los arreglos se pasan a las funciones simulando una llamada por referencia; las funciones llamadas pueden modificar los valores de los elementos de los arreglos originales. El nombre del arreglo es la direccin de su primer elemento. Debido a que se pasa la direccin de inicio del arreglo, la funcin llamada sabe exactamente dnde est almacenado dicho arreglo. !"Para recibir un arreglo como argumento, la lista de parmetros de la funcin debe especificar que se recibir un arreglo. No es necesario el tamao del arreglo entre los corchetes. !"Cuando una funcin recibe un arreglo como parmetro, la funcin debe especificar la clase del arreglo y su nombre, pero no el tamao del arreglo. !"C++ tiene el calificador de clase const, que permite a los programas evitar la modificacin, en una funcin, de los valores de un arreglo. Cuando un parmetro de arreglo est precedido por el calificador const, los elementos del arreglo se vuelven constantes en el cuerpo de la funcin y cualquier intento por modificarlos provoca un error de sintaxis. !"La bsqueda y ordenacin son operaciones comunes realizadas sobre arreglos. !"Los arreglos pueden ordenarse mediante la tcnica de ordenamiento de burbuja. Se realizan varias pasadas al arreglo. Con cada pasada se comparan los pares consecutivos de los elementos. Si un par est ordenado (o sus valores son idnticos), se deja tal cual. Si est fuera de orden, se intercambian. El ordenamiento de la burbuja es aceptable en los arreglos pequeos, pero en los mayores es ineficiente en comparacin con otros algoritmos de ordenamiento ms complejos. La !" bsqueda secuencial es una bsqueda iterativa que busca un valor dado en un arreglo, comparando en forma secuencial el valor con los elementos del arreglo, empezando con el primer elemento del arreglo, hasta que se encuentra el valor en el arreglo o hasta que se alcanza el final del arreglo. La !" bsqueda lineal compara todos los elementos de un arreglo con la clave de bsqueda. Si el arreglo no est en ningn orden en particular, existe la misma probabilidad de que el valor se encuentre en el primer elemento como que est en el ltimo. Por lo tanto, en promedio, el programa tendr que comparar la clave de bsqueda con la mitad de los elementos del arreglo. El mtodo de bsqueda lineal funciona bien con los arreglos pequeos y es aceptable si se trata de arreglos desordenados. !" bsqueda binaria puede ser iterativa o recursiva. Una bsqueda binaria divide el arreglo Una en mitades, dirigindose a s misma hacia la mitad en donde es muy probable que se encuentre el valor. La !" bsqueda binaria requiere que el arreglo est ordenado, mientras que la bsqueda secuencial no tiene este requerimiento.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-67

MIGUEL . TOLEDO MARTNEZ

Por !" otra parte, la bsqueda binaria es mucho ms rpida que la secuencial, especialmente en grandes arreglos ordenados. La !" bsqueda binaria elimina de su consideracin la mitad de los elementos del arreglo tras cada comparacin; esto lo logra localizando el elemento central del arreglo y comparndolo con la clave de bsqueda. Si son iguales, entonces se encuentra la clave de bsqueda y se devuelve el ndice de dicho elemento. De otra manera, se reduce el problema a la bsqueda en una mitad del arreglo. En !" el peor caso, la bsqueda en un arreglo de 1024 elementos slo necesitara 10 comparaciones y se efecta mediante bsqueda binaria. !"Muchas aplicaciones en el mundo real requieren que la informacin est ordenada. Hay algunos algoritmos de clasificacin comunes, incluyendo clasificacin por insercin, clasificacin por burbuja, clasificacin por seleccin y clasificacin rpida. !"Todos estos algoritmos operan sobre arreglos. El algoritmo de clasificacin por insercin es un proceso iterativo que inserta un elemento dado en el arreglo en su lugar correcto relativo a los elementos que lo preceden en el arreglo. Usted se familiarizar con la clasificacin de burbuja y la clasificacin de seleccin en los problemas de esta leccin.

PREGUNTAS Y PROBLEMAS
PREGUNTAS
1. Llene los siguientes espacios en blanco: Las listas y tablas de valores se guardan en ________________________. Los elementos de un arreglo se relacionan por el hecho de que tienen el mismo __________ y _____________. c. El nmero con el que se hace referencia a un elemento en particular de un arreglo se llama _____________. d. Debe usarse una _______________ para declarar el tamao de un arreglo, pues hace ms escalable el programa. e. El proceso de colocar en orden los elementos en un arreglo se llama _______________ del arreglo. f. El proceso con el que se determina si un arreglo contiene cierto valor clave se llama ____________. g. C++ almacena las listas de valores en _________________. h. Al referirse a un elemento de un arreglo, el nmero de posicin contenido entre parntesis se llama _____________. i. Los nombres de los cuatro elementos del arreglo p son __________, _____________, _________ y ___________. j. La denominacin de un arreglo, indicacin de su clase y especificacin de la cantidad de elementos que hay en l se llama _____________ del arreglo. k. El proceso de colocacin de los elementos de un arreglo en orden ascendente o descendente se llama _____________. Indique si las siguientes oraciones son falsas o verdaderas. Si la respuesta es falso explique por qu. a. b. a. b. c. d. e. f. g. h. Un arreglo puede contener diferentes clases de valores. Los ndices de los arreglos normalmente deben de ser de clase float. Si hay menos inicializadores en una lista de iniciacin que el nmero de elementos que hay en el arreglo, los elementos restantes se inicializan automticamente al ltimo valor de dicha lista. Es un error que una lista de iniciacin contenga ms inicializadores que la cantidad de elementos que hay en el arreglo. Un elemento de un arreglo que se pasa a una funcin y se modifique ah contendr el valor modificado cuando termine la ejecucin de la funcin llamada. Para hacer referencia a una localidad particular o elemento de un arreglo, se especifica el nombre del arreglo y el valor del elemento. Una declaracin de arreglo reserva espacio para el arreglo. Para indicar que se deben reservar 100 localidades para el arreglo de enteros p, el programador escribir la declaracin

2.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-68

MIGUEL . TOLEDO MARTNEZ

p[100]; i. 3. Un programa C++ que inicialice a 0 los elementos de un arreglo de 15 elementos debe contener cuando menos una instruccin for. Defina una variable constante tamanoArreglo que se inicialice a 10. Declare un arreglo con elementos tamanoArreglo de la clase float e inicialice dichos elementos a 0. Nombre el cuarto elemento a partir del inicio del arreglo. Haga referencia al elemento 4. Asgnele el valor 1.667 al elemento 9. Asgnele el valor 3.333 al sptimo elemento del arreglo. Imprima los elementos 6 y 9 del arreglo con una precisin de dos dgitos a la derecha del punto decimal y muestre la salida que se desplegar en la pantalla. Imprima todos los elementos del arreglo mediante una estructura de repeticin for. Defina la variable entera x como la variable de control del ciclo. Muestre la salida.

Conteste las siguientes preguntas relacionadas con un arreglo llamado fracciones. a. b. c. d. e. f. g. h.

4.

Encuentre los errores en los siguientes segmentos de programa y corrjalos. a. #include <iostream.h>; //tamanoArreglo se declar como const b. tamanoArreglo = 10; int b[10] = {0}; c. Suponga que for(int i = 0; i <= 10; i++) b[i] = 1; instrucciones en C++ que lleven a cabo lo siguiente: Escriba a. Presente el valor del sptimo elemento de un arreglo de caracteres f. b. Introduzca un valor en el elemento 4 de un arreglo de punto flotante b, de un solo ndice. c. Inicialice a 8 los 5 elementos del arreglo de enteros g, de un solo ndice. d. Totalice e imprima los elementos del arreglo de punto flotante c, que tiene 100 elementos. e. Copie el arreglo a a la primera parte del arreglo b. Suponga que estn declarados como float a[11], b[34]; f. Determine e imprima el valor menor y el mayor contenidos en un arreglo w de punto flotante de 99 elementos.

5.

6.

Cules son las tres cosas que se deben especificar para definir un arreglo?

Use la siguiente definicin de arreglo para contestar las preguntas 7 12.


char caracteres[15]; Cul es el ndice del primer elemento del arreglo? Cul es el ndice del ltimo elemento del arreglo?

7. 8. 9.

Escriba un enunciado que coloque el carcter 'Z' en la tercera celda del arreglo. 10. Escriba un enunciado que muestre el ltimo elemento del arreglo. 11. Escriba el cdigo necesario para llenar el arreglo desde el teclado. Cercirese de preguntar al usuario antes de cada entrada de carcter. 12. Escriba un ciclo que muestre verticalmente en la pantalla todos los elementos del arreglo. 13. Muestre el contenido del siguiente Arreglo: int enteros[5] = {1,2,3}; 14. Muestre el contenido del siguiente arreglo: char caracteres[5] = {C, +, +}; 15. Dnde est el error en la siguiente definicin de arreglo? char OOP[3] = C++; Cmo corrige el problema en esta definicin?
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-69

MIGUEL . TOLEDO MARTNEZ

16. Escriba un enunciado para definir un arreglo de punto flotante que se inicializar con ceros y es local para main() 17. Dnde est el error en la siguiente definicin del arreglo? int nmeros[4] = {0,1,2,3,4}; 18. Dada la siguiente definicin de arreglo, int valores[10]; a. Escriba un enunciado para colocar el producto del primero y segundo elementos de arreglo en la posicin del ltimo elemento.

Use la siguiente definicin de arreglo para contestar las preguntas 19 - 23:


const int MAX = 4; char cadena[MAX] =C++; 19. Escriba el prototipo para una funcin de nombre longitudCadena() que recibir el arreglo completo y regresa la longitud de la cadena. 20. Escriba un prototipo para una funcin de nombre elementoCadena() que recibir un elemento sencillo de la cadena, de manera que cualquier operacin sobre ese elemento dentro de la funcin no afectar el valor del elemento dentro del arreglo. 21. Escriba un enunciado para llamar la funcin de la pregunta 19 y pase el primer elemento del arreglo a la funcin. 22. Escriba un prototipo para una funcin de nombre cambiaElemento() que recibir un solo elemento de la cadena, de manera que cualquier modificacin en este elemento dentro de la funcin cambie el valor del elemento en el arreglo. 23. Escriba un enunciado para llamar a la funcin de la pregunta 22 y pase el ltimo elemento del arreglo a la funcin. 24. En general, qu posicin del elemento se regresar por medio de las funciones de bsqueda secuencial y binaria desarrolladas en esta leccin, si un elemento se presenta varias veces en el arreglo? 25. Por qu, en promedio, es ms rpida la bsqueda binaria que la secuencial? 26. Cundo es ms rpida la bsqueda secuencial que la binaria? 27. Revise el algoritmo clasifPorInser() para ordenar el arreglo de modo descendente.

PROBLEMAS
1. Escriba un programa para llenar un arreglo con todos los enteros impares desde 1 hasta 99. Escriba una funcin para llenar el arreglo y otra para mostrar ste, desplegando en la pantalla los enteros impares separados por comas. Escriba una funcin para leer el nombre del usuario desde la entrada del teclado y colquelo en un arreglo de caracteres. Escriba otra funcin para mostrar el nombre del usuario almacenado en el arreglo. Verifique sus funciones por medio de un programa de aplicacin. Escriba un programa para leer una lista de 25 elementos de caracteres desde una entrada de teclado y mustrelos en orden inverso. Use una funcin para llenar la lista con los elementos escritos y otra para mostrarla. Escriba un programa que use seis arreglos de caracteres para almacenar el nombre del usuario, domicilio, ciudad, estado, cdigo postal y nmero telefnico. Proporcione una funcin para llenar los arreglos y otra para mostrar el contenido del arreglo usando un formato de direccionamiento apropiado. (La coladera de Eratstenes) Un entero primo es cualquier entero que es divisible slo entre l mismo y entre 1. La coladera de Eratstenes es un mtodo para encontrar nmeros primos. Opera como sigue:

2.

3.

4.

5.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-70

MIGUEL . TOLEDO MARTNEZ

a) Cree un arreglo con todos los elementos inicializados a 1 (verdadero) Los elementos del arreglo que tengan ndices primos permanecern en 1. Los dems elementos del arreglo en algn momento se establecern a cero. b) Comenzando por ndice 2 (el ndice 1 debe ser primo), cada vez que se encuentre un elemento del arreglo que sea 1, haga un ciclo por el resto del arreglo y establezca a cero todos los elementos cuyo ndice sea un mltiplo de dicho ndice. Para el ndice 2, todos los elementos por encima de 2 que sean mltiplos de 2 se establecern a cero (los ndices 4, 6, 8, 10, etc.); en el caso del ndice 3, todos los elementos por encima de 3 que sean mltiplos de 3 se establecern a cero (ndices 6, 9, 12, 15, etc.); y as sucesivamente. Terminado este proceso, los elementos del arreglo que an estn establecidos a 1 indicarn que el ndice es un nmero primo, as que podrn imprimirse. Escriba un programa con un arreglo de 1000 elementos que determine e imprima los nmeros primos entre 1 y 999. Ignore el elemento 0 del arreglo. Por medio de un arreglo de un solo ndice resuelva el siguiente problema. Una compaa paga a sus vendedores con base en una comisin. Los vendedores reciben $200 a la semana ms 9% de sus ventas netas durante la semana. Por ejemplo, un vendedor cuyas ventas brutas son de $5000, a la semana recibe $200 ms 9% de $5000, es decir un total de $650. Escriba un programa (con un arreglo de contadores) que determine la cantidad de vendedores que ganaron salarios dentro de los siguientes rangos (suponga que el salario de cada vendedor se cierra a una cifra entera): a) $200 - $299 b) $300 - $399 c) $400 - $499 d) $500 - $599 e) $600 - $699 f) $700 - $799 g) $800 - $899 h) $900 - $999 i) $1000 o ms El ordenamiento por el mtodo de la burbuja elaborado en el ejemplo 18.26. es ineficiente en el caso de arreglos grandes. Haga las siguientes modificaciones sencillas que mejorarn el desempeo del ordenamiento de burbuja. a) Despus de la primera pasada, se garantiza que la cifra mayor es el elemento de mayor ndice del arreglo, tras la segunda pasada, los dos nmeros mayores estn en su lugar, etc. En lugar de hacer nueve comparaciones con cada pasada, modifique el ordenamiento de burbuja para que efecte ocho comparaciones en la segunda pasada, siete en la tercera, etc. b) Los datos en el arreglo tal vez ya estn en el orden adecuado, o casi, as que por qu hacer nueve pasadas si tal vez baste con menos? Modifique el ordenamiento para comprobar al final de cada pasada si se han hecho intercambios. Si no ha sucedido ninguno, entonces los datos ya estarn en orden y deber terminar el programa. Si han sucedido intercambios, entonces se necesita cuando menos otra pasada. 8. Escriba instrucciones que lleven a cabo las siguientes operaciones sobre arreglos de un solo ndice. Debe ser una sola instruccin por cada una. Inicialice a cero los 10 elementos del arreglo de enteros contador. Sume 1 a cada uno de los 15 elementos del arreglo de enteros bonos. Lea del teclado 12 valores para el arreglo float temperaturaMensual. Imprima los 5 valores del arreglo de enteros mejoresCalificaciones en formato de columnas Encuentre el error o los errores en las siguientes instrucciones: a) b) c) d) a) Suponga que: char cadena[5]; cin >> cadena; //El usuario teclea bello int a[3]; cout << a[1] << << a[2] << << a[3] << endl; 18-71

6.

7.

9.

b) Suponga que:

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

MIGUEL . TOLEDO MARTNEZ

c) float f[3] = {1.1, 10.01, 100.001, 1000.0001}; 10. Modifique el ejemplo 18.32 para que la funcin moda() pueda manejar empates en el valor de la moda. Tambin modifique la funcin mediana() de modo que se promedien los dos elementos centrales cuando se trate de un arreglo con un nmero par de elementos. 11. Con un arreglo de un solo ndice resuelva el siguiente problema. Lea 20 nmeros entre 10 y 100, inclusive. A medida que se lea cada nmero, imprmalo slo si no es un duplicado de algn nmero ya ledo. Tome en cuenta el peor caso, cuando todos los nmeros son diferentes. Resuelva este problema empleado el arreglo ms pequeo posible. 12. Escriba un programa que simule el lanzamiento de dos dados. El programa deber valerse de rand() para lanzar el primer dado y nuevamente rand() para lanzar el segundo. Luego debe calcular la suma de ambos valores. Nota: debido a que cada dado puede tener un valor entero de 1 a 6, entonces la suma de ambos valores variar de 2 a 12, siendo 7 la suma ms frecuente y 2 y 12 las menos frecuentes. La figura 18.5 muestra las 36 combinaciones de dados posibles. Su programa deber lanzar ambos dados 36,000 veces. Mediante un arreglo de un solo ndice, registre la cantidad de veces que aparece cada suma. Imprima el resultado en formato de tabla. Adems determine si los totales son razonables, es decir, hay seis maneras de lanzar 7, por lo que aproximadamente una sexta parte de los lanzamientos debe ser 7. 1 2 3 4 5 6 7 2 3 4 5 6 7 8 3 4 5 6 7 8 9 4 5 6 7 8 9 10 5 6 7 8 9 10 11 6 7 8 9 10 11 12

1 2 3 4 5 6

Figura 18.5. Las 36 posibles combinaciones de lanzamiento de dos dados. 13. Qu hace el siguiente problema? // Nombre del programa: PROBLEMA11.CPP #include <iostream.h> int queEsEsto(int[], int); void main(void) { const int TAMANO_ARREGLO = 10; int a[TAMANO_ARREGLO] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int resultado = queEsEsto(a, TAMANO_ARREGLO); cout << El resultado es: << resultado << endl; } int queEsEsto(int b[], int tamano) { if(tamano == 1) return b[0]; else return b[tamano 1] + queEsEsto(b, tamano 1); } 14. Escriba un programa que ejecute 1000 juegos de dados y conteste las siguientes preguntas: a) Cuntos juegos se ganan al primer lanzamiento, al segundo, ..., al vigsimo y despus de veinte lanzamientos? b) Cuntos juegos se pierden al primer lanzamiento, al segundo, ..., al vigsimo y despus de veinte lanzamientos? c) Cules son las posibilidades de ganar jugando a los dados? (Nota: deber descubrir que los dados son uno de los juegos de casino ms justos. Qu supone que significa esto?)
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-72

MIGUEL . TOLEDO MARTNEZ

d) cul es la duracin promedio de un juego de dados? e) Mejoran las posibilidades de ganar a medida que aumenta la duracin del juego? 15. (Sistema de reservaciones de una aerolnea) Una lnea area pequea acaba de comprar una computadora para su nuevo sistema automatizado de reservaciones. Se le ha pedido a usted que programa este sistema. Deber escribir un programa que asigne asientos en cada vuelo del nico avin de la compaa (capacidad: 10 asientos) Su programa deber presentar el siguiente men de alternativas: Por favor teclee 1 para fumar. Por favor teclee 2 para no fumar. Si se teclea 1, el programa deber asignar un asiento en la seccin de fumadores (asientos 1 a 5) Si se teclea 2, se asignar un asiento en la seccin de no fumar (asientos 6 a 10). El programa deber imprimir un pase de abordar que indique el nmero de asiento del pasajero y si se trata de la seccin de fumar o de no fumar. Mediante un arreglo de un solo ndice, represente la grfica de asientos del avin. Inicialice a cero todos los elementos del arreglo, indicando que todos los asientos estn vacos. A medida que se asigne un asiento, establezca a 1 el elemento correspondiente, indicando que ya no est disponible. El programa, claro est, no deber volver a asignar un asiento ya asignado. Cuando la seccin de fumadores est llena, el programa deber preguntar si es aceptable asignar un asiendo en la seccin de no fumar (y viceversa) Si la respuesta es s, entonces haga la asignacin. Si no, imprima el mensaje el prximo vuelo parte en tres horas. 16. Qu hace el siguiente programa? // PROGRAMA14.CPP #include <iostream.h> void ciertaFuncin(int[], int); void main(void) { const int TAMANO_ARREGLO = 10; int a[TAMANO_ARREGLO] = {32, 27, 64, 18, 95, 14, 90, 70, 60, 37}; cout << Los valores en el arreglo son: << endl; ciertaFuncion(a, TAMANO_ARREGLO); cout << endl; } void ciertaFuncion(int b[], int tamano) { if(tamano > 0) { ciertaFuncion(&b[1], tamano 1); cout << b[0] << ; } } 17. Escriba un programa para verificar la funcin busquedaSec() desarrollado en esta leccin. Use las funciones srand() y rand() disponibles en stdlib.h para llenar un arreglo con valores enteros aleatorios antes de aplicar busquedaSec() Primero se deber hacer una llamada a srand(1) para inicializar el generador de nmero aleatorio. Despus, una llamada a rand() regresar un valor entero entre cero y RAND_MAX, donde su compilador define a RAND_MX. Por ejemplo, el siguiente cdigo generar 10 enteros aleatorios entre 0 y 99:

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-73

MIGUEL . TOLEDO MARTNEZ

srand(1); for(int l = 0; 1 < 10; ++1) cout << rand() % 100 << endl; Primero se llama a la funcin srand() con un valor de argumento de 1 para inicializar el generador de nmero aleatorio de manera que no se generan los mismos 10 nmeros cada vez que se ejecuta el ciclo. La operacin %100 escala el valor que regresa rand() para producir un rango de valores entre 0 y 99. 18. Escriba un programa para verificar la funcin busquedaBin() desarrollada en esta leccin. Use las funciones estndar srand() y rand() disponibles en stdlibh para llenar un arreglo con valores enteros aleatorios como se describi en el problema 5. Despus, aplique clasifPorInser() para clasificar el arreglo antes de usar busquedaBin() Nota: si usa el cdigo clasifPorInser() desarrollado en esta leccin, deber cambiar el cdigo para ordenar un arreglo de enteros en lugar de un arreglo de caracteres. 19. Aqu est la solucin iterativa para una bsqueda binaria en forma de seudocdigo: busquedaBin() Inicio encuentra = Falso. mientras( !encuentra AND primero <= ultimo) hacer mitad = (primero + ltimo) / 2. si (elemento == A[mitad]) entonces encuentra = Verdadero. sino si (elemento < A[mitad]) entonces ultimo = mitad 1.. sino primero = mitad +1.. si (encuentra) entonces regresar mitad.. sino regresar -1. Fin. Codifique este algoritmo como una funcin C++ para buscar un elemento dado en un arreglo de enteros. Escriba un programa de aplicacin para verificar la funcin. Recuerde clasificar el arreglo usando una funcin de clasificacin antes de llamar la funcin de bsqueda binaria. 20. Otro algoritmo de clasificacin iterativa comn es clasificacin por burbuja; aqu est el algoritmo: clasifPorBurbuja() Inicio pasos = 1.. intercambio = Verdadero. mientras(pasos < nmero de elementos del arreglo) AND (intercambio == Verdadero) intercambio = Falso. para ndice = (primer ndice del Arreglo) hasta (ltimo ndice del Arreglo - pasos) si A[ndice] > A[ndice + 1] Permuta(A[ndice], A[ndice + 1]. intercambio = Verdadero. pasos = pasos + 1. Fin. El algoritmo de clasificacin por burbuja hace algunos pasos a travs del arreglo, comparando valores adyacentes durante cada paso. Los valores adyacentes se intercambian si el primer valor es ms grande que el segundo. El proceso termina cuando se han hecho los pasos n 1 (en donde n es el nmero de elementos en el arreglo) o cuando no son posibles ms intercambios. Su trabajo es codificar el algoritmo anterior como una funcin C++ de nombre clasifPorBur() Adems, tendr que codificar una funcin permuta() que se pueda llamar por
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-74

MIGUEL . TOLEDO MARTNEZ

medio de la funcin clasifPorBur() para intercambiar dos elementos del arreglo como se muestra en el algoritmo. Escriba sus funciones para clasificar un arreglo de caracteres. Incorprelas dentro de un programa para que verifique el procedimiento de clasificacin. Por qu la clasificacin por burbuja es menos eficiente que la clasificacin por insercin? 21. Otro algoritmo de clasificacin iterativa comn es clasificacin por seleccin. El algoritmo es como ste: clasifPorSelec() Inicio para indice1 = (primer ndice del arreglo) hasta (ultimo ndice del arreglo) hacer posicin = indice1. masPequeno = A[Posicion]. para indice2 = (indice1 + 1) hasta (ultimo ndice del arreglo) hacer si A[indice2] < masPequeno posicion = indice2. masPequeno = A[posicion]. A[posicion] = A[indice1]. A[indice1] = masPequeno. Fin. Como en la clasificacin por burbuja, la clasificacin por seleccin realiza diversos pasos a travs del arreglo. En el primero de ellos examina al arreglo completo y coloca los elementos ms pequeos en la primera posicin del arreglo. En el segundo paso se examina el arreglo empezando en el segundo elemento. Se encuentra el elemento ms pequeo en el segmento del arreglo y se coloca en la segunda posicin del arreglo. El tercer paso examina el arreglo empezando en el tercer elemento, encuentra el elemento ms pequeo en el segmento del arreglo y lo coloca en la tercera posicin del elemento. El proceso contina hasta que no quedan ms segmentos del arreglo. Su trabajo es codificar el algoritmo anterior como una funcin C++ de nombre clasifPorSelec() Escriba su funcin para clasificar un arreglo de caracteres. Despus sela en un programa que verifique el procedimiento de clasificacin. Por qu la clasificacin por seleccin es menos eficiente que la clasificacin por insercin? 22. Escriba un programa que tome un arreglo entero sin ordenar y encuentre la localizacin del valor mximo en el arreglo. (Sugerencia: copie el arreglo dentro de otro y clasifique este segundo arreglo para determinar su valor mximo. Despus busque el arreglo original para este valor)

Problemas de recursividad
23. (Ordenamiento por seleccin) El ordenamiento por seleccin busca en un arreglo el elemento ms pequeo, el cual se intercambia con el primero del arreglo. El proceso se repite con el subarreglo que comienza en el segundo elemento del arreglo. Cada pasada por el arreglo da como resultado la colocacin de un elemento en su lugar correcto. El desempeo de este ordenamiento es comparable con el ordenamiento de burbuja: para un arreglo de n elementos, se necesita hacer n-1 pasadas y por cada subarreglo, hay que hacer n-1 comparaciones para encontrar el valor ms pequeo. Cuando el subarreglo que se est procesando slo contiene un elemento, el arreglo est ordenado. Escriba la funcin recursiva clasifOrdenamiento() 24. (Palndromos) Un palndromo es una cadena que se pronuncia igual hacia delante que hacia atrs. Algunos ejemplos son: radar, anilina y dbale arroz a la zorra el abad. Escriba una funcin recursiva pruebaPalindrome() que devuelva verdadero si la cadena almacenada en el arreglo es un palndromo y falso si no. La funcin deber ignorar los espacios y la puntuacin en la cadena. 25. (Bsqueda lineal) Modifique el ejemplo 18.33 para que emplee la funcin recursiva busquedaBinaria() para llevar a cabo una bsqueda lineal en el arreglo. La funcin deber recibir como argumentos un arreglo de enteros y su tamao. Si se encuentra la clave de bsqueda, devuelva el ndice del arreglo; de otro modo, devuelva 1. 26. (Bsqueda binaria) Modifique el programa del ejemplo 18.34 para que utilice una funcin recursiva busquedaBinaria() que lleve a cabo una bsqueda binaria en el arreglo. La funcin deber recibir como argumentos un arreglo de enteros y el ndice inicial y el final. Si se encuentra la clave de bsqueda, devuelva el ndice del arreglo; de otro modo, devuelva 1.
ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-75

MIGUEL . TOLEDO MARTNEZ

27. (Impresin de un arreglo) Escriba una funcin recursiva imprimirArreglo() que tome como argumentos un arreglo y su tamao y no devuelva nada. La funcin deber terminar el proceso y regresar cuando reciba un arreglo de tamao cero. 28. (Impresin inversa de una cadena) Escriba una funcin recursiva cadenaInvertida() que tome un arreglo de caracteres que contenga como argumento una cadena, la imprima al revs y no devuelva nada. La funcin deber terminar el proceso y regresar cuando se encuentre el carcter nulo de terminacin. 29. (Encuentre el valor mnimo dentro de un arreglo) Escriba una funcin recursiva minimoRecursivo() que tome como argumentos un arreglo de enteros y su tamao y devuelva su elemento ms pequeo. La funcin deber terminar el proceso y regresar cuando reciba un arreglo de 1 elemento

EXAMEN BREVE 34
1. Los dos componentes principales de un arreglo son: ______________ y ___________. 2. Verdadero o falso: Los elementos dentro de un arreglo determinado pueden ser de cualquier combinacin de clase de datos.

EXAMEN BREVE 35
Defina un arreglo de nombre registrosDeExamen que almacene hasta 15 registros de exmenes. Cul es la dimensin del arreglo en la pregunta 1? Cul es el ndice del primer elemento del arreglo en la pregunta 1? Cul es el ndice del ltimo elemento del arreglo en la pregunta 1? Defina un arreglo de nombre esteSemestre que almacene elementos de una clase enumerada de nombre cursos, que incluya los cursos que usted est tomando este semestre. 6. Suponga que el ndice del ltimo elemento en un arreglo es [25] Cuntos elementos almacenar el arreglo? 1. 2. 3. 4. 5.

EXAMEN BREVE 36
1. Escriba un ciclo for que llene el siguiente arreglo desde la entrada del usuario: char caracteres[15]; 2. Escriba un ciclo for que muestre el contenido del arreglo de la pregunta 1.

EXAMEN BREVE 37
1. Verdadero o falso: el nombre del arreglo es la direccin del ndice[1] del arreglo. 2. Escriba un prototipo para una funcin de nombre muestra() que modifique al siguiente arreglo: char caracteres[15]; Suponga que la funcin no regresa ningn valor excepto el arreglo modificado. 3. Escriba un prototipo para una funcin de nombre prueba() que modifique un solo elemento del arreglo que se defini en la pregunta 2. 4. Escriba un enunciado que llamar a la funcin prototipo elaborada en la pregunta 3 para modificar el elemento almacenado en el ndice[5] del arreglo definido en la pregunta 2.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-76

MIGUEL . TOLEDO MARTNEZ

EXAMEN BREVE 38
1. Defina un arreglo e inicialcelo con los valores enteros de -3 hasta +3. 2. Cul es la dimensin del arreglo que defini en la pregunta 1? 3. Muestre el contenido del siguiente arreglo:
char lenguaje[51 = {C, +, +};

4. Muestre el contenido del siguiente arreglo:


char lenguaje[] = " C++";

5. Suponga que define globalmente un arreglo de caracteres sin valores de iniciacin. Qu almacena el compilador en el arreglo?

RESPUESTA EXAMEN BREVE 34


1. Los dos componentes principales de un arreglo son: indice y elemento. 2. Falso: Todos los elementos dentro de un arreglo deben de ser de la misma clase de datos.

RESPUESTA EXAMEN BREVE 35


1. 2. 3. 4. 5.
float registrosDeExamen[15];

La dimensin del arreglo de la pregunta 1 es 1 15. El ndice del primer elemento del arreglo de la pregunta 1 es [0] El ndice del ltimo elemento en el arreglo de la pregunta 1 es [14]
enum cursos {Computacion, Matematicas, Fsica, Ingles, Oratoria}; cursos esteSemestre[5];

6. El arreglo almacenar 26 elementos, dado que el primer ndice de elemento es [0]

RESPUESTA EXAMEN BREVE 36


1. El ciclo for que se necesita para llenar el arreglo char caracteres[15]; es:
for(int indice = 0; indice < 15; ++indice) cin >> caracteres[indice];

2. El ciclo for que mostrar el contenido del arreglo anterior es:


for(int indice = 0; indice < 15; ++indice) cout << caracteres[indice] << \t;

RESPUESTA EXAMEN BREVE 37


1. Falso: El nombre del arreglo se localiza en el ndice[0] del mismo. 2. Un prototipo para una funcin llamada muestra() que debe modificar el arreglo char caracteres[15] es:
void muestra(char caracteres[15]);

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-77

MIGUEL . TOLEDO MARTNEZ

3. Un prototipo para una funcin llamada prueba() que modificar slo un elemento en el arreglo de la pregunta 2 es:
void prueba(char &elementoDelArreglo);

4. Un enunciado que llamar a la funcin anterior para modificar el elemento almacenado en el ndice[5] del arreglo en la pregunta 2 es:
prueba(caracteres[5]);

RESPUESTA EXAMEN BREVE 38


1. La definicin de un arreglo inicializado con los valores enteros de 3 a +3 es:
int numeros[7] = [-3, -2, -1, 0, 1, 2, 3}; o int numeros[] = [-3, -2, -1, 0, 1, 2, 3};

2. La dimensin del arreglo antes mencionado es 1 x 7. 3. El contenido del arreglo char lenguaje[51 = {C, +, +}; es:
[C] [+] [+] [\0] [\0]

4. El contenido del arreglo char lenguaje[] = "C++"; es;


[C] [+] [+] [\0]

5. Un carcter terminador nulo (\0) se coloca en cada posicin de un arreglo de caracteres definido globalmente sin ningn valor de inicializacin.

ARREGLOS, APUNTADORES Y ESTRUCTURAS LECCIN 18

18-78

You might also like