Anda di halaman 1dari 109

FACULTAD DE INDUSTRIAL Y SISTEMA

Separata
Estructura y Algoritmos de Datos II

Prof. Ing. Alberto Moreno 2013

INDICE
1.- Funciones Sintaxis de las funciones Parmetros por referncia y valor Recursividad

2.- Arrays Unidimesionales y Bidimensionales Definicin Operaciones con arreglos Metodos de Ordenacin Operaciones con bidimensionales Ejercicios propuestos 3.- Estructuras Definicin Arreglos con estructuras Ejercicios propuestos

4.- Punteros Definicin Arreglos de punteros Ejercicios propuestos 5.-Gestion dinamica de memoria Definicin Manejo de pilas y colas Ejercicios propuestos 6.- Listas Enlazadas Representacin de una Lista simple y Doble Operciones de insercin, eliminacin y modificacion. Listas simples y dobles Ejercicios propuestos Profesor: Ing. Alberto Moreno

CAPITULO 1.- FUNCIONES

Tiempo de vida de los datos Segn el lugar donde son declaradas puede haber dos tipos de variables. Globales: las variables permanecen activas durante todo el programa. Se crean al iniciarse ste y se destruyen de la memoria al finalizar. Pueden ser utilizadas en cualquier funcin. Locales: las variables son creadas cuando el programa llega a la funcin en la que estn definidas. Al finalizar la funcin desaparecen de la memoria. Si dos variables, una global y una local, tienen el mismo nombre, la local prevalecer sobre la global dentro de la funcin en que ha sido declarada. Dos variables locales pueden tener el mismo nombre siempre que estn declaradas en funciones diferentes.

/* Variables globales y locales. */ #include <iostream.h> int num1=1; void main() /* Escribe dos cifras */ { int num2=10; cout<<num1<<endl; cout<<num2;

}
Funciones Las funciones son bloques de cdigo utilizados para dividir un programa en partes ms pequeas, cada una de las cules tendr una tarea determinada. Su sintaxis es:

tipo_funcin nombre_funcin (tipo y nombre de argumentos) { bloque de sentencias } tipo_funcin: puede ser de cualquier tipo de los que conocemos. El valor devuelto por la funcin ser de este tipo. Por defecto, es decir, si no indicamos el tipo, la funcin devolver un valor de tipo entero ( int ). Si no queremos que retorne ningn valor deberemos indicar el tipo vaco ( void ).

nombre_funcin: es el nombre que le daremos a la funcin. tipo y nombre de argumentos: son los parmetros que recibe la funcin. Los argumentos de una funcin no son ms que variables locales que reciben un valor. Este valor se lo enviamos al hacer la llamada a la funcin. Pueden existir funciones que no reciban argumentos. bloque de sentencias: es el conjunto de sentencias que sern ejecutadas cuando se realice la llamada a la funcin. Las funciones pueden ser llamadas desde la funcin main o desde otras funciones. Nunca se debe llamar a la funcin main desde otro lugar del programa. Por ltimo recalcar que los argumentos de la funcin y sus variables locales se destruirn al finalizar la ejecucin de la misma. 1.3.- Declaracin de las funciones Al igual que las variables, las funciones tambin han de ser declaradas. Esto es lo que se conoce como prototipo de una funcin. Para que un programa en C sea compatible entre distintos compiladores es imprescindible escribir los prototipos de las funciones. Los prototipos de las funciones pueden escribirse antes de la funcin main o bin en otro fichero. En este ltimo caso se lo indicaremos al compilador mediante la directiva #include. En el ejemplo adjunto podremos ver la declaracin de una funcin ( prototipo ). Al no recibir ni retornar ningn valor, est declarada como void en ambos lados. Tambin vemos que existe una variable global llamada num. Esta variable es reconocible en todas las funciones del programa. Ya en la funcin main encontramos una variable local llamada num. Al ser una variable local, sta tendr preferencia sobre la global. Por tanto la funcin escribir los nmeros 10 y 5. /* Declaracin de funciones. */ #include <iostream.h> void funcion(void); /* prototipo */ int num=5; /* variable global */ void main() /* Escribe dos nmeros */ { int num=10; /* variable local */ cout<<num<<endl; funcion(); /* llamada */ } void funcion(void){ cout<<num; } Paso de parmetros a una funcin Como ya hemos visto, las funciones pueden retornar un valor. Esto se hace mediante la instruccin return, que finaliza la ejecucin de la funcin, devolviendo o no un valor. En una misma funcin podemos tener ms de una instruccin return. La forma de retornar un valor es la siguiente: return ( valor o expresin );

El valor devuelto por la funcin debe asignarse a una variable. De lo contrario, el valor se perder. En el ejemplo puedes ver lo que ocurre si no guardamos el valor en una variable. Fjate que a la hora de mostrar el resultado de la suma, en el cout, tambin podemos llamar a la funcin.

/* Paso de parmetros. */ #include <iostream.h> int suma(int,int); /* prototipo */ void main() /* Realiza una suma */ { int a=10,b=25,t; t=suma(a,b); /* guardamos el valor */ cout<<"a+b=<<t; } int suma(int a,int b){ return (a+b); } Ahora veremos lo que se conoce como paso de parmetros. Existen dos formas de enviar parmetros a una funcin: Por valor: cualquier cambio que se realice dentro de la funcin en el argumento enviado, NO afectar al valor original de las variables utilizadas en la llamada. Es como si trabajaramos con una copia, no con el original. No es posible enviar por valor arrays, deberemos hacerlo por referencia. Por referencia: lo que hacemos es enviar a la funcin la direccin de memoria donde se encuentra la variable o dato. Cualquier modificacin SI afectar a las variables utilizadas en la llamada. Trabajamos directamente con el original. /* Paso por valor. */ #include <iostream.h> void intercambio(int,int); void main() /* Intercambio de valores */ { int a=1,b=2; cout<<"a=<<a<<endl; cout<<b=<<b<<endl; intercambio(a,b); /* llamada */ cout<<a<< , <<b; } void intercambio (int x,int y) { int aux; aux=x; x=y; y=aux; cout<<"a=<<x<<endl; cout<<b=<<y<<endl;

}
Para enviar un valor por referencia se utiliza el smbolo & ( ampersand ) delante de la variable enviada. Esto le indica al compilador que la funcin que se ejecutar tendra que obtener la direccin de memoria en que se encuentra la variable. Vamos a fijarnos en los ejemplos. En el ejemplo anterior podrs comprobar que antes y despus de la llamada, las variables mantienen su valor. Solamente se

modifica en la funcin intercambio ( paso por valor ). En el siguiente ejemplo podrs ver como las variables intercambian su valor tras la llamada de la funcin ( paso por referencia ). Las variables con un * son conocidas como punteros, el nico dato en 'C' que puede almacenar una direccin de memoria.

/* Paso por referencia. */ #include <iostream.h> void intercambio(int *,int *); void main() /* Intercambio de valores */ { int a=1,b=2; cout<<"a=a<<endl; cout<<b=<<b<<endl; intercambio(&a,&b); /* llamada */ } void intercambio (int *x,int *y) { int aux; aux=*x; *x=*y; *y=aux; cout<<"a=<<*x<< , <<b=<<*y;

}
Los argumentos de la funcin main Ya hemos visto que las funciones pueden recibir argumentos. Pues bin, la funcin main no poda ser menos y tambin puede recibir argumentos, en este caso desde el exterior. Los argumentos que puede recibir son: argc: es un contador. Su valor es igual al nmero de argumentos escritos en la lnea de comandos, contando el nombre del programa que es el primer argumento. argv: es un puntero a un array de cadenas de caracteres que contiene los argumentos, uno por cadena. En este ejemplo vamos a ver un pequeo programa que escribir un saludo por pantalla (Programa : ARGUMENTO.C). /* Argumentos de la main. */ #include <iostream.h> main(int argc,char *argv[]) /* argumentos */ { cout<<"\nCurso de Programacin en C\n"; cout<<"Programa de ejemplo.\n\n"; if (argc<2) { cout<<"Teclee: ARGUMENTO su_nombre"; exit(1); /* fin */ } cout<<"Hola:<<argv[1];

} La declaracin de las funciones mediante los prototipos suele hacerse alcomienzo del fichero, despus de los #include.

Llamada:La llamada a una funcin se hace incluyendo su nombre en una expresin o sentencia del programa principal o de otra funcin. Este nombre debe ir seguido de una lista de argumentos separados por comas y encerrados entre parntesis. A los argumentos incluidos en la llamada se les llama argumentos actuales, y pueden ser no slo variables y/o constantes, sino tambin expresiones.

Sobrecarga de Funciones:Casi siempre es recomendable dar nombresdistintos a funciones diferentes, pero que pasa cuando las tareas a realizar sonlas mismas pero con diferentes tipos de datos? En este caso es msconveniente darle a las funciones el mismo nombre, pero con argumentos dedistinto tipo, que sern los que permitan al compilador llamar a una u otrafuncin.

Paso de argumentos por valor: Hasta ahora los ejemplos que hemos visto hanutilizado este mecanismo. La llamada por valor significa que una copia delargumento se pasa al parmetro de la funcin. Esto significa que todo lo que serealice en el cdigo de la funcin no va a alterar el valor del argumento usadopara llamar a la funcin.

En el ejemplo, al pasar como argumento la variable r, se hace una copia en la variableradio, la cual es una variable local de la funcin AreaCirculo, por lo tanto los cambiosrealizados sobre esta variable no afectan a la del programa principal. Paso de argumentos por Referencia:Es el mecanismo de pasar argumentosmediante las direcciones en lugar de valores. Debe utilizarse siempre y cuando lafuncin deba devolver argumentos modificados. Un caso de particular inters esel paso de arrays (vectores, matrices y cadenas de caracteres). Los argumentos formalesdeben ser declarados como punteros a los argumentos actuales, quesern las direcciones.

VARIABLES LOCALES Y VARIABLES GLOBALES


Como se discuti en clase, cuando uno llama una funcin, no es necesario saber los tipos y los nombres de las variables que se declaran en la definicin de dicha funcin. Simplemente se requiere de conocer el tipo de los argumentos que necesita y el tipo de valor que regresa. Esto se debe a que en C++ las variables que se definen en las funciones son independientes de las variables que se definen en la funcin main (programa principal) o en cualquier otra funcin. Si se declara una variable en una funcin y se declara otra variable con el mismo nombre en la funcin principal del programa (main), estas dos variables, aunque tengan el mismo nombre, se consideran como dos variables diferentes. Observe el siguiente ejemplo:

la variable cuadrado se declara tanto en la funcin main como en la funcin square y la declaracin es idntica: double cuadrado; Sin embargo, la variable cuadrado de la funcin main y la variable cuadrado de la funcin square se consideran como dos variables diferentes.

Ejemplo
//Programa para el calculo del area de un circulo y el volumen de una esfera //usando dos funciones. Se usa el mismo valor de radio para los dos calculos. #include <iostream.h> #include <math.h> constdoublePI = 3.14159; /* Tiene alcance global. Se coloca por debajo de los include y antes de los prototipos */ /* Prototipos */ doublearea_circulo(double radio); double volumen_esfera(double radio); int main( ) { doubleradio_de_ambos, area, volumen; /*Alcance local*/ cout<<Dame el radio del circulo y de la esfera \n; cin>>radio_de_ambos; area = area_circulo(radio_de_ambos); volumen = volumen_esfera(radio_de_ambos); cout<<El area del circulo es <<area<<\n; cout<<El volumen de la esfera es <<volumen<<\n; cout<<\n; system(PAUSE); return 0; }

/*Observe que las dos funciones siguientes usan la constante global PI*/ /* Funcion para el calculo del area de un circulo */ doublearea_circulo(double radio) { doublearea; /* Alcance local, diferente de la variable definida en main */ area = PI * pow(radio, 2.0); /* Uso de constante global */ returnarea; } /* Funcion para el calculo del volumen de una esfera */ double volumen_esfera(double radio) { double volumen; /*Alcance local, diferente de la variable definida en main*/ volumen = (4.0/3.0) * PI * pow(radio, 3.0); return volumen; /* Uso de constante global */ }

PROBLEMAS PROPUESTOS 1
1. Especifique el resultado que se obtiene al ejecutar el siguiente programa. #include <iostream.h> void velresult (int distancia, int tiempo ) { float vel; vel = (float) distancia / tiempo; cout<<La velocidad Kmph:<<vel; } void main ( ) { int distancia, tiempo; distancia = 100; tiempo = 2; velresult (distancia, tiempo); velresult (400, 10); } 2. Escriba una funcin llamada bisuma que calcule la suma de dos variables num1 y num2 enteras y regrese un resultado entero. Escriba una funcin llamada media_de_3 que reciba como parmetro un dato entero y lo divida entre 3. Suponga que el dato enviado a la funcin es el total de sumar 3 nmeros, por lo que el resultado de esta funcin ser la media de los 3 datos. Escriba un programa completo que lea tres valores enteros para las variables a, b, c, que enseguida invoque a las funciones bisuma y media_de_3 de los ejercicios anteriores y que, por ltimo, despliegue el valor promedio de los tres datos con un mensaje apropiado. Qu cambios necesitara realizar a las funciones para obtener el promedio de ms de 3 datos? Escriba una funcin llamada cuadrado que tenga un parmetro de entrada llamado longitud y entregue como resultado el permetro del cuadrado cuyo lado sea la longitud especificada y su rea. Todas las variables son reales. Escriba una funcin llamada magnitud que tenga cuatro parmetros de entrada llamados x1, x2, y1, y2 y que entregue como resultado la distancia entre dos puntos cuyas coordenadas son (x1, y1) y (x2, y2) segn la siguiente frmula:

3.

4.

5.

6.

dist
7.

( y2

y1 ) 2

( x2

x1 ) 2

Un piso rectangular que mide 12 metros por 15 metros est cubierto parcialmente por tapetes circulares. El radio de un tapete es un metro. El radio del otro es de dos metros. Escriba un programa que encuentre el rea de la parte del piso que est descubierta. El programa deber tener: a) Una funcin que reciba como parmetro el radio de un crculo y que regrese el valor del rea de ese crculo. Suponga que el radio y el rea son reales.

b)

Una funcin con dos parmetros reales que calcule el rea de un rectngulo de base y altura dadas.

8.

Escriba una funcin llamada digfinal que tenga un parmetro de entrada llamado nmero y que entregue como resultado el dgito de las unidades del nmero. Por ejemplo, si el nmero es 234, el resultado es 4. Escribe una funcin que tome 3 parmetros: dos de tipo enteros y uno de tipo carcter. La funcin deber sumar, restar, multiplicar o dividir los valores de los dos primeros parmetros dependiendo del cdigo indicado en el tercer parmetro, y devolver el resultado. Escribe una funcin que devuelva el (a) factorial, (b) n-simo nmero de Fibonacci, de su argumento. Escribe una funcin que diga si sus dos argumentos son mltiplo el uno del otro (no importa cul de cul). Escribe una funcin que devuelva si su argumento n es o no es primo. NOTA: Tener en cuenta que basta con probar la divisibilidad por los nmeros desde el 2 hasta la n . Lo cual ahorra muchas operaciones. Si adems consideramos que basta con saber si es par o no al principio, podemos ahorrarnos la mitad de las pruebas de divisores, eliminando todos los pares. Por fin una ltima mejora, importante, es eliminar los mltiplos de tres.

9.

10. 11. 12.

13. 14.

Escribe una funcin que devuelva el n-smo nmero primo (1 es el primero), recibiendo n como argumento. Escribe una funcin que escriba los nmeros primos hasta el numero que se le pasa como parmetro.

RECURSIVIDAD
Definicin
Propiedad que tienen los mtodos de poder ser re-invocados sin haber finalizado el proceso de las sentencias correspondientes a una invocacin previa de si mismo. El concepto deriva del de Relacin Recurrente. En toda relacin recurrente / proceso recursivo se distinguen dos partes bien diferenciadas: Caso Base Caso Recursivo : aquel que queda definido en si mismo. : basado en un caso base o en otro caso recursivo.

Tipos de Recursividad

Directa : es aquella en la que la invocacin recursiva se efecta desde dentro del mismo mtodo invocado. Mtodo 1

Indirecta : es aquella donde la invocacin recursiva la efecta un segundo mtodo. mtodo 1 mtodo 2

-15-

Se dice que algo es recursivo si se define en funcin de s mismo o a s mismo. Tambin se dice que nunca se debe incluir la misma palabra en la definicin de sta. El caso es que las definiciones recursivas aparecen con frecuencia en matemticas, e incluso en la vida real. Tipos Mtodos recursivos tipo void Mtodos recursivos que retornan valor

-16-

-17-

-18-

-19-

Metodos recursivos que retornan valor


void metodoRecursivo (parmetros) { if(condicin) return metodoRecursivo(parmetros); else return valor }

-20-

-21-

-22-

- El factorial: n!, de un nmero natural (incluido el 0): (1) si n = 0 entonces: 0! = 1 (2) si n > 0 entonces: n! = n (n-1)! Asimismo, puede definirse un programa en trminos recursivos, como una serie de pasos bsicos, o paso base (tambin conocido como condicin de parada), y un paso recursivo, donde vuelve a llamarse al programa. En un computador, esta serie de pasos recursivos debe ser finita, terminando con un paso base. Es decir, a cada paso recursivo se reduce el nmero de pasos que hay que dar para terminar, llegando un momento en el que no se verifica la condicin de paso a la recursividad. Ni el paso base ni el paso recursivo son necesariamente nicos.

Cundo utilizar la recursin?


Tampoco se debe utilizar cuando la solucin iterativa sea clara a simple vista. Sin embargo, en otros casos, obtener una solucin iterativa es mucho ms complicado que una solucin recursiva, y es entonces cuando se puede plantear la duda de si merece la pena transformar la solucin recursiva en otra iterativa. Aunque parezca mentira, es en general mucho ms sencillo escribir un programa recursivo que su equivalente iterativo. Si el lector no se lo cree, posiblemente se deba a que no domine todava la recursividad. Se propondrn diversos ejemplos de programas recursivos de diversa complejidad para acostumbrarse a la recursin. Ejercicio La famosa sucesin de Fibonacci puede definirse en trminos de recurrencia de la siguiente manera: (1) Fib(1) = 1 ; Fib(0) = 0 (2) Fib(n) = Fib(n-1) + Fib(n-2) si n >= 2 Cuantas llamadas recursivas se producen para Fib(6)?. Codificar un programa que calcule Fib(n) de forma iterativa. Nota: no utilizar estructuras de datos, puesto que no queremos almacenar los nmeros de Fibonacci anteriores a n; s se permiten variables auxiliares. - Dados dos nmeros a (nmero entero) y b (nmero natural mayor o igual que cero) determinar a^b. int potencia(int a, int b) { if (b == 0) return 1; else return a * potencia(a, b-1); } La condicin de parada se cumple cuando el exponente es cero. Por ejemplo, la evaluacin de potencia(-2, 3) es: potencia(-2, 3) -> (-2) potencia(-2, 2) -> (-2) (-2) potencia(-2, 1) -> (-2) (-2) (-2) potencia(-2, 0) ->

-23-

(-2) (-2) (-2) 1 y a la vuelta de la recursin se tiene: (-2) (-2) (-2) 1 /=/ (-2) (-2) (-2) potencia(-2,0) < (-2) (-2) (-2) /=/ (-2) (-2) potencia(-2, 1) < (-2) 4 /=/ (-2) potencia(-2,2) < -8 /=/ potencia(-2,3) en negrita se ha resaltado la parte de la expresin que se evala en cada llamada recursiva. Planteamiento: Ejercicio 1. Programar un algoritmo recursivo que calcule el factorial de un nmero. Solucin: Cdigo int factorial(int n){ if(n==0) return 1; //AXIOMA else return n*factorial(n-1); }

//FORMULA RECURSIVA

Planteamiento: Ejercicio 2. Programar un algoritmo recursivo que calcule un nmero de la serie fibonacci. Solucin: Cdigo int fibonaci(int n){ if(n==1 || n==2) return 1; else return fibonaci(n-1)+fibonaci(n-2); }

Planteamiento: Ejercicio 3. Programar un algoritmo recursivo que permita hacer la

-24divisin por restas sucesivas. Solucin: Cdigo int division (int a, int b) { if(b > a) return 0; else return division(a-b, b) + 1; }

Planteamiento: Ejercicio 4. Programar un algoritmo recursivo que permita invertir un nmero. Ejemplo: Entrada: 123 Salida: 321 Solucin: Cdigo int invertir (int n) { if (n < 10) //caso base return n; else return (n % 10) + invertir (n / 10) * 10; } Planteamiento: Ejercicio 5. Programar un algoritmo recursivo que permita sumar los dgitos de un nmero. Ejemplo: Entrada: 123 Resultado:6 Solucin: Cdigo int sumar_dig (int n) { if (n == 0) //caso base return n; else return sumar_dig (n / 10) + (n % 10); }

-25-

Planteamiento: Ejercicio 6. Programar un algoritmo recursivo que permita hacer una multiplicacin, utilizando el mtodo Ruso. Para mas informacion: aqui. Solucin: Cdigo int mult_rusa(int A, int B) { if(A==1){ return (B); } if(A%2!=0){ return(B+mult_rusa( A/2 , B*2)); } else{ return(mult_rusa( A/2 , B*2)); } }

Planteamiento: Ejercicio 7. Programar un algoritmo recursivo que permita sumar los elementos de un vector. Solucin: Cdigo int suma_vec(int v [], int n) { if (n == 0) return v [n]; else return suma_vec(v, n - 1) + v [n]; }

Planteamiento:

-26-

Ejercicio 8. Programar un algoritmo recursivo que permita multiplicar los elementos de un vector. Solucin: Cdigo int multiplicar (int vec [], int tam) { if (tam == 0) return (vec [0]); return (vec [tam] * multiplicar (vec, tam - 1)); }

Planteamiento: Ejercicio 9. Programar un algoritmo recursivo que calcule el Maximo comun divisor de dos nmeros. Solucin: Cdigo int sacar_mcd(int a, int b) { if(b==0) return a; else return sacar_mcd(b, a % b); }

Planteamiento: Ejercicio 10. Programar un algoritmo recursivo que determine si un nmero es positivo. Solucin: Cdigo public bool positivo(int n){ if(n>0) return true; else return negativo(n);

-27} public bool negativo(int n){ if(n<0) return false; else return positivo(n); }

Planteamiento: Ejercicio 11. Programar un algoritmo recursivo que determine si un nmero es impar utilizando recursividad cruzada. Solucin: Cdigo public boolean par(int n){ if(n==0) return true; else return impar(n-1); } public boolean impar(int n){ if(n==0) return false; else return par(n-1); }

Planteamiento: Ejercicio 12. Programar un algoritmo recursivo que permita sumar los elementos de una matriz. Solucin: Cdigo int suma (int fila, int col, int orden, int (*mat )[5]) { if (fila == 0 && col == 0) return mat [0] [0]; else if (col < 0) return suma (fila - 1, orden, orden, mat); else

-28return mat [fila] [col] + suma (fila, col - 1, orden, mat); }

Ejercicio 14. Programar un algoritmo recursivo que permita resolver la siguiente matriz: 1 1 1 1 1 1 2 2 2 2 1 2 4 4 4 1 2 4 8 8 1 2 4 8 16

EJERCICIOS Ejercicio 1: Escriba una definicin recursiva de una funcin que tiene un parmetro n de tipo entero y que devuelve el n-simo nmero de Fibonacci. Los nmeros de Fibonacci se definen de la siguiente manera: F0 = 1 F1 = 1 Fi+2 = Fi + Fi+1 Ejercicio 2 La forma para calcular cuantas maneras diferentes tengo para elegir r cosas distintas de un conjunto de n cosas es: C(n,r) = n! (r!*(n-r)!) Donde la funcin factorial se define como n! = n *(n-1)*(n-2)**2*1 Descubra una versin recursiva de la frmula anterior y escriba una funcin recursiva que calcule el valor de dicha frmula. Ejercicio 3 Escriba una funcin recursiva que ordene de menor a mayor un arreglo de enteros basndose en la siguiente idea: coloque el elemento ms pequeo en la primera ubicacin, y luego ordene el resto del arreglo con una llamada recursiva. Ejercicio 4

-29Escribir una funcin recursiva que devuelva la suma de los primeros N enteros Ejercicio 5 Escribir un programa que encuentre la suma de los enteros positivos pares desde N hasta 2. Chequear que si N es impar se imprima un mensaje de error. Ejercicio 6 Escribir un programa que calcule el mximo comn divisor (MCD) de dos enteros positivos. Si M >= N una funcin recursiva para MCD es MCD = M si N =0 MCD = MCD (N, M mod N) si N <> 0 El programa le debe permitir al usuario ingresar los valores para M y N desde la consola. Una funcin recursiva es entonces llamada para calcular el MCD. El programa entonces imprime el valor para el MCD. Si el usuario ingresa un valor para M que es < que N el programa es responsable de switchear los valores. Ejercicio 7 Programe un mtodo recursivo que transforme un nmero entero positivo a notacin binaria. Ejercicio 8 Programe un mtodo recursivo que transforme un nmero expresado en notacin binaria a un nmero entero. Ejercicio 9 Programe un mtodo recursivo que calcule la suma de un arreglo de nmeros enteros. Ejercicio 10 Programe un mtodo recursivo que invierta los nmeros de un arreglo de enteros. Ejercicio 11 Cul es el resultado de esta funcin para distintos valores de X? Static int f(int x) { if (x >100) { return (x-10); } else { return(f(f(x+11))); } } Ejercicio 12 Implemente una funcin recursiva que nos diga si una cadena es palndromo.

-30Ejercicio 13 Disee e implemente un algoritmo que imprima todas las posibles descomposiciones de un nmero natural como suma de nmeros menores que l. 1= 1 2 = 1+1 3= 2 + 1 3= 1+1+1 4= 3+1 4= 2+1+1 4 = 1+1+1+1 4=2+2 4=2+1+1 4=1+1+1+1 N = (n-1) +1 N = (n-2) + 2 = (n-2) + 1 + 1

CAPITULO 2.- ARRAYS


Un array es un identificador que referencia un conjunto de datos del mismo tipo. Imagina un tipo de dato int; podremos crear un conjunto de datos de ese tipo y utilizar uno u otro con slo cambiar el ndice que lo referencia. El ndice ser un valor entero y positivo. En C los arrays comienzan por la posicin 0. Vectores Un vector es un array unidimensional, es decir, slo utiliza un ndice para referenciar a cada uno de los elementos. Su declaracin ser: tipo nombre [tamao]; El tipo puede ser cualquiera de los ya conocidos y el tamao indica el nmero de elementos del vector ( se debe indicar entre corchetes [ ] ). En el ejemplo puedes observar que la variable i es utilizada como ndice, el primer for sirve para rellenar el vector y el segundo para visualizarlo. Como ves, las posiciones van de 0 a 9 ( total 10 elementos ).

/* Declaracin de un array. */ #include <iostream.h> void main() /* Rellenamos del 0 - 9 */ { int vector[10],i; for (i=0;i<10;i++) vector[i]=i; for (i=0;i<10;i++) cout<<vector[i]<<endl;

-31} Podemos inicializar (asignarle valores) un vector en el momento de declararlo. Si lo hacemos as no es necesario indicar el tamao. Su sintaxis es: tipo nombre []={ valor 1, valor 2...} Ejemplos: int vector[]={1,2,3,4,5,6,7,8}; char vector[]="programador"; char vector[]={'p','r','o','g','r','a','m','a','d','o','r'}; Una particularidad con los vectores de tipo char (cadena de caracteres), es que deberemos indicar en que elemento se encuentra el fin de la cadena mediante el caracter nulo (\0). Esto no lo controla el compilador, y tendremos que ser nosotros los que insertemos este caracter al final de la cadena. Por tanto, en un vector de 10 elementos de tipo char podremos rellenar un mximo de 9, es decir, hasta vector[8]. Si slo rellenamos los 5 primeros, hasta vector[4], debemos asignar el caracter nulo a vector[5]. Es muy sencillo: vector[5]='\0'; . Ahora veremos un ejemplo de como se rellena un vector de tipo char. /* Vector de tipo char. */ #include <iostream.h> void main() /* Rellenamos un vector char */ { char cadena[20]; int i; for (i=0;i<19 && cadena[i-1]!=13;i++) cadena[i]=getche( ); if (i==19) cadena[i]='\0'; else cadena[i-1]='\0'; cout<<cadena<<endl; } Podemos ver que en el for se encuentran dos condiciones: 1.- Que no se hayan rellenado todos los elementos (i<19). 2.- Que el usuario no haya pulsado la tecla ENTER, cuyo cdigo ASCII es 13. (cadena[x-i]!=13). Tambin podemos observar una nueva funcin llamada getche( ), que se encuentra en conio.h. Esta funcin permite la entrada de un caracter por teclado. Despus se encuentra un if, que comprueba si se ha rellenado todo el vector. Si es cierto, coloca el caracter nulo en el elemento n20 (cadena[19]). En caso contrario tenemos el else, que asigna el caracter nulo al elemento que almacen el caracter ENTER.

-32-

En resumen: al declarar una cadena deberemos reservar una posicin ms que la longitud que queremos que tenga dicha cadena. Llamadas a funciones con arrays Como ya se coment en el tema anterior, los arrays nicamente pueden ser enviados a una funcin por referencia. Para ello deberemos enviar la direccin de memoria del primer elemento del array. Por tanto, el argumento de la funcin deber ser un puntero. /* Envo de un array a una funcin. */ #include <iostream.h> void visualizar(int []); /* prototipo */ void main() /* rellenamos y visualizamos */ { int array[25],i; for (i=0;i<25;i++) { cout<<"Elemento:"<<(i+1)<<:; cin>>array[i]; } visualizar(&array[0]); } void visualizar(int array[]) /* desarrollo */ { int i; for (i=0;i<25;i++) cout<<array[i]<<endl; } En el ejemplo se puede apreciar la forma de enviar un array por referencia. La funcin se poda haber declarado de otra manera, aunque funciona exactamente igual:

declaracin o prototipo

void visualizar(int *); void visualizar(int *array)

desarrollo de la funcin

Matrices Una matriz es un array multidimensional. Se definen igual que los vectores excepto que se requiere un ndice por cada dimensin. Su sintaxis es la siguiente: tipo nombre [tamao 1][tamao 2]...;

-33Una matriz bidimensional se podra representar grficamente como una tabla con filas y columnas. La matriz tridimensional se utiliza, por ejemplo, para trabajos grficos con objetos 3D. En el ejemplo puedes ver como se rellena y visualiza una matriz bidimensional. Se necesitan dos bucles para cada una de las operaciones. Un bucle controla las filas y otro las columnas. /* Matriz bidimensional. */ #include <iostream.h> void main() /* Rellenamos una matriz */ { int x,i,numeros[3][4]; /* rellenamos la matriz */ for (x=0;x<3;x++) for (i=0;i<4;i++) cin>>numeros[x][i]; /* visualizamos la matriz */ for (x=0;x<3;x++) for (i=0;i<4;i++) cout<<numeros[x][i]<<endl; } Si al declarar una matriz tambin queremos inicializarla, habr que tener encuenta el orden en el que los valores son asignados a los elementos de la matriz. Veamos algunos ejemplos: int numeros[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; quedaran asignados de la siguiente manera: numeros[0][0]=1 numeros[0][1]=2 numeros[0][2]=3 numeros[0][3]=4 numeros[1][0]=5 numeros[1][1]=6 numeros[1][2]=7 numeros[1][3]=8 numeros[2][0]=9 numeros[2][1]=10 numeros[2][2]=11 numeros[2][3]=12 Tambin se pueden inicializar cadenas de texto: char dias[7][10]={"lunes","martes","mircoles","jueves","viernes","sbado", "domingo"}; Para referirnos a cada palabra bastara con el primer ndice: cout<<dias[i]);

PROGRAMAS DE APLICACIN - ARRAY


1. METODO DE ORDENAMIENTO POR BURBUJA /*Programa que realiza una ordenacion por el metodo de la burbuja*/

-34-

#include <iostream.h> #include <conio.h> #define N 100 /*Maximo de elementos en el arreglo*/ void main() { int a[N];/*Declaracion del arreglo unimensional*/ int i,j,aux,sw,n; cout<<" tamao del vector "; cin>>&n;/*Tamao del arreglo en el programa*/ cout<<"\n Valores del vector :\n"; for (i=0; i<n; i++) cin>>a[i]);/*lectura de elementos que estaran en el arreglo*/ i=1; sw=0;/*variable para interrumpir el ordenamiento cuando ya esta ordenado el arreglo*/ aux=0;/*variable auxiliar para el intercambio de valores del arreglo*/ while (sw!=1){ sw=1; for (j=0; j<=n-i; j++) { if (a[j] > a[j+1]) {/*obtiene el elemento a ordenar*/ aux=a[j]; /*copia el valor en la posicion actual a la variable auxiliar*/ a[j]=a[j+1];/*copia el valor de la posicion siguiente a la posicion actual*/ a[j+1]=aux; /*copia al valor de la variable auxiliar a la posicion siguiente*/ sw=0; } } i=i+1; } cout<<"El vector ordenado es :\n"; for (i=0; i<n; i++) cout<<(a[i]<<endl;/*impresion de los elementos en el arreglo en forma ordenada*/ getch(); return(0); }

-352.- METODO DE ORDENAMIENTO POR INSERCION

/*Metodo de Ordenacion por Insercion*/ #include <iostream.h> #include <conio.h> #define N 100/*Elementos maximos en el arreglo*/ main () { int a[N];/*declaracion del arreglo*/ int i, n, p, u; int k, j, c, aux; cout<<"Total de elementos del vector :"; cin>> n;/*Total de elementos en el arreglo*/ cout<<"Valores del vector :\n"; for (i=1; i<=n; i++) cin>>a[i]);/*lectura y almacenamiento de los elementos en el arreglo*/ aux=0;/*variable auxiliar para copiar los elementos*/ c=0;/*nueva posicion en el arreglo*/ for (k=2; k<=n; k++){ aux=a[k];/*copia el elemento de la posicion k del arreglo a una variable auxiliar*/ p=1;/*posicion a partir del cual empezara a comparar los elementos*/ u=k-1;/*posicion en el arreglo*/ while (p<=u){/*compara las posiciones*/ c=(p+u)/2;/*obtiene la nueva posicion del arreglo para comparar*/ if (aux < a[c])/*compara el contenido del arreglo en la nueva posicion y el valor de la variable auxiliar(elemento)*/ u=c-1;/*decrementa la posicion del arreglo*/ else p=c+1;/*incrementa la posicion del arreglo en uno*/ } for (j=k-1 ;j>=p; j--)/*busca la posicion del elemento a cambiar*/ a[j+1]=a[j];/*cambia el elemento en el arreglo que esta contenido en aux por el nuevo elemento*/ a[p] = aux;/*cambia el elemento contenido en la posicion p del arreglo por el elemento contenido en aux y empieza a ordenar el arreglo*/ } cout<<"\n El vector ordenado es: \n"; for (i = 1; i<=n; i++) cout<<a[i]<<endl;/*impresion del arreglo ordenado/ getch(); return 0;

-363.- ORDENAMIENTO POR SELECCIN

/*Metodo de Ordenacion por Seleccion*/ #include "iostream.h" #include "conio.h" #define N 100 /*Maximo de elementos*/ void main() { int a[N];/*Declaracion del arreglo*/ int i, j, k, menor, n; cout<<"Introduzca el tamao del vector \n \n"; cin>>n;/*Total de elemetos en el arreglo*/ cout<<"\n Introduce los elementos \n"; for (i=0; i<n; i++) cin>>a[i];/*Lee y almacene los elementos en el arreglo*/ for (i=0; i<n-1; i++) { menor=a[i];/*obtiene el elemento en la posicion actual a i*/ k=i;/*k toma la posicion i*/ for (j=i+1; j<n; j++){/*empieza a recorrer el arreglo una posicion adelante a la de i*/ if (a[j] < menor){/*si el elemento en la posicion j del arreglo es menor que el elemento contenido en menor*/ menor=a[j]; /*menor toma el elemento contenido en j*/ k=j;/*k toma la posicion j*/ } } a[k]=a[i];/*almacena en la posicion k del arreglo el elemento contenido en la posicion i del arreglo*/ a[i]=menor;/*almacena el elemento contenido en menor en el arreglo en la posicion i*/ } cout<<"\t El vector ordenado es \n"; for (i=0; i<n; i++) cout<<a[i]<<endl;/*imprime el arreglo ordenado*/ getch(); } return 0;

-374.- ORDENAMIENTO POR METODO SHELL

/*Metodo de Ordenacion por Shell*/ #include <iostream.h> #include <conio.h> #define N 100/*Maximo de elementos*/ void main() { int a[N];/*declaracion del arreglo*/ int i, j, k, aux, inc, n; cout<<"Introduzca el tamao del vector \n \n"; cin>>n);/*tamao del arreglo*/ cout<<"\n Introduce los elementos \n"; for (i=1; i<=n; i++) cin>>a[i];/*lee y almacena los elementos en el arreglo*/ inc=n/2;/*obtiene el valor de incremento para empezar a ordenar*/ while (inc>0) { for (i=inc+1; i<=n; i++) { j=i-inc;/*obtiene la posicion inicial del arreglo*/ while (j>0){ if (a[j] > a[j+inc]){/*obtiene el mayor de los elementos*/ aux=a[j];/*alamacena en la variable auxiliar aux el elemento mayor*/ a[j]=a[j+inc];/*copia el elemento menor a la posiscion en donde se encontraba el elemento mayor*/ a[j+inc]=aux;/*copia elemento mayor contenido en aux a la posicion del arreglo en donde se encontraba el elemento menor*/ j=j-inc;/*decrementa la posicion del arreglo*/ } else j=0; } } inc=inc/2;/*obtiene el valor de incrementos para empezar a ordenar*/ } cout<<"\t El vector ordenado es \n"; for (i=1; i<=n; i++) cout<<a[i]<<endl;/*Imprime el arreglo ordenado*/ getch(); return 0;

-385.- Metodo de Ordenacion por Quick Short

#include <iostream.h> #include <conio.h> #define N 100 /*maximo de elementos*/ #define M 50 /*mitad de elementos que N*/ main(){ int mayor[M]={0}, /*arreglo auxiliar*/ menor[M]={0}, /*arreglo auxiliar*/ a[N]={0};/*arreglo principal*/ int aux, /*variable auxiliar para intercambio de elementos*/ n, /*tamao del arreglo*/ ban; int der, /*posicion a la derecha*/ izq, /*posicion a la izquierda*/ top; /*tope del arreglo*/ int ini, /*posicion inicio*/ fin, /*posicion final*/ pos, /*posicion*/ i; cout<<"Introduzca el tamao del vector \n \n"; cin>>n);/*lee el tamao del arreglo*/ cout<<"valores para el vector: \n \n"; for (i=1; i<=n; i++) cin>>a[i];/*lee y almacena los elementos en el arreglo principal*/ top=1; /*inicio del tope del arreglo*/ menor[top]=1; /*almacena el valor 1 en la posicion top del arreglo menor*/ mayor[top]=n; /*almacena el valor de n(tamao del arreglo) en la posicion top del arreglo mayor*/ while (top > 0) {/*Mientras la posicion top sea mayor que 0*/ ini=menor[top];/*ini toma el elemento contenido en la posicion top del arreglo menor*/ fin=mayor[top];/*fin toma el elemento contenido en la posicion top del arreglo mayor*/ top--;/*decrementa la posicion top menos uno*/ izq=ini;/*izq toma el valor de ini*/ der=fin;/*der toma el valor de fin*/ pos=ini;/*pos toma el valor de ini*/ ban=1;/*variable de desicion a ordenar toma el valor 1*/ while (ban){/*mientras ban valga 1*/ while ((a[pos]<=a[der]) && (pos!=der))/*disminuye el valor de der si el valor del elemento en a[pos] es menor*/ der--; /*que a[der] y ademas pos es diferente que der*/

-39if (pos==der)/*si las posiciones son iguales*/ ban=0; /*cambia el valor de ban*/ else{/*hace el cambio de elementos*/ aux=a[pos];/*aux toma el valor mayor contenido en la posicion pos del arreglo*/ a[pos]=a[der];/*el arreglo en la posicion pos almacena el valor menor contenido en la posicion derecha*/ a[der]=aux;/*el arreglo en la posicion der toma el elemento mayor contenido en aux*/ pos=der;/*la variable de posicion pos toma el valor de la nueva posicion contenida en der*/ while ((a[pos] >= a[izq]) && (pos != izq)) /*mientras el elemento contenido en la posicion pos del arreglo sea mayor o igual*/ izq++; /*que el elemento contenido en la posicion izq del arreglo y el valor de pos sea diferente del valor de izq incrementa el valor de izq mas uno*/ if (pos==izq) /*si las posiciones son iguales cambia el valor de ban*/ ban=0; else{ /*si el valor contenido en la posicion pos es menor que el contenido en la posicion izq del arreglo hace el cambio*/ aux=a[pos]; /*aux toma el elemento menor contenido en la posicion pos del arreglo*/ a[pos]=a[izq]; /*se almacena el elemento mayor contenido en la posicion izq en la posicion pos del arreglo*/ a[izq]=aux; /*se almacena el elemento menor contenido en aux en la posicion izq del arreglo*/ pos=izq; /*pos toma la nueva posicion del arreglo almacenada en izq*/ } } } if (ini<(pos-1)){ /*si el valor de la posicion ini es menor que el valor de la posicion pos-1*/ top++;/*se incrementa el valor de la posicion top mas uno*/ menor[top]=ini; /*almacena el valor de la posicion ini en la posicion top del arreglo menor*/ mayor[top]=pos-1; /*almacena el valor de la posicion pos-1 en la posicion top del arreglo mayor*/ } if (fin>(pos+1)){ /*si el valor de la posicion fin es mayor que el valor de la posicion pos+1*/ top++;/*incrementa el valor de la posicion top mas uno*/ menor[top]=pos+1; mayor[top]=fin; }

-40} cout<"El vector ordenado es :\n"; for (i=1; i<=n; i++) cout<<a[i]<<endl;/*imprime el arreglo ordenado*/ getch(); return 0; }

-41PROBLEMAS PROPUESTOS DE ARREGLOS UNIDIMENSIONALES


1. Una fbrica de llantas quiere un programa para calcular el costo total de produccin de los n modelos de llantas que produce. Los datos con que cuenta son los siguientes: n, ao, a1, ..., an-1, c0, c1, con: 1 n 50, entero ai enteros ci enteros ..., cn-1,

Donde: ai ci 2. representa la cantidad de llantas producidas del modelo i representa el costo de produccin de una llanta del modelo i

Se tienen los siguientes datos: n, ic0, ic1, ..., icn-1 con: 1 n 32, entero ici reales

Donde: ici representa el ingreso per cpita de cada entidad federativa de la Repblica Mexicana. Elabore una funcin para calcular e imprimir el ingreso per cpita promedio de la Repblica, as como para escribir cuntas entidades tienen un ingreso menor que este promedio y cuntas lo tienen mayor o igual. 3. Sean los datos: n, x1, x2, . . . , xn con: 1 n 25, entero xi reales

Elabore un programa que realice funciones por cada inciso y la funcin principal que las mande llamar e imprima los resultados: a) b) Lea los datos y almacene los xi en un arreglo. Calcule e imprima la media de los datos dada por la frmula:

i 1

xi

-42c) Calcule e imprima la desviacin estndar dada por la frmula:


n

( xi a
i 1

x) 2

4.

Una compaa ha clasificado a sus n (1 n 50) empleados dentro de los grupos 1 y 2. Cada empleado del grupo 1 recibir, a partir de ahora, un aumento de $250.00 a la semana sobre su sueldo actual, mientras que a cada uno de los del grupo 2 slo se le dar $150.00 adicionales por semana. La informacin que se proporciona de cada empleado es: clave del empleado (comprendida entre 100 y 2500, inclusive), grupo al que pertenece (1 o 2) y sueldo semanal actual (entre $300.00 y $6000.00). Si un empleado del grupo 1 con el nuevo sueldo gana semanalmente ms que el sueldo promedio del grupo, entonces debe cambiar al grupo 2. Elabore un programa modular que: a) b) c) Lea la informacin de los n empleados e imprima la clave, grupo y sueldo semanal nuevo para cada empleado, actualizando el grupo si es el caso. Calcule el sueldo promedio de los empleados por grupo y calcule tambin el promedio general de todos, sin considerar el grupo. Indique cuntos empleados cambiaron del grupo 1 al 2.

5.

Se tienen n alumnos (1 n 50) de los cuales se conoce la clave y la calificacin final. Elabore un programa modular que: a) b) c) Lea dicha informacin, la cual se da ya ordenada en forma descendente, con respecto a la clave. Imprima la clave y calificacin de todos los alumnos que obtuvieron calificacin superior al promedio del grupo. Imprima la calificacin que obtuvieron los alumnos cuyas claves proporcionar el usuario. Se sabr que el usuario ya no quiere conocer ms calificaciones cuando, en lugar de una clave, proporcione un cero. Utilice bsqueda binaria para buscar las claves que el usuario solicita.

6.

Se tiene un conjunto de n parejas de datos Xi, Yi donde cada pareja representa las coordenadas del punto i de un polgono irregular de n lados. Suponga que las coordenadas se proporcionarn en orden adyacente. Elabore una funcin para leer el nmero de lados del polgono, leer las coordenadas de los puntos y obtener el rea del polgono irregular utilizando la siguiente frmula: Area = [(X0+X1)*(Y0-Y1 ) + (X1+X2)*(Y1-Y2)+. . .+ (Xn-1+X0)*(Yn-1-Y0) /2 Suponga que los Xi ,Yi son reales y n es entero con 1 n 50.

-437. Elabore una serie de funciones para leer una serie de n datos desordenados, almacenarlos en el arreglo val (de mximo 50 localidades), ordenarlos de manera creciente, utilizando el algoritmo de seleccin directa, en ese mismo arreglo y, por ltimo, imprimirlos en orden. val 0 vo Variante: 8. 1 v1 2 v2 . . n-1 vn-1 49 ...

En el arreglo final no debe haber datos repetidos.

Partiendo del ejercicio anterior, elabore un programa que contenga funciones para: a) Buscar un valor x dentro del arreglo utilizando el algoritmo de bsqueda secuencial. La funcin debe regresar como resultado la posicin en la que se encuentra el valor buscado. Si x no se encuentra en el arreglo, la funcin calcula la posicin en la que debera encontrarse y regresa: (posicin 1). Buscar un valor x dentro del arreglo utilizando el algoritmo de bsqueda binaria. Insertar un valor x en el arreglo de tal forma que se siga conservando el orden ascendente de los valores. Al insertar se debe verificar que haya espacio libre y que x no exista en el arreglo. La funcin debe regresar como resultado 1 si se insert x en el arreglo, 0 si x ya exista en el arreglo y 1 si no existe espacio libre en el arreglo. Eliminar un valor x del arreglo, compactando si es necesario para que no haya espacios libres entre valores. La funcin debe regresar como resultado 1 si se elimin x, 0 si x no se encontraba en el arreglo y 1 si el arreglo estaba vaco. Sustituir un valor x ya existente en el arreglo con un valor y de tal manera que el arreglo siga conservando su orden creciente. La funcin debe regresar como resultado 1 si se hizo la sustitucin, 0 si x no se encontraba en el arreglo y 1 si el arreglo estaba vaci.

b) c)

d)

e)

9.

Elabore un programa modular que lea dos arreglos de diferente nmero de elementos, los ordene y posteriormente los mezcle en un tercer arreglo guardando el orden. Restriccin: no se deben unir los arreglos en desorden, ni copiar un arreglo completo, es decir, los elementos que se almacenen en el tercer arreglo se deben ir guardando en orden.

10.

Elabore un programa modular para leer un arreglo cuyos datos se proporcionan en orden ascendente, leer un segundo arreglo cuyos datos se proporcionan en orden descendente, mezclarlos en un tercer arreglo cuyos datos aparezcan en orden ascendente, y por ltimo, imprimir el arreglo resultante.

-4411. Elabore un programa modular que lea los datos de dos polinomios como se explica posteriormente y que, utilizando un men, efecte las siguientes operaciones sobre polinomios: a) b) c) Suma. Resta. Multiplicacin.

Al seleccionar el usuario una de estas tres opciones dar los polinomios sobre los cuales se realizar la operacin solicitada. Los datos que el usuario proporcionar son los coeficientes (reales) y los exponentes (enteros, 0 y 15) de ambos polinomios, los cuales pueden o no estar ordenados. El final de cada polinomio est dado por un 1 como coeficiente y como exponente. Los trminos del polinomio resultante debern ser desplegados en orden descendente, observando el siguiente formato: cX ^e Donde: c ^ e representa el signo del trmino representa el coeficiente del trmino significa exponenciacin representa el valor del exponente

Por ejemplo, suponga que los datos son: 2.5 -2 3 2 -4 -3 2 4 6.5 9.1 1 1 3 6.9 4 8 -1 -1 -1 -1

Entonces, los polinomios que se van a operar son: +2.5X3 - 4X2 + 6.5X1 + 3X4 -2X2 - 3X4 + 9.1X1 + 6.9X8 De tal forma que el resultado de la suma es: 6.9X8 + 2.5X3 - 6X2 + 15.6X1 y se desplegara como: + 6.9X^8 + 2.5X^3 - 6X^2 + 15.6X^1 12. Dado un nmero natural n de 4 cifras, no todas iguales, encuentre e imprima el nmero mayor y el menor que se puede formar con las mismas cifras. Por ejemplo, si n = 6174, entonces el nmero mayor que se puede formar es 7641 y el menor 1467.

-4513. Elabore un programa que utilizando la criba de Eratstenes encuentre los nmeros primos entre 1 y 999, la cual funciona como sigue: a) Inicialice todos los elementos de un arreglo (comenzando en el ndice 2), de 1000 enteros, con 1 (verdadero). Los elementos con ndices 0 y 1 deben inicializarse con 0 (falso). Comience con el ndice i=2 del arreglo. Recorra el arreglo, del elemento i+1 al ltimo, y cada vez que encuentre un elemento cuyo valor sea 1, pngale 0 si su ndice es mltiplo de i. Vuelva a hacer lo mismo, pero ahora considerando el primer elemento que sea 1 y cuyo ndice sea mayor a i. Contine este proceso hasta que haya probado todos los elementos iguales a 1.

b)

Cuando se haya terminado este proceso, los ndices del arreglo cuyos elementos sean 1 son primos. 14. En estadstica, la moda de una serie de nmeros es aquel nmero que aparece con ms frecuencia. Por ejemplo, dada la lista 1,2,2,3,6,4,7,5,4,6,9,4, la moda es 4, ya que aparece tres veces. Calcule e imprima la moda. Si todos los nmeros son diferentes entonces no hay moda, con lo cual se debe indicar que hubo error. Haga un programa completo en C que deber tener una funcin que lea la serie de nmeros, otra funcin que reciba como parmetro la serie de nmeros y arroje la moda o si no la hay 1 y la funcin principal que mande llamar las anteriores e imprima la moda (nmero que mas veces se repiti en caso de haber dos iguales o ms mencione el primero). Una cooperativa de productores de naranjas almacena el total de toneladas cosechadas durante el ltimo ao en N parcelas (1 N 50). En cada parcela se pueden cultivar dos tipos de naranjas: para jugo y para comer. Se conoce el total de toneladas cosechadas de cada uno de los tipos de naranjas. Si en una parcela no se hubiera cosechado alguno de los tipos, entonces habr 0. La informacin se almacena en un arreglo como se muestra en el siguiente ejemplo:

15.

Naranjas para Naranjas para jugo comer

100

500

600 2

0 3

800 4

700 5

...
2N-2 2N-1 Parcela N

...
MAX - 1

0 1 Parcela 1

Parcela 2

Parcela 3

-46En la parcela 1 se cosecharon: 100 toneladas de naranjas para jugo y 500 toneladas de naranjas para comer. En la parcela 2 se cosecharon: 600 toneladas de naranjas para jugo y 0 toneladas de naranjas para comer. NOTA: Observe que la informacin de una misma parcela ocupa posiciones consecutivas en el arreglo. Se le pide que haga un programa en C, usando mdulos, que pueda: a) Leer la informacin: N (1 N 50) y las toneladas por tipo de naranja de cada una las parcelas. b) Calcular e imprimir el total de la produccin por parcela. c) Eliminar la informacin de una parcela. El dato requerido para esta opcin es el nmero de parcela a eliminar. d) Buscar e imprimir el nmero de una parcela (si hubiera) que no haya tenido produccin de ninguno de los tipos de naranjas. Es decir, durante el ltimo ao su produccin total fue 0.

-47PROBLEMAS PROPUESTOS DE MATRICES 3


1. 2. Elabore un programa modular que lea una matriz de enteros de m renglones y n columnas y calcule la suma de los elementos de cada columna. Elabore un programa modular que lea una matriz de m X n y la escriba poniendo las columnas como renglones y los renglones como columnas. Por ejemplo, si la matriz que da el usuario es: 4 2 3 7 0 1 1 6 2 3 9 6 5 7 4

entonces el programa debe escribir la matriz transpuesta: 4 7 1 3 5 3. 2 0 6 9 7 3 1 2 6 4

Elabore una funcin que reciba como entrada un entero n y una matriz cuadrada (n x n) de enteros e imprima los elementos que conforman su diagonal. Elabore una funcin que reciba como entrada un entero n y una matriz cuadrada (n x n) de enteros e imprima los elementos que conforman la diagonal que inicia en la esquina superior derecha y termina en la esquina inferior izquierda. Una matriz cuadrada A se dice que es simtrica si A(i, j) = A(j, i) para todo i, j dentro de los lmites de la matriz. Elabore una funcin que lea una matriz y regrese un 1 (uno) si es simtrica o un 0 (cero) no. Elabore una funcin que lea una matriz de enteros de m X n (1 < n, m 50) y otra funcin que encuentre el menor y el mayor valor y regrese sus posiciones. Resuelva el siguiente sistema de ecuaciones lineales: 2 x 2y + z = 1 -x + y + z = 0 -x +3y + 5z = 0

4.

5.

6. 7.

-488. Una empresa automotriz tiene cinco agencias y cuenta con la informacin acerca de las ventas mensuales de automviles logradas el ao pasado por cada una de stas. A partir de estos datos la empresa construy la siguiente matriz ventas: Lomas Enero Febrero ... Noviembre Diciembre Elabore un programa modular para contestar las siguientes preguntas: a) b) c) d) 9. 10. Cul fue el total de ventas en el ao de la agencia Lomas? Cul fue el promedio de ventas en el mes de diciembre? Qu agencia tuvo mayores ventas en el mes de mayo? En qu mes se registraron las menores ventas del ao, considerando todas las agencias? Vallejo Perisur del Valle Oriente

Elabore un programa modular que genere las tablas de multiplicar del 1 al 10 en un solo arreglo de dos dimensiones y posteriormente imprima dicho arreglo. Los resultados de las elecciones de un pas se esquematizaron en una matriz como la que se muestra a continuacin. e s t a d o s La matriz almacena el nmero de votos que obtuvo cada partido en el estado correspondiente, as como los votos anulados en cada estado. Se desea conocer: a) b) Total de votos de cada partido. Total de votos por estado, para comparar con una tabla que indica el nmero de personas que deben votar por estado con el fin de detectar en qu estados vot menos del 60% de la poblacin electora y tomar as medidas de concientizacin cvica. P1 Edo.0 Edo.2 ... Edo.31 P2 partidos P3 P4 P5 P6 P0(votos anulados)

Nmero de personas que deben votar por estado:

Edo.0

Edo.2

...

Edo.31

-49c) d) Qu partido obtuvo el mayor nmero de votos en el cuarto estado? Cul es el estado con mayor nmero de abstenciones y cul es el estado con mayor porcentaje de abstenciones? Debe ser forzosamente el mismo estado en ambos casos?

11.

Se tienen los resultados de las ltimas elecciones a gobernador en el estado X, el cual est conformado por 5 municipios. En dichas elecciones hubo 4 candUTPos.

Elabore un programa que: a) b) c) d) Lea e imprima una tabla indicando los votos obtenidos en cada municipio por los 4 candUTPos. Calcule el total de votos recibidos por cada candUTPo y el porcentaje del total de votos emitidos. Calcule el candUTPo ms votado. Si un candUTPo recibi ms del 50% de los votos, indicar que es el ganador. Si ningn candUTPo recibi ms del 50% de los votos, el programa debe imprimir los dos candUTPos ms votados, que sern los que pasen a la segunda ronda de las elecciones.

12.

Una agencia automotriz distribuye quince modelos diferentes de coches y tiene diez vendedores. Se desea un programa que escriba un informe mensual de las ventas por vendedor y modelo, as como el nmero de automviles vendidos por cada vendedor y el nmero total de cada modelo vendido por todos los vendedores. Asimismo, para entregar el premio al mejor vendedor, necesita saber cul es el vendedor que ms coches ha vendido.

Los datos se proporcionan por da (30 das), todos los vendedores informan la cantidad de coches que vendieron de cada modelo ese da, el final de datos de las ventas del da se conoce por un 0. Los vendedores no necesariamente informan sus ventas en orden, ni por orden de vendedor ni de modelo. 13. El IFE te encarg un programa en C para poder contar los votos del 2 de junio. La informacin de todos los electores del pas viene dada de la siguiente forma: estado, -1 , partido : -1

donde: estado: representa el estado del elector (0 <= estado < 32) partido: representa el partido por el que voto el elector (0<= partido < 6) a) En un arreglo bidimensional de tamao apropiado, guarda la suma de los votos obtenidos por cada partido en cada estado. Los renglones representan los estados y las columnas los partidos. b) Indica cuntas personas votaron en cada estado.

-50c) Determina cul fue el partido por el que ms personas votaron en el pas. d) Dados como parmetros una matriz cuadrada de enteros y n, se pide un mdulo llamado paralelo que imprima de cada paralela superior al diagonal principal, el valor mximo y de cada paralela inferior al diagonal principal, el valor mnimo. 14. Los resultados de un torneo de futbol de 16 equipos se encuentran almacenados en la tabla itorn de 16 renglones por 16 columnas. Por renglones se tienen los goles que un equipo anot a los dems, y por columnas se tienen los goles que dicho equipo recibi de los dems. Por ejemplo: Para un torneo de 4 equipos se tiene la siguiente tabla: 1 2 3 0 2 0 2 1 3 4 1 1 4 0 2 0 -

1 2 3 4

Se puede decir que los marcadores del equipo 1 fueron: Perdi Gan Empat 0 2 con el equipo 2. 4 3 con el equipo 3. 0 0 con el equipo 4.

Anot 4 goles y recibi 5 goles en el torneo. Se pide que elabore un solo programa que realice lo siguiente: a) b) c) d) 15. Lea la tabla itorn con los resultados del torneo. Imprima los marcadores de los partidos jugados por el equipo 1, indicando contra quin jug y si gan, perdi o empat cada partido. Imprima los goles a favor y los goles en contra del equipo 1. Imprima cul es el equipo con mayor nmero de partidos ganados (suponga que un solo equipo cumple con esta caracterstica).

Una compaa de transportes que tiene sucursales en 20 ciudades de la Repblica, quiere saber la distancia que recorre un chofer al ir de una ciudad a otra. Los datos referentes a las distancias estn indicados como se muestra a continuacin:

0 dist1,0 dist2,0 dist19,0 Donde:

dist0,1 0 dist2,1 dist19,1

dist0,2 dist1,2 0 dist19,2

. . . . .

. . . . .

. . . . .

dist0,19 dist1,19 dist2,19 0

-51disti, j > 0 disti, j = 0 representa que hay carretera de la ciudad i a la ciudad j y la distancia existente entre ambas ciudades. si i diferente a j, representa que no hay carretera entre la ciudad i y la ciudad j.

Se le pide que elabore un programa para: e) f) g) Leer la tabla de distancias, determinando usted la mejor disposicin de los datos. (slo es necesario leer una parte de la matriz) Leer la ciudad de origen a y la ciudad destino b. Encontrar la distancia que recorre el chofer al ir de la ciudad a a la ciudad b. Si no existe carretera directa, entonces deber encontrar una ciudad intermedia c, para hacer el recorrido de la ciudad a a la ciudad c y de la ciudad c a la cuidad b. Si no existe ninguna ruta posible para llegar de a a b, deber escribir un mensaje. De otro modo, escriba el total de kilmetros recorridos para llegar al destino. Si hay varias ciudades intermedias entre a y b, encuentre la ruta ms corta.

h) i)

16.

Una fbrica de bombas hidrulicas tiene una matriz con los insumos necesarios para la produccin de un conjunto de motores. Por ejemplo, suponiendo que la planta produce 7 motores y se utilizan 8 insumos en diferentes cantidades para su produccin, la matriz sera: Insumos 1 10 0 5 10 4 0 20 2 20 70 10 20 0 6 18 3 30 0 15 10 8 9 0 4 40 50 0 20 0 12 14 5 0 40 10 10 6 15 0 6 60 30 15 0 8 0 10 7 10 0 5 10 4 1 8 8 80 10 0 20 0 24 6

M o t o r e s

1 2 3 4 5 6 7

Analizando la matriz anterior, podramos ver que para producir un motor del tipo 3 es necesario utilizar 5 unidades del insumo 1, 10 unidades del insumo 2, 15 unidades del insumo 3, 10 unidades del insumo 5, 15 unidades del insumo 6 y 5 unidades del insumo 7. Por otro lado se tiene un arreglo con los costos unitarios en pesos de cada insumo: Costo de Insumos 1 3.5 2 0.1 3 2.0 4 1.5 5 6.0 6 4.2 7 2.5 8 1.3

Se tiene otro arreglo con los pedidos a surtir en el presente mes: Pedidos del mes de cada motor

-52-

1 100

2 25

3 75

4 150

5 80

6 90

7 10

Tambin se tiene un ltimo arreglo con la existencia actual de cada uno de los insumos: Existencia de Insumos 1 120 2 0 3 20 4 60 5 40 6 90 7 10 8 0

Elabore un programa para: a) b) c) d) e) f) g) Leer el nmero m de motores que fabrica la planta (mximo 50). Leer el nmero n de insumos necesarios para la fabricacin de los motores (mximo 50). Leer los datos de la matriz de Insumos/Motor. Leer los datos del arreglo de costos unitarios de insumos. Leer los datos del arreglo de pedidos del mes de cada motor. Leer los datos del arreglo de insumos existentes en la planta. Obtener e imprimir un arreglo de m elementos, con el costo de produccin de cada motor. Suponga que el costo de produccin de un motor consiste en sumar el producto de insumos necesarios por el costo unitario de cada insumo. Obtener e imprimir un arreglo de n elementos, con la cantidad de unidades de cada insumo, necesaria para cumplir con los pedidos del mes. Obtener e imprimir un arreglo de n elementos, cuyos datos indiquen cul es el costo total por concepto de cada insumo para cumplir con los pedidos del mes. Obtenga e imprima el costo total (tomando en cuenta todos los insumos) para cumplir con la produccin del mes. Obtenga e imprima un arreglo de n elementos, con la diferencia de los insumos necesarios para la produccin mensual menos los insumos existentes en la planta, con el fin de poder surtir dichos insumos a tiempo.

h) i) j) k)

-53-

CAPITULO 3.- ESTRUCTURAS


Concepto de estructura Una estructura es un conjunto de una o ms variables, de distinto tipo, agrupadas bajo un mismo nombre para que su manejo sea ms sencillo. Su utilizacin ms habitual es para la programacin de bases de datos, ya que estn especialmente indicadas para el trabajo con registros o fichas. La sintaxis de su declaracin es la siguiente: struct tipo_estructura { tipo_variable nombre_variable1; tipo_variable nombre_variable2; tipo_variable nombre_variable3; }; Donde tipo_estructura es el nombre del nuevo tipo de dato que hemos creado. Por ltimo, tipo_variable y nombre_variable son las variables que forman parte de la estructura. Para definir variables del tipo que acabamos de crear lo podemos hacer de varias maneras, aunque las dos ms utilizadas son stas: Una forma de definir la estructura: struct trabajador { char nombre[20]; char apellidos[40]; int edad; char puesto[10]; }; struct trabajador fijo, temporal; Otra forma: struct trabajador { char nombre[20]; char apellidos[40]; int edad; char puesto[10]; }fijo, temporal; En el primer caso declaramos la estructura, y en el momento en que necesitamos las variables, las declaramos. En el segundo las declaramos al mismo tiempo que la estructura. El problema del segundo mtodo es que no podremos declarar ms variables de este tipo a lo largo del programa. Para poder declarar una variable de tipo

-54estructura, la estructura tiene que estar declarada previamente. Se debe declarar antes de la funcin main. El manejo de las estructuras es muy sencillo, as como el acceso a los campos ( o variables ) de estas estructuras. La forma de acceder a estos campos es la siguiente: variable.campo; Donde variable es el nombre de la variable de tipo estructura que hemos creado, y campo es el nombre de la variable que forma parte de la estructura. Lo veremos mejor con un ejemplo basado en la estructura del captulo 13.1: temporal.edad=25; Lo que estamos haciendo es almacenar el valor 25 en el campo edad de la variable temporal de tipo trabajador. Otra caracterstica interesante de las estructuras es que permiten pasar el contenido de una estructura a otra, siempre que sean del mismo tipo naturalmente: fijo=temporal; Al igual que con los otros tipos de datos, tambin es posible inicializar variables de tipo estructura en el momento de su declaracin: struct trabajador fijo={"Pedro","Hernndez Surez", 32, "gerente"}; Si uno de los campos de la estructura es un array de nmeros, los valores de la inicializacin debern ir entre llaves: struct notas { char nombre[30]; int notas[5]; }; struct notas alumno={"Carlos Prez",{8,7,9,6,10}}; Estructuras y funciones Podemos enviar una estructura a una funcin de las dos maneras conocidas: 1.- Por valor: su declaracin sera: void visualizar(struct trabajador); Despus declararamos la variable fijo y su llamada sera: visualizar(fijo); Por ltimo, el desarrollo de la funcin sera:

-55void visualizar(struct trabajador datos) /* Paso de una estructura por valor. */ #include <iostream.h> struct trabajador { char nombre[20]; char apellidos[40]; int edad; char puesto[10]; }; void visualizar(struct trabajador); main() /* Rellenar y visualizar */ { struct trabajador fijo; cout<<"Nombre: "; cin>>fijo.nombre; cout<<"\nApellidos: "; cin>>fijo.apellidos; cout<<"Edad: "; cin>>&fijo.edad; cout<<Puesto: "; cin>>fijo.puesto; visualizar(fijo); } void visualizar(struct trabajador datos) { cout<<("Nombre:"<<datos.nombre<<endl; cout<<"Apellidos:"<<datos.apellidos<<endl; cout<<"Edad:"<<datos.edad<<endl; cout<<"Puesto:"<<datos.puesto<<endl; } 2.- Por referencia: su declaracin sera: void visualizar(struct trabajador *); Despus declararemos la variable fijo y su llamada ser: visualizar(&fijo); Por ltimo, el desarrollo de la funcin ser: void visualizar(struct trabajador *datos)

-56Fjate que en la funcin visualizar, el acceso a los campos de la variable datos se realiza mediante el operador ->, ya que tratamos con un puntero. En estos casos siempre utilizaremos el operador ->. Se consigue con el signo menos seguido de mayor que. /* Paso de una estructura por referencia. */ #include <iostream.h> struct trabajador { char nombre[20]; char apellidos[40]; int edad; char puesto[10]; }; void visualizar(struct trabajador *); void main() /* Rellenar y visualizar */ { struct trabajador fijo; cout<<"Nombre: "; cin>>fijo.nombre; cout<<"Apellidos: "; cin>>fijo.apellidos; cout<<"Edad: "; cin>>&fijo.edad; cout<<"Puesto: "; cin>>fijo.puesto; visualizar(&fijo); } void visualizar(struct trabajador *datos) { cout<<"Nombre:"<<datos->nombre<<endl; cout<<"Apellidos:"<<datos->apellidos<<endl; cout<<"Edad:"<<datos->edad<<endl; cout<<"Puesto:"<<datos->puesto; } Arrays de estructuras Es posible agrupar un conjunto de elementos de tipo estructura en un array. Esto se conoce como array de estructuras: struct trabajador { char nombre[20]; char apellidos[40]; int edad; }; struct trabajador fijo[20];

-57As podremos almacenar los datos de 20 trabajadores. Ejemplos sobre como acceder a los campos y sus elementos: para ver el nombre del cuarto trabajador, fijo[3].nombre;. Para ver la tercera letra del nombre del cuarto trabajador, fijo[3].nombre[2];. Para inicializar la variable en el momento de declararla lo haremos de esta manera: struct trabajador fijo[20]={{"Jos","Herrero Martnez",29},{"Luis","Garca Snchez",46}}; Typedef Es posible agrupar un conjunto de elementos de tipo estructura en un array. Esto se conoce como array de estructuras: El lenguaje 'C' dispone de una declaracin llamada typedef que permite la creacin de nuevos tipos de datos. Ejemplos: typedef int entero; entero */ entero a, b=3; /* acabamos de crear un tipo de dato llamado /* declaramos dos variables de este tipo */

Su empleo con estructuras est especialmente indicado. Se puede hacer de varias formas: Una forma de hacerlo: struct trabajador { char nombre[20]; char apellidos[40]; int edad; }; typedef struct trabajador datos; datos fijo,temporal; Otra forma: typedef struct { char nombre[20]; char apellidos[40]; int edad; }datos; datos fijo,temporal;

Arrays de estructuras

-58Es posible agrupar un conjunto de elementos de tipo estructura en un array. Esto se conoce como array de estructuras: struct trabajador { char nombre[20]; char apellidos[40]; int edad; }; struct trabajador fijo[20]; As podremos almacenar los datos de 20 trabajadores. Ejemplos sobre como acceder a los campos y sus elementos: para ver el nombre del cuarto trabajador, fijo[3].nombre;. Para ver la tercera letra del nombre del cuarto trabajador, fijo[3].nombre[2];. Para inicializar la variable en el momento de declararla lo haremos de esta manera: struct trabajador fijo[20]={{"Jos","Herrero Martnez",29},{"Luis","Garca Snchez",46}}; Typedef Es posible agrupar un conjunto de elementos de tipo estructura en un array. Esto se conoce como array de estructuras: El lenguaje 'C' dispone de una declaracin llamada typedef que permite la creacin de nuevos tipos de datos. Ejemplos: typedef int entero; entero a, b=3; /* acabamos de crear un tipo de dato llamado entero */ /* declaramos dos variables de este tipo */

Su empleo con estructuras se puede hacer de varias formas: Una forma de hacerlo: struct trabajador { char nombre[20]; char apellidos[40]; int edad; }; typedef struct trabajador datos; datos fijo,temporal; Otra forma: typedef struct { char nombre[20]; char apellidos[40]; int edad; }datos; datos fijo,temporal;

-59PROBLEMAS PROPUESTOS DE STRUCTURE 4


1. La informacin de todos los empleados de una cierta compaa est almacenada en una variable llamada empresa definida como un arreglo de registros. La informacin con que se cuenta de cada empleado es: nombre, sexo y sueldo. Escriba la declaracin para el registro y el arreglo empresa. Considerando las declaraciones que hizo, escriba las instrucciones en C para: a) b) c) Imprimir el nombre y el sexo del cuarto empleado. Imprimir los nombres de todos los empleados que ganan ms de $2,500.00 Sumar al sueldo del tercer empleado $2,000.00.

2. Considerando la siguiente definicin y declaraciones, indique para cada uno de los siguientes incisos sin es correcto o no. En caso de ser incorrecto diga brevemente por qu. struct nombre{ char pila[20], apellido [20]; }; struct estudiante { struct nombre nom; int calif; char grado; }; struct estudiante est1, est2, als[20]; int i; a) b) struct Estudiante als1[30]; void leer (struct estudiante *al[20]){ gets(al[2]->nom.pila); cin>>al[2]->calif); } cout<<als[10].pila[0]); for (i = 0; i < =20; i++) gets(als[i].nom); als[5] = est1; void leer(struct estudiante *est) { cin>>est->grado); } als[2].nom = als[5].nom;

c) d) e) f)

g)

-60-

3. En muchas microcomputadoras, el valor MaxInt es 32767. Esto impide un lmite estricto sobre el tamao de los enteros que puedan utilizarse. Existen diversas formas de ampliar el intervalo de valores; una se sugiere por analoga con lo que se hizo en el ejercicio anterior para representar el dinero. Por ejemplo, para representar nmeros positivos con hasta nueve cifras, podramos imaginar el nmero como lo escribimos comnmente a mano, como en estos ejemplos: 213 3 567 175 198 000

Podramos optar por utilizar un registro con tres enteros para representar el nmero de unidades de milln, unidades de millar y las unidades. Mediante el uso de esta representacin, escriba un subprograma para resolver cada una de las siguientes operaciones: a) b) c) d) e) Sume dos enteros. Reste dos enteros, suponiendo que el primero es mayor. Compare dos enteros para ver si son iguales. Compare dos enteros para ver si el primero es mayor. Multiplique dos enteros. Precaucin: si multiplica dos nmeros de tres cifras, el resultado puede ser mayor que MaxInt. Puede usted sugerir algunas soluciones a este problema?

4. Considere las siguientes definiciones: struct datos { char nombre[40], pais[25]; }; struct atleta { char deporte[30]; struct datos pers; int medallas[20]; }; struct atleta ats[1000]; Escriba un mdulo que lea del archivo f slo las 20 medallas de cada uno de los atletas (utilice el vector ats). El archivo se debe declarar como local al mdulo ya que en el resto del programa no se va a usar. No se sabe de cuntos atletas hay almacenadas medallas en el archivo. El archivo no almacena toda la informacin de los atletas, slo las medallas.

-615. Se tiene un arreglo de una dimensin en el que cada uno de sus elementos tiene la siguiente estructura: CLAVE NOMBRE SEMESTRE MATERIAS

En MATERIAS se almacena informacin acerca de las 6 calificaciones obtenidas por un alumno en el semestre indicado por SEMESTRE (entero). Suponiendo que en el arreglo ya se almacena la informacin completa de n alumnos y que est ordenado en forma ascendente por clave, escriba:

a) b) c) d) e)

La definicin del registro y la declaracin de la variable donde se guarda la informacin de los n alumnos. Una funcin que busque en el arreglo una determinada clave, si sta existe regrese como valor el lugar en el arreglo donde se encuentra. Si la clave buscada no existe deber regresar un 1. Utilice bsqueda binaria. Un mdulo que calcule el promedio de un cierto alumno. Un mdulo que imprima la clave, nombre, semestre y promedio de un determinado alumno. Por ltimo, escriba parte del programa principal donde se lean p claves y, utilizando los mdulos anteriores, se escriban los datos de los p alumnos correspondientes.

6. En un archivo se tiene informacin sobre los miembros de un coro. La informacin que se tiene de cada uno es: Nombre. Parte de voz: soprano, alto, tenor o grave. Extensin: alta o baja

Escriba: a) b) c) d) e) f) La definicin del registro y la declaracin de la variable para guardar la informacin de los miembros del coro. Un mdulo para leer la informacin del archivo y almacenarla en el vector. Un mdulo que calcule el porcentaje de miembros del coro que tienen una determinada parte de voz. Un mdulo que calcule el porcentaje de los miembros de una cierta parte de voz que tienen una determinada extensin. Por ejemplo, el porcentaje de los tenores que tienen extensin baja. Un mdulo que dado un nombre escriba su parte de voz y extensin. Un mdulo que calcule el total de miembros de cada una de las 4 partes de voz.

7. Simule, por medio de un programa, un directorio telefnico que lea nombres (20 caracteres como mximo) y nmeros telefnicos (enteros) de un archivo de texto en un arreglo de registros. Cuando el usuario teclee un nombre, el programa debe verificar si ste ya est en el directorio, en cuyo caso imprimir el nmero telefnico. De no ser as, pedir al usuario que escriba el telfono y agregar el nombre y el nmero en el arreglo.

-62La informacin no se encuentra ordenada por lo que tendr que hacer una bsqueda secuencial. 8. Defina un registro para representar la informacin de los alumnos de una escuela. La informacin que se desea guardar de cada uno es: nombre (pila, apellido), telfono, clave y calificacin. Posteriormente, defina una variable para poder almacenar 80 alumnos y escriba las instrucciones necesarias para leer el apellido de los 80 alumnos. 9. Un grupo consta de n alumnos (mximo 50), donde cada alumno cursa 5 materias. La informacin con que se cuenta de cada alumno es la clave (entero) y las 5 calificaciones (reales). Haga un programa que, utilizando un arreglo de registros, lea la informacin de cada alumno e imprima la clave, promedio redondeado a un entero y una barra horizontal de tantos asteriscos como fue su promedio. Dicha tabla deber imprimirse en forma ascendente con respecto al promedio. Por ltimo, el programa debe crear un archivo de texto, que se utilizar como reporte, con la clave, las 5 calificaciones y el promedio de los n alumnos. 10. El mundo est formado por cinco continentes, stos estn compuestos por pases conteniendo ciudades, las cuales, a su vez, tienen pueblos. a) b) c) d) e) f) Haga las definiciones necesarias y la declaracin de la variable del mundo. Suponga que de cada continente, pas, ciudad y pueblo se conoce el nombre y el nmero de habitantes. Obtenga en la variable pob el valor de la poblacin del segundo continente. Obtenga el total de habitantes del cuarto continente, suponiendo que slo se conoce la poblacin de los pueblos. Escriba el quinto carcter del nombre de la segunda ciudad del octavo pas del segundo continente. Lea el nombre de la sexta ciudad del dcimo pas del tercer continente. Lea el nombre y la poblacin de los veinte pueblos de las quince ciudades de los doce pases del quinto continente.

11. Tomando la estructura NOMINA del ejercicio anterior y considerando que est ordenada por nombre, haga un programa que imprima el sueldo de un determinado profesor. El programa deber tener un mdulo que realice una bsqueda binaria para encontrar al profesor en cuestin en NOMINA, la informacin que se proporciona es el nombre completo. 12. La informacin que tiene una empresa, almacenada en un archivo, sobre sus empleados (mximo 100) es: Clave. Entero. Sueldo. Real Cantidad de tareas pendientes. Entero (mximo 30). Tareas pendientes. Vector. Descripcin. Fecha de asignacin.

-63-

Haga un programa que: a) Lea la informacin de los empleados y la almacene en un vector. b) Dada una clave de un empleado, le asigne una nueva tarea pendiente. La bsqueda del empleado se debe realizar recursivamente. c) Recursivamente calcule el total de tareas pendientes de todos los empleados. d) Recursivamente cree dos vectores, almacenando en uno la informacin de los empleados que no tienen tareas pendientes y en el otro los que s tienen.

-64-

CAPITULO 3.- PUNTEROS O APUNTADORES


Un puntero es un tipo especial de variable, que almacena el valor de una direccin de memoria, esta direccin puede ser la de una variable individual, pero ms frecuentemente ser la de un elemento de un array o vector, una estructura u objeto de una clase. Los punteros, al igual que una variable comn, pertenecen a un tipo de dato (type), se dice que un puntero 'apunta a' ese tipo al que pertenece. Ejemplos: int* pint; char* pchar; fecha* pfecha; //Declara un puntero a entero //Puntero a char //Puntero a objeto de clase 'fecha'

Declaracin e inicializacin
Un puntero, como cualquier variable u objeto, adems de ser declarado (para comenzar a existir) necesita ser inicializado (darle un valor de modo controlado), lo cual se realiza mediante el operador de asignacin ('='). Desde que el puntero es declarado almacena un valor, el problema es que se trata de un valor aleatorio. Para que el programa compile sin problemas es necesario utilizar el operador '&' antes del nombre de la variable, el efecto del operador es devolver la direccin en memoria de la variable, la cual se asigna naturalmente a un puntero. Ejemplo Demostrativo. void main(){ int a=4; int* b; b = &a; cout<<La direccin es:<<b; cout<<El valor es:<<*b; }

//Declaracin del puntero b //El puntero 'b' apunta a 'a'.

El puntero 'b' es equivalente a la direccin de memoria a la que apunta. La variable 'a' es equivalente al valor que cout<<b; //visualiza en pantalla una almacena direccin de memoria cout<<a; //saca en pantalla '4' (por ej: 0x8f70fff0) Mientras que la expresin '*b' es sinnimo del elemento individual que se encuentra en la localidad apuntada por el puntero cout<<*b; //saca en pantalla '4' Mientras que la expresin '&a' es un sinnimo de la direccin de memoria donde se encuentra esa variable cout<<&v; //saca en pantalla una direccin de memoria (ej: 0x8f70fff0)

-65Como puede observarse, el efecto de ambos operadores es inverso, en un caso dada una localidad de memoria se accede al elemento almacenado en ella (el caso de '*'), en el otro ('&') dada una variable accedemos a la direccin de memoria donde almacena su valor.

Ejemplo Demostrativo Implemente un Programa donde ingrese 3 nmeros, utilizando punteros, visualice el mayor de los tres #include<iostream.h> void main(){ int a,b,c; //definicin de tres variables de tipo int int *p,*q,*r; //definicin de tres punteros de tipo int cout<<"Ingrese el primer numero:"; cin>>a; cout<<"Ingrese el segundo numero:"; cin>>b; cout<<"Ingrese el tercer numero:"; cin>>c; //los punteros se les asignaran la direccin de memoria p=&a; q=&b; r=&c; //comparacin if(*p>*q && *q>*r) cout<<"El mayor es:"<<*p; else if(*q>*p && *p>*r) cout<<"El mayor es:"<<*q; else if(*r>*p && *p>*q) cout<<"El mayor es:"<<*r; }

Punteros y cadenas
Una Cadena es un conjunto de caracteres encerrados entre comillas, por ejemplo la cadena "Hasta luego". Es importante comprender que una cadena es una entidad diferente a un array de caracteres o a un puntero a char*, es un valor constante y su contenido se almacena en un sector especial del segmento de datos, en la parte inicial del mismo. Ligar un puntero a una cadena no es un error, si lo es el intentar modificar un valor que debe ser tratado como constante. Cuidando estos detalles, declarar un puntero a cadena puede ser muy cmodo para manejar cadenas constantes.

-66Ejemplo Demostrativo #include<iostream.h> void main() { char cad[30]=Computacin; char* ptr = cad; //Aqui el '*' es un indicador de tipo, no de 'indirection' cout<<ptr<<endl; cout<<*ptr; } El puntero 'ptr' apunta a 'cad', al char inicial de 'cad'. Veamos ahora que saldra en pantalla con 'ptr' y con '*ptr'. cout<<ptr; cout<<*ptr; //sale en pantalla: "Computacion" //sale en pantalla: 'C'

Lo que puede desorientar aqu es que 'ptr' no imprima en pantalla una direccin de memoria, que es lo esperable tratndose de un puntero. Se trata de una caracterstica propia de las funciones que tratan con punteros a char, y no de un rasgo diferencial de los punteros a char, estos tienen las mismas caractersticas generales de cualquier puntero. Ejemplo Demostrativo Ingrese por teclado una cadena, visualizar, utilizando un puntero: Longitud de la Cadena Cadena Invertida #include<iostream.h> #include<string.h> #include<stdio.h> void main() { char cad[30]; char* ptr = cad;

//Aqui el '*' es un indicador de tipo, no de 'indirection'

cout<<"Ingrese una cadena:"; gets(cad); cout<<strlen(ptr)<<endl; cout<<strrev(ptr)<<endl; }

-67-

Arrays y punteros
Existe una equivalencia casi total entre arrays y punteros. Cuando declaramos un array estamos haciendo varias cosas a la vez: Declaramos un puntero del mismo tipo que los elementos del array, y que apunta al primer elemento del array. Reservamos memoria para todos los elementos del array. Los elementos de un array se almacenan internamente en el ordenador en posiciones consecutivas de la memoria. La principal diferencia entre un array y un puntero es que el nombre de un array es un puntero constante, no podemos hacer que apunte a otra direccin de memoria. Adems, el compilador asocia una zona de memoria para los elementos del array, cosa que no hace para los elementos apuntados por un puntero autntico. Ejemplo Demostrativo #include"iostream.h" void main() { int vector[5]={12,26,41,22,19}; int *puntero; puntero = vector; // Equivale a puntero = &vector[0] cout<<*puntero<<endl; puntero++; // puntero equivale a &vector[1] cout<<*puntero<<endl; puntero+=2; cout<<*puntero; } // equivale a 2*sizeof(int)

Paso de parmetros en funciones


Por default las variables declaradas dentro de una funcin no estn disponibles para otras funciones. Cuando necesitamos que una funcin acceda a datos de otra el principal recurso es el paso de argumentos. Un parmetro puede ser pasado a una funcin de dos modos diferentes: por valor y por referencia. Pasarlo por valor implica que la funcin receptora hace una copia del argumento y trabaja con ese doble del original, cualquier modificacin realizada en la variable-copia no producir ningn cambio en el parmetro enviado. En cambio al pasar un valor por referencia estamos pasando la direccin de memoria del mismo argumento, en este caso no hay otra 'copia' del mismo, el dato es uno y el mismo para las dos funciones, la que enva el dato y la que lo recibe.

-68-

Ejemplo Demostrativo #include"iostream.h" void suma(int, int *); void main() { int a,b; a=20; b=21; suma(a,&b); } void suma(int x, int *y){ cout<<(x+*y); }

//se pasan dos parmetros: uno por valor y otro por referencia

//al enviarse, uno enva el valor y el otro su direccin

Punteros y Estructuras
Los punteros tambin pueden apuntar a estructuras. En este caso, para referirse a cada elemento de la estructura se usa el operador (->), en lugar del (.). Ejemplo Demostrativo #include <iostream.h> struct stEstructura { int a, b; } estructura, *e; void main() { estructura.a = 10; estructura.b = 32; e = &estructura; cout << "puntero" << endl; cout << e->a << endl; cout << e->b << endl; cout << "variable" << endl; cout << estructura.a << endl; cout << estructura.b << endl; }

-69-

EJERCICIOS RESUELTOS
1. Ingrese por Teclado 3 nmeros, utilizando punteros visualice el mayor de los tres #include<iostream.h> void main() { int a,b,c; int *x=&a, *y=&b, *z=&c, *my=NULL; cout<<"Ingrese 1er numero:"; cin>>a; cout<<"Ingrese 2do numero:"; cin>>b; cout<<"Ingrese 3er numero:"; cin>>c; if(*x>*y) my=x; else my=y; if(*z>*my) my=z; cout<<"El mayor es:"<<*my; } 2. Definir un programa que me permita definir 4 variables reales ( x, y, p, q) , donde x=34.53 y=23.567 , p es un puntero que seala a la variable x y q es un puntero que seala a la variable y , definir las operaciones matemticas de los 2 punteros . #include<iostream.h> #include<conio.h> void main(){ double x=34.53 , y=23.567,*p,*q; p=&x; q=&y; cout<<"LAS OPERACIONES MATEMATICAS"<<endl; cout<<"============================"<<endl; cout<<"La Suma ="<<*p+*q<<endl; cout<<"La Resta ="<<*p-*q<<endl; cout<<"El Producto ="<<(*p)*(*q)<<endl; getch(); }

-703. Realizar un programa que me permita ingresar por teclado 3 notas del curso de estructura de datos y calcular el promedio ,mostrar por pantalla la condicin actual del alumno , si el promedio es mayor de 10.5 imprimir APROBADO en caso contrario imprimir DESAPROBADO, utilizar punteros. #include<iostream.h> #include<conio.h> void Calcular(int *, int *, int *); void main(){ int n1,n2,n3 ; cout<<"Ingrese Nota1 = "; cin>>n1; cout<<"Ingrese Nota2 = "; cin>>n2; cout<<"Ingrese Nota1 = "; cin>>n3; Calcular(&n1,&n2,&n3); } void Calcular(int *nota1,int *nota2, int *nota3){ double p1,*promedio; char *condicion; p1=(double)(*nota1+*nota2+*nota3)/3; promedio=&p1; if(*promedio>=10.5) condicion="APROBADO"; else condicion="DESAPROBADO"; cout<<"ALUMNO ESTA ="<<condicion<<endl; getch(); } 4. Realizar un programa que me permita ingresar por teclado 2 cadenas de caracteres y concatenar las 2 cadenas y mostrar por pantalla dicha cadena unida, usar punteros. #include<iostream.h> #include<conio.h> char *concatenacion(); void main(){ cout<<concatenacion()<<endl; getch(); } char *concatenacion(){ char *cad1,*cad2; char *cad3=""; cad1="estudia y progresa "; cad2=" y avanza "; cout<<"LA CADENA CONCATENADA "<<endl; cout<<"======================= "<<endl; return strcpy(cad3, strcat(cad1,cad2) ); }

-71-

CAPITULO 4.-GESTION DE MEMORIA DINAMICA


Cuando hablamos de asignacin dinmica de memoria, nos referimos al hecho de crear variables annimas, es decir reservar espacio en memoria para estas variables en tiempo de ejecucin, y tambin a liberar el espacio reservado para una variable annima en tiempo de ejecucin, en caso de que dicha variable ya no sea necesaria. El ncleo del sistema de asignacin dinmica de C++ est compuesto por las funciones malloc() o new() para la asignacin de memoria, y las funciones free() o delete() para la liberacin de memoria. Estas funciones trabajan juntas usando la regin de memoria libre. Esto es, cada vez que se hace una peticin de memoria con malloc() o new(), se asigna una parte de la memoria libre restante. Cada vez que se libera memoria con free() o delete(), se devuelve la memoria al sistema. El subsistema de asignacin dinmica de C++ se usa para dar soporte a una gran variedad de estructuras de programacin, tales como listas enlazadas que se vern ms adelante en este tema. Funciones de reserva de memoria dinmica malloc y new() El prototipo de la funcin malloc() es: void *malloc(size_t nmero_de_bytes); Aqu, nmero_de_bytes es el nmero de bytes de memoria que se quieren asignar. El tipo size_t est definido en <stdlib.h> como un tipo entero sin signo. La funcin malloc() devuelve un puntero de tipo void * , lo que significa que se puede asignar a cualquier tipo de puntero. Tendremos que convertir de forma explcita el resultado al tipo de puntero para el cual estamos reservando memoria. En la lnea de cdigo siguiente se indica con (char *)que el puntero p es un puntero a char. Tras una llamada con xito, malloc() devuelve un puntero al primer byte de la regin de memoria dispuesta del montn. Si no hay suficiente memoria libre para satisfacer la peticin de malloc(), se produce un fallo de asignacin y malloc() devuelve un nulo. char *p; p = (char *) malloc(1000); /*reserva 1.000 bytes */

Para la reserva de memoria dinmica en C, es muy til la utilizacin de la funcin sizeof(). int *p; /* reserva espacio para 50 valores de tipo entero (int) */ p = (int *) malloc(50*sizeof(int)); La funcin new() es ms simple de usar y ser la funcin que nosotros siempre utilizaremos. El prototipo de la funcin new() es: void *new <nombre_tipo>;

-72Aqu, nombre_tipo es el tipo para el cual se quiere reservar memoria. La funcin new() reservar la cantidad apropiada de memoria para almacenar un dato de dicho tipo. La funcin new() devuelve un puntero de tipo void *, lo que significa que se puede asignar a cualquier tipo de puntero. Convierte automticamente el puntero devuelto al tipo adecuado, por lo que el programador no tiene que preocuparse de hacer la conversin de forma explcita. char *p; p = new char; // reserva espacio para un carcter La funcin new tambin se encarga de averiguar cual es el tamao en bytes del tipo de datos para el cual se desea reservar memoria. Observar en el ejemplo anterior que se indica el que se quiere reservar memoria para un dato de tipo char y no cual es el tamao en bytes que se quiere reservar.

Funciones de liberacin de memoria dinmica free() y delete() La funcin free()es la complementaria de malloc() y la funcin delete() es la complementaria de new(). Una vez que la memoria ha sido liberada, puede ser reutilizada en una posterior llamada a malloc() o new(). El prototipo de la funcin free() es: void free(void *p); Aqu, p es un puntero a memoria que ha sido previamente asignado con malloc(). El prototipo de la funcin delete() es: void delete <variable_puntero>; Aqu, p es un puntero a memoria que ha sido previamente asignado con new().

EJERCICIOS RESUELTOS
1. Ingrese por Teclado 2 nmeros, utilizando punteros y gestin de memoria calcular la suma de dichos nmeros ingresados. #include<iostream.h> void main(){ int *p, *q; p=new int; q=new int; cout<<"Ingrese un Numero:"; cout<<"Ingrese otro Numero:"; cout<<"La suma es:"<<(*p+*q); }

cin>>*p; cin>>*q;

-732. Ingrese por Teclado 2 nmeros, utilizando punteros y gestin de memoria visualizar el mayor de los 2 nmeros ingresados. #include<iostream.h> #include<stdlib.h> void main(){ int *p, *q; p=(int *)(malloc(sizeof(int))); q=(int *)(malloc(sizeof(int))); cout<<"Ingrese un Numero:"; cin>>*p; cout<<"Ingrese otro Numero:"; cin>>*q; if(*p>*q) cout<<"EL mayor es:"<<*p; else cout<<"EL mayor es:"<<*q; } 3. Ingrese por Teclado una cadena, utilizando punteros y gestin de memoria visualizar la longitud de la cadena y la cadena invertida. #include<iostream.h> #include<string.h> #include<stdio.h> void main(){ char *p; p=new char[50]; cout<<"Ingrese una Cadena:"; gets(p); cout<<"Longitud:"<<strlen(p)<<endl; cout<<"Cadena Invertida:"<<strrev(p)<<endl; } 4. Ingrese por Teclado una cadena, utilizando punteros y gestin de memoria visualizar la cantidad de vocales y la cantidad de palabras que tiene la cadena. #include<iostream.h> #include<string.h> #include<stdio.h> void main(){ int i=0; char *p,*c; int *palabras, *vocales; p=new char[50]; c=new char; palabras=new int;

-74vocales=new int; cout<<"Ingrese una Cadena:"; gets(p); *palabras=0; *vocales=0; do{ if(p[i]= ='a' || p[i]= ='e' || p[i]= ='i' || p[i]= ='o' || p[i]= ='u') *vocales=*vocales+1; else if(p[i]= =' ' || p[i]= ='\0') *palabras=*palabras+1; i++; }while(i<=strlen(p)); cout<<"Numero de vocales:"<<*vocales<<endl; cout<<"Numero de palabras:"<<*palabras; } 5. Se desea implementar un programa que permita registrar las notas de un alumno, ingrese el nombre y apellido y dos notas de un alumno; calcule y visualice su promedio; utilice un puntero de registro y gestin de memoria dinmica. #include<iostream.h> #include<stdio.h> struct registro{ char nombre[50]; char apellido[50]; int n1, n2; double prom; }; void main(){ registro *p; p=new registro; cout<<"Ingrese su nombre:"; gets(p->nombre); cout<<"Ingrese su apellido:"; gets(p->apellido); cout<<"Ingrese Nota1:"; cin>>p->n1; cout<<"Ingrese Nota2:"; cin>>p->n2; p->prom=(double)(p->n1+p->n2)/2; cout<<"Su promedio:"<<p->prom; }

-755. Se desea implementar un programa que permita registrar 10 nmeros en un array( el cual utilice un puntero y gestin de memoria); ordene el array y visualizar dichos nmeros. #include<iostream.h> void main(){ int *p,*aux; int i,j; p=new int[5]; aux=new int; //ingreso de los numeros en un array for(i=0;i<5;i++){ cout<<"ingrese un numero:"; cin>>p[i]; } //ordenamiento de los numeros for(i=0;i<4;i++){ for(j=i+1;j<5;j++){ if(p[i]>p[j]){ *aux=p[i]; p[i]=p[j]; p[j]=*aux; } } } //visualizar los numeros ordenados for(i=0;i<5;i++){ cout<<p[i]<<endl; } }

Ejercicios Propuestos 5
1. Realizar un programa que me permita ingresar 3 nmeros, visualice el segundo mayor, utilice punteros y gestin de memoria 2. Realizar un programa que me permita un nmero utilizando punteros y gestin de memoria, calcular: La cantidad de cifras ceros que tiene el numero La cantidad de cifras pares e impares que tiene el nmero El numero formado por las cifras de los extremas 3. Ingrese por teclado una cadena en un puntero, calcule y visualice La vocal que ms se repite La cantidad de consonantes que tiene la cadena La cantidad de prrafos que tiene la cadena

-76-

4. Ingrese por teclado 50 nmeros en un Array (utilice puntero y gestin de memoria) se pide: El mayor de los nmeros El menor de los nmeros El promedio de los nmeros 5. Genere en forma aleatoria 100 nmeros de solamente 3 cifras y almacenarlos en un Array (utilice un puntero). Calcule y visualice: Los nmeros mayores al promedio de los nmeros generados Los nmeros capicas que se generaron 6. Se desea implementar un programa que permita registrar los datos de un trabajador: nombre, apellido, categora (obrero, empleado o auxiliar) sueldo bonificacin bonificacin especial Tipo de Afiliacin (AFP u ONP) Estos datos debern ser registrados utilizando un puntero de tipo Registro (struct). Se pide: Nombre y Apellido del Trabajador La remuneracin, suma de sus ingresos Descuento Neto 7. Se desea implementar un programa donde permita registrar las matriculas (10) de los diversos cursos de Especializacin que se dictan en UTP: Nombre y Apellido del Alumno El curso que estudia El costo del curso Estos datos debern ser registrados utilizando en un Array de punteros de tipo Registro (struct). Se pide, la cantidad de matriculas y el monto total por el curso que mas se matricularon los alumnos.

-77-

CAPITULO 5 PILAS
Una pila es una estructura de datos homognea (elementos del mismo tipo), secuencial y de tamao variable. Slo es posible un modo de acceso a esta estructura: a travs de la cabeza de la pila. De este modo podemos aadir un elemento a la cabeza de la pila o extraer un elemento de la cabeza de la pila. Debido a que las operaciones de extraccin e insercin se realizan por el mismo extremo, el ltimo elemento en ser aadido ser el primero en ser extrado; por ello a estas estructuras se las conoce con el nombre de LIFO (last-in, first-out; ltimo en entrar, primero en salir).

Otras operaciones posibles sobre la pila son la creacin de una pila vaca, la interrogacin de la misma para determinar si contiene o no algn elemento y la destruccin de la pila. Para implementar una pila como una estructura dinmica de datos se usa una lista enlazada, las operaciones de extraccin e insercin en la lista (pila) se hacen siempre sobre la cabeza de la misma.

El nodo tpico para construir pilas es

struct nodo { int dato; struct nodo *siguiente; };

-78-

Declaracin de una Pila


Los tipos que definiremos normalmente para manejar pilas sern casi los mismos que para manejar listas, tan slo cambiaremos algunos nombres:

struct nodo { int dato; struct nodo *siguiente; } *Pila=NULL, pNodo=NULL;


Donde: pNodo es el tipo para declarar punteros a un nodo. Pila es la cabecera de la Estructura.

Es evidente, a la vista del grfico, que una pila es una lista abierta. As que sigue siendo muy importante que nuestro programa nunca pierda el valor del puntero al primer elemento, igual que pasa con las listas abiertas.

Operaciones bsicas con pilas


Las pilas tienen un conjunto de operaciones muy limitado, slo permiten las operaciones: Push: Aadir un elemento al final de la pila. Pop: Leer y eliminar un elemento del final de la pila. Las operaciones con pilas son muy simples, no hay casos especiales, salvo que la pila est vaca. Push en una pila vaca Partiremos de que ya tenemos el nodo a insertar y, por supuesto un puntero que apunte a l, adems el puntero a la pila valdr NULL:

El proceso es muy simple, bastar con que: nodo->siguiente apunte a NULL. Pila apunte a nodo.

-79Push en una pila no vaca Podemos considerar el caso anterior como un caso particular de ste, la nica diferencia es que podemos y debemos trabajar con una pila vaca como con una pila normal. De nuevo partiremos de un nodo a insertar, con un puntero que apunte a l, y de una pila, en este caso no vaca

El proceso sigue siendo muy sencillo: Hacemos que nodo->siguiente apunte a Pila. Hacemos que Pila apunte a nodo.

Pop, leer y eliminar un elemento


Ahora slo existe un caso posible, ya que slo podemos leer desde un extremo de la pila. Partiremos de una pila con uno o ms nodos, y usaremos un puntero auxiliar, nodo:

1. Hacemos que nodo apunte al primer elemento de la pila, es decir a Pila. 2. Asignamos a Pila la direccin del segundo nodo de la pila: Pila->siguiente. 3. Guardamos el contenido del nodo para devolverlo como retorno, recuerda que la operacin pop equivale a leer y borrar. 4. Liberamos la memoria asignada al primer nodo, el que queremos eliminar.

Si la pila slo tiene un nodo, el proceso sigue siendo vlido, ya que el valor de Pila->siguiente es NULL, y despus de eliminar el ltimo nodo la pila quedar vaca, y el valor de Pila ser NULL.

EJERCICIOS RESUELTOS

-80-

1. Implemente un Programa que permita registrar nmeros. Utilizando Pilas se pide: Ingreso de nmeros Listado de nmeros

#include<iostream.h> #include<conio.h> #include<alloc.h> //definir la Estructura que almacenara el nmero y la direccin de memoria struct datos{ int numero; datos *dir; }*Pila=NULL; //creamos las rutinas del programa void ingresar(datos *); void listado(datos *); void menu(); void main(){ char rp; do { menu(); cin>>rp; switch(rp){ case '1': ingresar(Pila);break; case '2': listado(Pila);break; } }while(rp!='3'); } //Menu de Opciones el cual permite seleccionar una opcin para ejecutar un procedimiento void menu(){ clrscr(); cout<<"Menu"<<endl; cout<<"1.Ingreso"<<endl; cout<<"2.Listado"<<endl; cout<<"3.Salir"<<endl; cout<<"Ingrese opcion : "; }

//Proceso Listado, el cual visualiza los nmeros ingresados

-81void listado(datos *nodo) { clrscr(); int f=1; datos *reg; reg=nodo; while(reg!=NULL) { gotoxy(3,f); cout<<reg->numero; reg=reg->dir; f++; } getch(); } //Proceso ingresar, el cual permite ingresar los nmeros as como las direcciones de //memoria de las estructuras que se van creando void ingresar(datos *nodo){ char op; datos *reg; do { clrscr(); reg=(datos *)(malloc(sizeof(datos))); cout<<"Ingrese un Numero: "; cin>>reg->numero; if(nodo= =NULL){ reg->dir=nodo; } else{ reg->dir=nodo; } nodo=reg; cout<<"Desea continuar : "; cin>>op; }while(op!='n'); Pila=nodo; }

-822. Implemente un Programa que permita registrar los datos de los trabajadores del grupo UTP: cdigo, nombre y apellido, sueldo. Utilizando Pilas se pide: Ingreso de Trabajadores Listado de Trabajadores Buscar un Trabajador por su cdigo, si existe visualice sus datos Eliminar un Trabajador utilizando su cdigo, primero buscar el cdigo, si existe, eliminar el Trabajador #include<iostream.h> #include<conio.h> #include<alloc.h> #include<string.h> //definicin de la Estructura struct datos{ char codigo[5]; char nombre[40]; float sueldo; datos *dir; }*Pila=NULL; //definir los prototipos void ingresar(datos*); void listado(datos*); void buscar(datos*); void menu(); void eliminar(datos*); //Rutina Principal void main(){ char rp; do{ menu(); cin>>rp; switch(rp){ case '1': ingresar(Pila);break; case '2': listado(Pila);break; case '3': buscar(Pila);break; case '4':eliminar(Pila);break; } }while(rp!='5'); }

//Implementar la Rutina menu()

-83void menu(){ clrscr(); cout<<"Menu"<<endl; cout<<"1.Ingreso"<<endl; cout<<"2.Listado"<<endl; cout<<"3.Buscar"<<endl; cout<<"4.Eliminar"<<endl; cout<<"5.Salir"<<endl; cout<<"Ingrese opcion : "; } //Implementar la Rutina listado, donde se le enva un parmetro, que ser el puntero Pila void listado(datos *n){ clrscr(); int f=1; datos *reg; reg=n; while(reg!=NULL){ gotoxy(3,f);cout<<reg->codigo; gotoxy(10,f);cout<<reg->nombre; gotoxy(40,f);cout<<reg->sueldo; reg=reg->dir; f++; } getch(); } //Implementar la Rutina ingresar, donde se le enva un parmetro, que ser el puntero Pila void ingresar(datos *nodo){ char op; datos *reg; do{ clrscr(); reg=(datos *)(malloc(sizeof(datos))); cout<<"Codigo : ";cin>>reg->codigo; cout<<"Nombre : ";cin>>reg->nombre; cout<<"Sueldo : ";cin>>reg->sueldo; if(nodo==NULL) reg->dir=nodo; else reg->dir=nodo; nodo=reg; cout<<"Desea continuar : ";cin>>op; }while(op!='n'); Pila=nodo; } //Implementar la Rutina buscar, donde se le enva un parmetro, que ser el puntero Pila

-84void buscar(datos *nodo){ if (nodo==NULL) return; char cod[5]; clrscr(); cout<<"Codigo : ";cin>>cod; datos *reg; reg=nodo; while(reg!=NULL){ if(strcmp(cod,reg->codigo)==0) break; reg=reg->dir; } if(reg!=NULL){ cout<<reg->nombre<<endl; cout<<reg->sueldo; getch(); } free(reg); } //Implementar la Rutina eliminar, donde se le enva un parmetro, que ser el puntero Pila void eliminar(datos *nodo){ if(nodo==NULL){ return; } char cod[5]; cout<<"Codigo : ";cin>>cod; datos *p,*s; p=nodo; s=nodo; if(strcmp(cod,p->codigo)==0){ //si el registro se encuentra en el Ultimo Registro nodo=p->dir; free(p); cout<<"Eliminado el Ultimo Registro..."; getch(); return; } while(p!=NULL){ //Buscar el registro por su codigo if (strcmp(cod,p->codigo)==0){ break; } if(p= =nodo){ p=p->dir; }else{ p=p->dir; s=s->dir;

-85} } if(p!=NULL){ //si lo encontr, deber eliminarse s->dir=p->dir; free(p); cout<<"Eliminado... "; }else{ cout<<"Codigo no Encontrado..."; } getch(); }

Ejercicios Propuestos
1. Se desea implementar un Programa que permita registrar solamente nmeros de 3 cifras en una Pila, se pide realizar las siguientes operaciones: Ingrese los nmeros Listados de nmeros Ordenar los nmeros Visualizar el nmero que mas se repite 2. Se desea implementar un programa que permita registrar las notas de los alumnos: cdigo, nombre y apellido, el curso que estudio y su promedio de notas (debe estar entre 5 a 20); se pide realizar las siguientes operaciones: Ingrese de Notas Listados de Notas Listado de Notas de los Aprobados y visualizar el Promedio Ponderado Listado de Notas de los Desaprobados y visualizar la Cantidad de alumnos desaprobados 3. Se desea implementar un programa que permita registrar las matriculas en las diversas carreras que dicta utp: numero de matricula, nombre y apellido, carrera a estudiar (Computacin, Secretariado, Redes y Comunicaciones, Electrnica) y el pago. Se pide realizar las siguientes operaciones: Ingrese de Matriculas Listados de Matriculas Listado de Matriculas por cada Carrera, donde visualice la cantidad de matriculados por carrera Buscar una matricula, al ingresar el numero de la matricula, si existe, visualice los datos de dicha matricula Buscar las matriculas por carrera, al ingresar una carrera, visualice las matriculas realizadas, la cantidad de matriculas que se realizaron y el monto total por dichas matriculas

-864. Se desea implementar un programa que permita registrar las facturas que emite la empresa UTP: numero de factura, nombre y apellido del cliente, importe de la factura y la fecha de pago. Se pide realizar las siguientes operaciones: Ingrese de Facturas Listados de Facturas Buscar una Factura, al ingresar el numero de la factura, si existe, visualice los datos de dicha Factura Buscar las Facturas por Cliente, al ingresar un Cliente, visualice las Facturas realizadas, la cantidad de Facturas que se emitieron y el monto total por dichas facturas Eliminar una Factura, al ingresar su numero, si existe, eliminar dicha Factura

CAPITULO 7.- . LISTAS ENLAZADAS Los punteros y la asignacin dinmica de memoria permiten la construccin de estructuras enlazadas. Una estructura enlazada es una coleccin de nodos, cada uno de los cuales contiene uno o ms punteros a otros nodos. Cada nodo es un registro en el que uno o ms campos son punteros. La estructura enlazada ms sencilla es la lista enlazada. Una lista enlazada consiste en un nmero de nodos, cada uno de los cuales contiene uno o varios datos, ms un puntero; el puntero permite que los nodos formen una cadena.

Una variable puntero (puntero externo) apunta al primer nodo en la lista, el primer nodo apunta al segundo, y as todos los dems. El ltimo nodo contiene el valor nulo en su campo de tipo puntero. Para ilustrar las listas enlazadas, mostraremos como definir, crear y manipular una lista enlazada cuyos nodos contiene un nico carcter. Los elementos que se guardan en una lista enlazada consisten normalmente en estructuras ya que el elemento debe disponer de un enlace al siguiente elemento adems de los datos propiamente dichos. En nuestro ejemplo, declaramos el tipo TPListaEnlazada que define un puntero a la estructura ListaEnlazada que representa un nodo de la lista. Un valor del tipo ListaEnlazada ser un registro con dos campos: c (el carcter almacenado en el nodo) y sig (un puntero al siguiente nodo en la lista). struct ListaEnlazada { char c; ListaEnlazada *sig;

-87}*TPListaEnlazada; Podemos dibujar un valor de tipo ListaEnlazada como una caja con dos campos. Una lista de caracteres tendra la forma siguiente, donde primero es una variable de tipo TPListaEnlazada (puntero externo) que apunta al primer nodo de la lista: TPListaEnlazada primero;

Con esta estructura, para almacenar una cadena de caracteres en memoria iremos leyendo carcter a carcter desde teclado, y creando variables annimas de forma dinmica, almacenando en cada una de ellas un carcter y enlazndolas mediante los campos puntero; as hasta que nos introduzcan un retorno de carro, que me indicar el final de la cadena de caracteres. Las operaciones bsicas sobre listas enlazadas son: 1) Insertar un nodo en la lista enlazada 2) Borrar un nodo de la lista enlazada

Insertar un elemento en una lista vaca


Partiremos de que ya tenemos el nodo a insertar y, por supuesto un puntero que apunte a l, adems el puntero a la lista valdr NULL:

El proceso es muy simple, bastar con que: 1. nodo->siguiente apunte a NULL. 2. Lista apunte a nodo.

Insertar un elemento en la primera posicin de una lista


Podemos considerar el caso anterior como un caso particular de ste, la nica diferencia es que en el caso anterior la lista es una lista vaca, pero siempre podemos, y debemos considerar una lista vaca como una lista. De nuevo partiremos de un nodo a insertar, con un puntero que apunte a l, y de una lista, en este caso no vaca:

-88-

El proceso sigue siendo muy sencillo: 1. Hacemos que nodo->siguiente apunte a Lista. 2. Hacemos que Lista apunte a nodo.

Insertar un elemento en la ltima posicin de una lista


Este es otro caso especial. Para este caso partiremos de una lista no vaca:

El proceso en este caso tampoco es excesivamente complicado: 1. Necesitamos un puntero que seale al ltimo elemento de la lista. La manera de conseguirlo es empezar por el primero y avanzar hasta que el nodo que tenga como siguiente el valor NULL. 2. Hacer que nodo->siguiente sea NULL. 3. Hacer que ultimo->siguiente sea nodo.

Insertar un elemento a continuacin de un nodo cualquiera de una lista


De nuevo podemos considerar el caso anterior como un caso particular de este. Ahora el nodo "anterior" ser aquel a continuacin del cual insertaremos el nuevo nodo:

-89Suponemos que ya disponemos del nuevo nodo a insertar, apuntado por nodo, y un puntero al nodo a continuacin del que lo insertaremos. El proceso a seguir ser: 1. Hacer que nodo->siguiente seale a anterior->siguiente. 2. Hacer que anterior->siguiente seale a nodo.

Eliminar un elemento en la primera posicin de una lista


Es el caso ms simple. Partiremos de una lista con uno o ms nodos, y usaremos un puntero auxiliar, nodo:

Hacemos que nodo apunte al primer elemento de la lista, es decir a Lista. 1. Asignamos a Lista la direccin del segundo nodo de la lista: Lista->siguiente. 2. Liberamos la memoria asignada al primer nodo, el que queremos eliminar.

Eliminar un elemento cualquiera de la lista


En todos los dems casos, eliminar un nodo se puede hacer siempre del mismo modo. Supongamos que tenemos una lista con al menos dos elementos, y un puntero al nodo anterior al que queremos eliminar. Y un puntero auxiliar nodo.

El proceso es parecido al del caso anterior: 1. Hacemos que nodo apunte al nodo que queremos borrar. 2. Ahora, asignamos como nodo siguiente del nodo anterior, el siguiente al que queremos eliminar: anterior->siguiente = nodo->siguiente. 3. Eliminamos la memoria asociada al nodo que queremos eliminar.

-90-

Si el nodo a eliminar es el ltimo, es procedimiento es igualmente vlido, ya que anterior pasar a ser el ltimo, y anterior->siguiente valdr NULL.

EJERCICIOS RESUELTOS
Implemente un Programa que permita registrar Nmeros en una Lista enlazada. Se pide desarrollar los siguientes procesos: Ingresar nmeros Listado de los nmeros ingresados Buscar un nmero, visualizar la cantidad de veces que se repite Eliminar, al ingresar un Numero, si existe, debe ser eliminado #include<iostream.h> #include<conio.h> #include<alloc.h> //definir la estructura que trabajara la Lista struct registro{ int numero; registro *sig; }*cab=NULL ;

void ingresar(registro *); void listado(registro *); void buscar(registro *); void eliminar(registro *); void menu(); //Rutina Principal void main(){ char rp; do{

-91menu(); cin>>rp; switch(rp){ case '1': ingresar(cab);break; case '2': listado(cab);break; case '3': buscar(cab);break; case '4':eliminar(cab);break; } }while(rp!='5'); }

//Rutina Menu, donde se visualiza el Menu de Opciones void menu(){ clrscr(); cout<<"Menu"<<endl; cout<<"1.Ingreso"<<endl; cout<<"2.Listado"<<endl; cout<<"3.Buscar"<<endl; cout<<"4.Eliminar"<<endl; cout<<"5.Salir"<<endl; cout<<"Ingrese opcion : "; } //Rutina Ingresar, donde se ingresar los nodos y luego realizar el enlace entre ellos void ingresar(registro *nodo){ char op; registro *reg,*c; c=nodo; if(c!=NULL){ while(c->sig!=NULL){ c=c->sig; } } do{ clrscr(); reg=(registro *)(malloc(sizeof(registro))); cout<<"Ingrese un Numero: "; cin>>reg->numero; reg->sig=NULL; if(c==NULL) cab=reg; else c->sig=reg;

-92c=reg; cout<<"Desea continuar : "; cin>>op; }while(op!='n'); } //Rutina Listado, que permite visualizar los nmeros ingresados en la Lista void listado(registro *nodo){ if(nodo==NULL) return; clrscr(); int f=1; registro *reg; reg=nodo; while(reg!=NULL){ gotoxy(3,f); cout<<reg->numero; reg=reg->sig; f++; } free(reg); getch(); } //Rutina Buscar, al ingresar un Numero se visualiza la cantidad que se repite void buscar(registro *nodo){ clrscr(); if(nodo==NULL) return; int f=3,contador=0; int numero; cout<<"Ingrese el numero a buscar:"; cin>>numero; registro *reg; reg=nodo; while(reg!=NULL){ gotoxy(3,f); cout<<reg->numero; if(numero==reg->numero) contador++; reg=reg->sig; f++; } gotoxy(3,f+2); cout<<"Veces que se repite:"<<contador<<endl; free(reg); getch(); }

-93-

//Rutina eliminar, al ingresar un Numero se debe eliminar de la lista void eliminar(registro *nodo){ clrscr(); if(nodo= =NULL) return; int numero; cout<<"Ingrese el numero a eliminar:"; cin>>numero; registro *reg; reg=nodo; if(nodo->numero==numero){ cab=reg->sig; free(reg); cout<<"Registro Eliminado"<<endl; } else{ registro *p,*s; p=nodo; s=nodo; while(p!=NULL){ if(p->numero==numero) break; if(p==nodo) p=p->sig; else{ p=p->sig; s=s->sig; } } if(p!=NULL){ s->sig=p->sig; free(p); cout<<"Registro Eliminado"<<endl; } else{ cout<<"EL Numero no Existe"<<endl; } } getch(); }

Ejercicios Propuestos
1. Se desea implementar un Programa que permita registrar solamente nmeros de 4 cifras en una Lista, se pide realizar las siguientes operaciones: Ingrese los nmeros Listados de nmeros Ordenar los nmeros

-94Buscar, ingrese un numero y visualice las veces que mas se repite Visualizar el nmero que mas se repite 2. Se desea implementar un programa que permita registrar los accesorios de computadora que se vende en INFORDATA, cuyos datos a registrar son: cdigo del accesorio, descripcin, precio y stock, donde precio y stock deben ser mayor a cero; se pide realizar las siguientes operaciones: Ingrese de Accesorios Listados de Accesorios Ordenar los Accesorios por su Stock en forma ascendente. Eliminar un Accesorio, ingrese el cdigo del Accesorio, si existe, eliminar el Registro

3. Se desea implementar un programa que permita registrar los Libros que se encuentran en la Biblioteca de UTP, los datos de los libros son: cdigo, titulo, nombre del autor, especialidad, nro de pginas y ao de edicin. Se pide realizar las siguientes operaciones, a travs de una Lista Enlazada: Ingrese de Libros Listados de Libros Listado de Libros por Autor, al ingresar un Autor, visualice los Libros de dicho autor. Buscar un Libro, al ingresar el cdigo del Libro, si existe, visualice los datos de dicho Libro Buscar los Libros por Especialidad, al ingresar una Especialidad, visualice los libros de dicha especialidad y la cantidad de libros de dicha especialidad. 4. Se desea implementar un programa que permita registrar las facturas que emite la empresa UTPRON: numero de factura, nombre y apellido del cliente, importe de la factura y la fecha de pago. Se pide realizar las siguientes operaciones: Ingrese de Facturas Listados de Facturas Buscar una Factura, al ingresar el numero de la factura, si existe, visualice los datos de dicha Factura Buscar las Facturas por Cliente, al ingresar un Cliente, visualice las Facturas realizadas, la cantidad de Facturas que se emitieron y el monto total por dichas facturas Eliminar una Factura, al ingresar su numero, si existe, eliminar dicha Factura

-95-

CAPITULO 7 LISTAS CIRCULARES


Una lista circular es una lista lineal en la que el ltimo nodo a punta al primero. Las listas circulares evitan excepciones en las operaciones que se realicen sobre ellas. No existen casos especiales, cada nodo siempre tiene uno anterior y uno siguiente. En algunas listas circulares se aade un nodo especial de cabecera, de ese modo se evita la nica excepcin posible, la de que la lista est vaca. DEFINICION Los tipos que definiremos normalmente para manejar listas cerradas son los mismos que para manejar listas abiertas: struct _nodo { int dato; struct _nodo *siguiente; } *cab;

Operaciones bsicas con listas circulares


A todos los efectos, las listas circulares son como las listas abiertas en cuanto a las operaciones que se pueden realizar sobre ellas: Aadir o insertar elementos. Borrar elementos. Moverse a travs de la lista, siguiente.

Aadir elemento en una lista circular vaca


Partiremos de que ya tenemos el nodo a insertar y, por supuesto un puntero que apunte a l, adems el puntero que define la lista, que valdr NULL:

-96-

El proceso es muy simple, bastar con que: 1. lista apunta a nodo. 2. lista->siguiente apunte a nodo.

Aadir elemento en una lista circular no vaca


De nuevo partiremos de un nodo a insertar, con un puntero que apunte a l, y de una lista, en este caso, el puntero no ser nulo:

El proceso sigue siendo muy sencillo: 1. Hacemos que nodo->siguiente apunte a lista->siguiente. 2. Despus que lista->siguiente apunte a nodo.

Aadir elemento en una lista circular, caso general


Para generalizar los dos casos anteriores, slo necesitamos aadir una operacin: 1. Si lista est vaca hacemos que lista apunte a nodo. 2. Si lista no est vaca, hacemos que nodo->siguiente apunte a lista->siguiente. 3. Despus que lista->siguiente apunte a nodo.

-97-

Eliminar un elemento de una lista circular


Para sta operacin podemos encontrar tres casos diferentes: 1. Eliminar un nodo cualquiera, que no sea el apuntado por lista. 2. Eliminar el nodo apuntado por lista, y que no sea el nico nodo. 3. Eliminar el nico nodo de la lista.

Eliminar un nodo en una lista circular con ms de un elemento


Consideraremos los dos primeros casos como uno slo.

1. El primer paso es conseguir que lista apunte al nodo anterior al que queremos eliminar. Esto se consigue haciendo que lista valga lista->siguiente mientras lista>siguiente sea distinto de nodo. 2. Hacemos que lista->siguiente apunte a nodo->siguiente. 3. Eliminamos el nodo.

Eliminar el nico nodo en una lista circular


Este caso es mucho ms sencillo. Si lista es el nico nodo de una lista circular: 1. Borramos el nodo apuntado por lista. 2. Hacemos que lista valga NULL.

-98-

Ejercicio Demostrativo
Implemente un Programa que permita registrar las Notas; ingrese el Nombre del Alumno, el curso estudiado y su promedio. Se pide, utilizando Listas Circulares: Ingreso de Alumnos y Notas Listado de los Registros ingresados Buscar por Alumno, al ingresar su nombre visualice los cursos y su promedio

#include<iostream.h> #include<string.h> #include<conio.h> //Definicion de la Estructura struct registro{ char alumno[40]; char curso[40]; double prom; registro *sig; }*cab=NULL ; //Definicion de los Prototipos void ingresar(registro *); void listado(registro *); void buscar(registro *); void menu(); //Rutina Principal void main(){ char rp; do{ menu(); cin>>rp; switch(rp){ case '1': ingresar(cab);break; case '2': listado(cab);break; case '3': buscar(cab);break; } }while(rp!='4'); } //Rutina de Menu de Opciones void menu(){ clrscr(); cout<<"Menu"<<endl; cout<<"1.Ingreso"<<endl; cout<<"2.Listado"<<endl;

-99cout<<"3.Buscar"<<endl; cout<<"4.Salir"<<endl; cout<<"Ingrese opcion : "; } //Rutina para el Ingreso de Registros void ingresar(registro *nodo){ char op; registro *reg,*c,*p; c=nodo; if(c!=NULL){ p=c; do{ if(p==c) p=p->sig; else{ p=p->sig; c=c->sig; } }while(p!=nodo); } do{ clrscr(); reg=(registro *)(malloc(sizeof(registro))); cout<<"Ingrese el Alumno: ";cin>>reg->alumno; cout<<"Ingrese el Curso Estudiado: ";cin>>reg->curso; cout<<"Ingrese el Promedio: ";cin>>reg->prom; if(nodo==NULL){ c=reg; reg->sig=c; nodo=reg; cab=reg; } else{ c->sig=reg; reg->sig=nodo; c=reg; } cout<<"Desea continuar : ";cin>>op; }while(op!='n'); free(p); free(reg); free(c); }

-100//Rutina para el Listado de los registros void listado(registro *nodo){ clrscr(); if(nodo==NULL) return; int f=1; registro *reg; reg=nodo; do{ gotoxy(3,f);cout<<reg->alumno; gotoxy(25,f);cout<<reg->curso; gotoxy(45,f);cout<<reg->prom; f++; reg=reg->sig; }while(reg!=nodo); free(reg); getch(); } //Rutina para Buscar por el nombre del alumno void buscar(registro *nodo){ clrscr(); if(nodo==NULL) return; int f=3; char alu[40]; cout<<"Ingrese el Alumno a buscar:"; cin>>alu; registro *reg; reg=nodo; do{ if(strcmp(alu,reg->alumno)==0){ gotoxy(3,f);cout<<reg->curso; gotoxy(30,f);cout<<reg->prom; f++; } reg=reg->sig; }while(reg!=nodo); free(reg); getch(); }

-101-

CAPITULO 8 LISTAS ENLAZADAS DOBLES


Las listas doblemente enlazadas consisten en datos, ms un enlace al elemento siguiente y otro enlace al elemento anterior.

Disponer de dos enlaces en lugar de slo uno tiene varias ventajas: La lista puede recorrerse en cualquier direccin. Esto simplifica la gestin de la lista, facilitando las inserciones y las eliminaciones. Ms tolerante a fallos. Se puede recorrer la lista tanto con los enlaces hacia delante como con los enlaces hacia atrs, as si se invalida algn enlace se puede reconstruir la lista utilizando el otro enlace. La forma de construir una lista doblemente enlazada es similar a la de una lista simplemente enlazada excepto en que hay que mantener dos enlaces. Por tanto, la estructura tiene que contener esos dos enlaces. Usando el mismo ejemplo anterior modificamos la estructura REG y aadimos el nuevo enlace. struct ListaDobleEnlazada { char c; ListaDobleEnlazada* sig; ListaDobleEnlazada* ant; } *TPListaDobleEnlazada; Las operaciones bsicas son las mismas que en las listas simplemente enlazadas: 1) Insertar un nodo en la lista doblemente enlazada 2) Borrar un nodo de la lista doblemente enlazada

Aadir elemento en una lista doblemente enlazada vaca Partiremos de que ya tenemos el nodo a insertar y, por supuesto un puntero que apunte a l, adems el puntero que define la lista, que valdr NULL:

El proceso es muy simple, bastar con que:

-1021. lista apunta a nodo. 2. lista->siguiente y lista->anterior apunten a null.

Insertar un elemento en la primera posicin de la lista Partimos de una lista no vaca. Para simplificar, consideraremos que lista apunta al primer elemento de la lista doblemente enlazada:

El proceso es el siguiente: 1. nodo->siguiente debe apuntar a Lista. 2. nodo->anterior apuntar a Lista->anterior. 3. Lista->anterior debe apuntar a nodo.

Recuerda que Lista no tiene por qu apuntar a ningn miembro concreto de una lista doblemente enlazada, cualquier miembro es igualmente vlido como referencia. Insertar un elemento en la ltima posicin de la lista Igual que en el caso anterior, partiremos de una lista no vaca, y de nuevo para simplificar, que Lista est apuntando al ltimo elemento de la lista:

-103-

El proceso es el siguiente: 1. nodo->siguiente debe apuntar a Lista->siguiente (NULL). 2. Lista->siguiente debe apuntar a nodo. 3. nodo->anterior apuntar a Lista.

Insertar un elemento a continuacin de un nodo cualquiera de una lista Bien, este caso es ms genrico, ahora partimos de una lista no vaca, e insertaremos un nodo a continuacin de uno nodo cualquiera que no sea el ltimo de la lista:

El proceso sigue siendo muy sencillo: 1. 2. 3. 4. Hacemos que nodo->siguiente apunte a lista->siguiente. Hacemos que Lista->siguiente apunte a nodo. Hacemos que nodo->anterior apunte a lista. Hacemos que nodo->siguiente->anterior apunte a nodo.

-104-

Eliminar nodos en una lista doblemente enlazada


Eliminar el nico nodo en una lista doblemente enlazada En este caso, ese nodo ser el apuntado por Lista.

1. Eliminamos el nodo. 2. Hacemos que Lista apunte a NULL.

Eliminar el primer nodo de una lista doblemente enlazada Tenemos los dos casos posibles, que el nodo a borrar est apuntado por Lista o que no. Si lo est, simplemente hacemos que Lista sea Lista->siguiente.

1. Si nodo apunta a Lista, hacemos que Lista apunte a Lista->siguiente. 2. Hacemos que nodo->siguiente->anterior apunte a NULL 3. Borramos el nodo apuntado por nodo.

El paso 2 depara el nodo a borrar del resto de la lista, independientemente del nodo al que apunte Lista.

-105Eliminar el ltimo nodo de una lista doblemente enlazada De nuevo tenemos los dos casos posibles, que el nodo a borrar est apuntado por Lista o que no. Si lo est, simplemente hacemos que Lista sea Lista->anterior.

1. Si nodo apunta a Lista, hacemos que Lista apunte a Lista->anterior. 2. Hacemos que nodo->anterior->siguiente apunte a NULL 3. Borramos el nodo apuntado por nodo.

Eliminar un nodo intermedio de una lista doblemente enlazada De nuevo tenemos los dos casos posibles, que el nodo a borrar est apuntado por Lista o que no. Si lo est, simplemente hacemos que Lista sea Lista->anterior o Lista->siguiente

1. Si nodo apunta a Lista, hacemos que Lista apunte a Lista->anterior (o Lista>siguiente). 2. Hacemos que nodo->anterior->siguiente apunte a nodo->siguiente. 3. Hacemos que nodo->siguiente->anterior apunte a nodo->anterior. 4. Borramos el nodo apuntado por nodo.

-106-

Ejercicio Demostrativo
Implemente un Programa que permita registrar las Notas; ingrese el Nombre del Alumno, el curso estudiado y su promedio. Se pide, utilizando Listas Circulares: Ingreso de Alumnos y Notas Listado de los Registros ingresados Buscar por Alumno, al ingresar su nombre visualice los cursos y su promedio #include<iostream.h> #include<string.h> #include<conio.h> #include<alloc.h> struct registro{ char alumno[40]; char curso[40]; double prom; registro *sig; registro *ant; }*cab=NULL ;

void ingresar(registro *); void listado(registro *); void buscar(registro *); void menu(); void main(){ char rp; do{ menu(); cin>>rp; switch(rp){ case '1': ingresar(cab);break; case '2': listado(cab);break; case '3': buscar(cab);break; } }while(rp!='4'); } void menu(){ clrscr(); cout<<"Menu"<<endl; cout<<"1.Ingreso"<<endl; cout<<"2.Listado"<<endl; cout<<"3.Buscar"<<endl; cout<<"4.Salir"<<endl;

-107cout<<"Ingrese opcion : "; } void listado(registro *nodo){ clrscr(); if(nodo==NULL) return; int f=1; registro *reg; reg=nodo; while(reg!=NULL){ gotoxy(3,f);cout<<reg->alumno; gotoxy(25,f);cout<<reg->curso; gotoxy(45,f);cout<<reg->prom; f++; reg=reg->sig; } free(reg); getch(); } void ingresar(registro *nodo){ char op; registro *reg,*c,*p; c=nodo; if(c!=NULL){ p=c; do{ if(p==c) p=p->sig; else{ p=p->sig; c=c->sig; } }while(p!=NULL); } do{ clrscr(); reg=(registro *)(malloc(sizeof(registro))); cout<<"Ingrese el Alumno: ";cin>>reg->alumno; cout<<"Ingrese el Curso Estudiado: ";cin>>reg->curso; cout<<"Ingrese el Promedio: ";cin>>reg->prom; if(c==NULL){ reg->ant=NULL; reg->sig=NULL; c=reg; cab=reg;

-108} else{ c->sig=reg; reg->ant=c; reg->sig=NULL; c=reg; } cout<<"Desea continuar : ";cin>>op; }while(op!='n'); free(p); free(reg); free(c); } void buscar(registro *nodo){ clrscr(); if(nodo==NULL) return; int f=3; char alu[40]; cout<<"Ingrese el Alumno a buscar:"; cin>>alu; registro *reg; reg=nodo; do{ if(strcmp(alu,reg->alumno)==0){ gotoxy(3,f);cout<<reg->curso; gotoxy(30,f);cout<<reg->prom; f++; } reg=reg->sig; }while(reg!=nodo); free(reg); getch(); }

Ejercicios Propuestos
1. Se desea implementar un Programa que permita registrar solamente nmeros de 4 cifras en una Lista, se pide realizar las siguientes operaciones: Ingrese los nmeros Listados de nmeros, en forma Ascendente o Descendente Ordenar los nmeros Buscar, ingrese un numero y visualice las veces que mas se repite

-1092. Se desea implementar un programa que permita registrar los accesorios de computadora que se vende en INFORDATA, cuyos datos a registrar son: cdigo del accesorio, descripcin, precio y stock, donde precio y stock deben ser mayor a cero; se pide realizar las siguientes operaciones: Ingrese de Accesorios, donde el cdigo no se repita Listados de Accesorios Ordenar los Accesorios por su Stock en forma ascendente. Eliminar un Accesorio, ingrese el cdigo del Accesorio, si existe, eliminar el Registro

3. Se desea implementar un programa que permita registrar los Libros que se encuentran en la Biblioteca de UTP, los datos de los libros son: cdigo, titulo, nombre del autor, especialidad, nro de pginas y ao de edicin. Se pide realizar las siguientes operaciones, a travs de una Lista Enlazada: Ingrese de Libros Listado de Libros por Autor, al ingresar un Autor, visualice los Libros de dicho autor. Buscar un Libro, al ingresar el cdigo del Libro, si existe, visualice los datos de dicho Libro Eliminar un Libro, donde al ingresar su cdigo, si existe, eliminar el Libreo 4. Se desea implementar un programa que permita registrar las facturas que emite la empresa UTPRON: numero de factura, nombre y apellido del cliente, importe de la factura y la fecha de pago. Se pide realizar las siguientes operaciones: Ingrese de Facturas Listados de Facturas Buscar una Factura, al ingresar el numero de la factura, si existe, visualice los datos de dicha Factura Buscar las Facturas por Cliente, al ingresar un Cliente, visualice las Facturas realizadas, la cantidad de Facturas que se emitieron y el monto total por dichas facturas Eliminar una Factura, al ingresar su numero, si existe, eliminar dicha Factura

Bibliografia: - Lenguaje C Estructura de Datos Autor: Javier Ceballos - La Biblia de C++ Autor: grupo Eidos Direcciones de Internet http://www.manualesgratis.com http://www.devc.net

Anda mungkin juga menyukai