Introducción: Estructuras de Datos y Algoritmos
Introducción: Estructuras de Datos y Algoritmos
Introducción: Estructuras de Datos y Algoritmos
obj) y luego
Introducción el linker (enlazador) combina archivos objeto y bibliotecas (.lib), y genera un
programa (archivo binario ejecutable, por ejemplo, de extensión .exe).
A medida que los problemas a resolver son más complejos, los tipos de datos a
Bibliotecas y
usar se hacen complejizan también. Ya no es suficiente con tener tipos enteros o archivos objetos Linkeditor
flotantes sino que se hace necesario contar con organizaciones de datos más Archivos de (.obj, .lib)
completas. Por ejemplo, si necesitamos representar una fecha, quizás sea más encabezado (.h)
conveniente tener un tipo específico que agrupe en una sola entidad el día, el mes
y el año. Así, entonces, definimos formas más complejas de organización de datos,
las estructuras de datos y el lenguaje que vamos a utilizar es el lenguaje C. Programa
ejecutable
(.exe)
Lenguaje C
Algunas características de este lenguaje son:
Para obtener el archivo ejecutable del programa, cada archivo fuente primero es
preprocesado. Las directivas para el preprocesador son las precedidas por #. El
preprocesador se ocupa de la inclusión de archivos, sustitución de macros,
compilación condicional y eliminación de comentarios.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
La línea int main ( )
Lenguaje C Forma parte de todo programa en C.
Los paréntesis después de main indican que es un bloque constructivo del programa
Sintaxis conocido como una función.
El lenguaje C facilita un método estructurado y disciplinado para el diseño de programas de Todos los programas de C empiezan a ejecutarse en la función main.
computación.
La llave izquierda { inicia el cuerpo de la función main. La llave derecha } da por terminada
En el siguiente capítulo presentaremos las funciones elementales para trabajar en el la función main.
lenguaje C.
Este par de llaves y el conjunto de instrucciones que abarca recibe el nombre de bloque.
Al comenzar a trabajar en cualquier IDE (Entorno de desarrollo integrado para desarrollar
Antes de la llave de cierre, colocamos “return 0;”. Esta instrucción brinda información de
un programa) aparecerá:
cómo el programa finaliza su ejecución. Todo programa que ha terminado exitosamente
#include <stdio.h> retorna el valor 0 (cero) al sistema operativo
#include <stdlib.h> La línea printf ("Hello World!\n");
int main() printf ( ) es una función que permite mostrar o imprimir en la pantalla una leyenda.
{ Los paréntesis se escriben después del nombre de toda función para escribir entre ellos el
printf("Hello world!\n"); argumento.
return 0; En este programa se quiere mostrar la cadena de caracteres enunciada entre comillas
dobles; al ejecutarlo, aparecerá en la pantalla Hello World!.
}
La cadena de caracteres escrita entre comillas también se llama mensaje, leyenda o literal,
Analicemos cada una de las líneas de este código
y al mostrarla se respetan exactamente todos los caracteres que aparecen allí, salvo la barra
Las líneas #include <stdio.h> e #include <stdlib.h> invertida ´\´y el carácter escrito inmediatamente después.
Son directrices del procesador de C. La \ se llama carácter de escape y siempre se combina con el siguiente carácter:
C tiene ciertos procesos ya desarrollados y guardados ordenadamente, según sus \n significa línea nueva (el cursor se coloca al comienzo de la siguiente línea).
aplicaciones, en distintas carpetas: entrada/salida, pantalla, string, matemática, etc.. Estas
\t tabulador horizontal
carpetas se llaman en general bibliotecas.
\\ imprime una diagonal invertida \
Las líneas que se inician con # son procesadas o ejecutadas por el procesador, antes de la
compilación del programa. Esta línea le indica al procesador que incluya dentro del \% imprime el símbolo %
programa, el contenido del "archivo de cabecera de entrada/salida estándar (stdio.h)". \" imprime la doble comilla
Este archivo de cabecera contiene información y declaraciones utilizadas por el compilador Para indicar que luego de una instrucción se debe seguir en secuencia con la siguiente línea,
al compilar funciones estándar de la biblioteca de entrada/salida como son: scanf (leer) y todo enunciado debe terminar con ";" (punto y coma).
printf (mostrar).
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
En el programa se puede indicar o agregar una línea como comentario para documentar
Número con decimales entre 3.4E- Float %f
los programas y mejorar la legibilidad de los mismos. Punto flotante
38 decimales(6)
6 byte
Si el comentario ocupa solo una línea, se coloca al comenzar el mismo //, si ocupa más de
una línea, comienza con /* y termina con */. Al ejecutar el programa los comentarios no Doble punto Número con decimales entre 1.7E- Double %lf
realizan ninguna acción. Son instrucciones no ejecutables. flotante 308 decimales(10)
8 byte
Un carácter Char %c
Variables, Tipos y Declaración: Caracter
1 byte
Una variable es una posición en memoria donde se puede almacenar un valor. Antes de
usar una variable en un programa se la debe declarar, decir de qué tipo es (para determinar Cadena de caracteres char %s
cuántos bytes se reservan en memoria para almacenar su valor) y cuál es su nombre (para variable[longitud]
tantos byte
poder nombrarla en el programa). Es conveniente declararlas todas inmediatamente String
como
después de la llave de inicio del main.
caracteres
Los nombres de las variables son cadenas de letras y dígitos de 1 a 32. Se acepta el guión
bajo en los nombres nom_1, pero no puede comenzar con dígitos. Por ejemplo, para declarar la variable a como flotante, b como entera, nom como una
cadena de caracteres de a lo sumo 10 caracteres y z como caracter:
En C se consideran distintas las minúsculas de las mayúsculas. Es distinta la variable contc a
la variable contC. float a;
Todo se escribe en minúscula salvo las constantes y otros casos que ya se detallarán. int b;
char z;
La forma general para la declaración de variables:
FORMATO y _ Resta
TIPO DESCRIPCIÓN PALABRA CLAVE
TAMAÑO
+ Suma
Número sin decimales entre Int %d
Entero * Multiplica
-32768 y 32767 2 byte
/ Divide
Número sin decimales entre Long %ld
Entero largo % Resto de la división
±2.147.483.647
4 byte
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
-- Decrementa ! Not (negación)
++ Incrementa
La precedencia es:
Los operadores relacionales son símbolos que se usan para comparar dos valores. Si el ➢ !
resultado de la comparación es correcto la expresión considerada es verdadera, en caso ➢ >= > < <=
contrario es falsa. ➢ = = !=
➢ &&
Operadores relacionales: ➢ ||
Más baja
OPERADOR SIGNIFICADO
Si a la derecha hay un operando o más, primero se resuelve esa expresión y luego se asigna.
<= Menor o igual
que
Variable 1 = Variable 2; x = y;
== Igual
!= No igual x = y + z;
Variable 1 = Variable 2 operador Variable 3;
Los operadores lógicos retornan un valor lógico basados en las tablas de verdad.
C me permite un formato de "atajo" en el siguiente caso:
Operadores lógicos:
Variable1 = Variable 1 operador expresión;
OPERADOR SIGNIFICADO
Por ejemplo:
&& And ( y )
x = x +10;
Or ( o ) y = y /z;
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
Variable 1 operador = expresión;
x = x + 10; por x +=10;
printf ("argumento1");
y = y/z; por y / = z;
x = x - 23; por x -= 23; Si tiene solo un argumento es porque es una leyenda o secuencia de caracteres donde se
x = x * y; por x *= y; respeta la escritura entre comillas dobles.
Convierte ini a float antes de la asignación. scanf( "argumento 1" , &argumento 2);
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
scanf ("% d", &a);
Usa la función scanf para que el usuario entre por teclado un valor entero.
Corresponde a una declaración: a,b y sum son los nombres de las variables. Importante
Una variable es una posición en memoria donde se puede almacenar un valor para uso de En los scanf delante de las variables se coloca &, salvo excepciones. En caso de no colocarlo,
un programa. no guarda la dirección de memoria donde la almacenó y luego encontrarla es casi imposible,
utilizando cualquier valor en su reemplazo. Este valor se lo conoce como basura.
Esta declaración especifica que a, b y sum son enteros, y reserva en memoria el lugar
correspondiente, según el tipo, para cada variable. Esta secuencia printf y scanf facilita la interacción entre el usuario y la computadora. Ya
que con el printf me muestra una leyenda que me indica que hacer, que dato ingresar y el
Las variables se declaran enseguida de la llave izquierda del main, antes de ser utilizadas en
scanf me permite ingresar por teclado los datos.
el programa.
Si sólo colocamos el scanf se muestra en la pantalla un cursor titilando y al no tener una
La línea:
indicación sobre que está esperando como entrada: mi edad, mi nombre, mi sueldo… se
printf ("Ingrese el primer número entero \ n") ; hace poco amigable para el usuario.
Muestra la leyenda en la pantalla y coloca el cursor al principio del renglón siguiente, por Por eso es recomendable colocar un printf() y luego el scanf().
terminar con \ n.
La línea:
La línea:
printf ("La suma es %d", sum);
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 9 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 10
Utiliza la función printf para mostrar por pantalla la leyenda: ”La suma es” seguida del valor campo de 6 lugares
numérico de la variable sum.
Importante
Salida:
Este printf tiene 2 argumentos:
Si quiero mostrar 2 números en distinto renglón y alineados a derecha, debo saber cual
• El primer argumento es la leyenda que incluye dentro de las comillas dobles %d que es la cantidad máxima de dígitos y colocar ese número antepuesto a la d.
indica que se mostrará un número entero en ese lugar.
• El segundo argumento especifica el nombre de la variable que contiene el valor para Por ejemplo si tengo 2 números y el que ocupa más es de 6 dígitos
ser impreso 123 de los 6 lugares ocupa los 3 últimos
Es decir al mostrar por pantalla, en la leyenda se reemplaza el %d por el valor que tomó
154378 considera el campo de 6 lugares alineando de derecha a izquierda
sum.
Dentro de un printf también se pueden hacer cálculos. o Para mejorar la salida de puntos flotantes
Se puede reemplazar: Para mejorar el formato %f, que mostrará el valor con 6 decimales aunque no sea real,
sum= a+b; por ejemplo en el caso de sueldo no queda bien mostrar
printf ("La suma es %d", sum); $1245,500000 podemos recurrir a estas mejoras.
Por: printf("La suma es % d", a+b); % 6.1f son 6 caracteres en total de los cuales 1 es decimal
y en este caso no es necesario el uso de la variable sum. %.2f si delante del ´.´ no hay dígito significa que la cantidad de caracteres totales no
está restringida, pero el dígito que está detrás del ´.´ es la cantidad de decimales que se
Para ser más clara la salida podría ponerse:
mostrarán.
printf ("La suma entre los números %d y %d es %d", a,b,sum);
Si en el primer argumento hay varios controles de formato significa que serán reemplazados
por los valores de las variables del segundo argumento en el orden en que están
enumeradas.
Importante
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 11 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 12
Estructuras de decisión o selección: El primer operando es una condición, el segundo operando es el valor de toda la expresión
condicional si la condición es verdadera, y el tercer operando es el valor de toda la expresión
Sentencia IF: condicional si la condición es falsa.
Sintaxis:
Permite tomar una decisión para ejecutar una acción u otra, basándose en el resultado V o
F de una condición.
Condición? expresión 1: expresión 2;
Sintaxis:
# include <stdio.h>
Es por eso que el else es opcional, es posible que ante una decisión por la opción V se {
tengan que ejecutar sentencias, pero por el F no se ejecute ninguna sentencia. int x,a,b;
En caso de no ser así, se debe colocar la condición inversa. printf ("Ingrese un número: ");
Si tanto por la salida de V o F se deben ejecutar más de 1 sentencia, las salidas se deben scanf ("%d", &a);
colocar entre { } para limitar el bloque.
printf ("Ingrese otro ; ");
Los operadores de relación que van en la condición son <, >, <=, >=,
scanf ("%d", &b);
== (igualdad) ! = ( distinto).
x= a>b? a:b;
Cualquier regla convencional de sangrías que escoja deberá aplicarse con cuidado en todo
printf ("El mayor es %d", x);
el programa.
return 0;
Un programa que no siga reglas de esparcimiento uniformes es difícil de leer.
}
Sin utilizar la variable x sería:
OPERADOR ?:
printf ("%d", a>b? a:b);
C tiene este operador que utiliza 3 operandos.
Los operandos junto con el operador condicional conforman una expresión condicional.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 13 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 14
ANIDAMIENTO DE IF: Cada ELSE se corresponde con el IF más próximo que no haya sido emparejado.
Sintaxis:
{ F F NO NO
if (condición 2) F V NO NO
sentencia 1; V F NO SI
}
V V SI NO
else
Al colocar las { } estamos indicando que el else pertenece al primer if. Esas llaves son
sentencia
obligatorias ya que estamos 2;el orden de pertenencia de los else.
alterando
Operadores Lógicos:
/* siguiente instrucción ejecutable */
AND Y &&
Cond. 1 Cond. 2 Sent 1 Sent 2
OR O ||
F F NO SI Para recordar
F V NO SI
En un && (y), la salida es verdadera sólo si ambas condiciones son
V F NO NO VERDADERAS.
if (condición 1) Realizar un programa para sumar dos números reales tales que, si la suma es mayor que 10,
if (condición 2) se divide por 2 y si la suma es menor que 10 se multiplica por 3, si es 10 no se modifica.
Listar en todos los casos el resultado logrado.
sentencia 1;
else
sentencia 2;
/* siguiente instrucción ejecutable */
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 15 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 16
Sentencia WHILE
#include <stdio.h>
{
while (condición)
sentencia 1;
float sum, num1, num2, res=0;
res=sum*3;
Si la condición es verdadera entra al while o sea se ejecutan las sentencias del while.
else
Si la condición es falsa no entra y ejecuta la próxima instrucción ejecutable fuera del while.
res=sum;
IMPORTANTE!!
printf ("Resultado %.2f",res);
Cuando la variable es un contador que se incrementa en +1 se puede escribir como:
return 0;
variable++;
}
Cuando la variable es un contador que se incrementa en -1 se puede escribir como:
variable--;
Estructuras de repetición
Sentencia DO/WHILE
Una estructura de repetición le permite al programador que se repita una acción, en tanto
cierta condición se mantenga verdadera. Es similar al while. En el while la condición se encuentra al principio, antes de ejecutarse el
cuerpo del mismo.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 17 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 18
La estructura DO/WHILE prueba la condición de continuación del ciclo después de Sentencia FOR
ejecutarse el cuerpo del ciclo, y por lo tanto el cuerpo se ejecutará por lo menos una vez.
La utilizo sólo cuando sé exactamente la cantidad de repeticiones que se debe hacer:
Cuando la condición es falsa se ejecuta la acción siguiente a la del while.
Sintaxis:
sentencia1;
do
}
¡IMPORTANTE!
}
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 19 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 20
El valor inicial es 7, la condición es que sea <=112 y el incremento o progresión es de 7, por
pedir múltiplos de 7.
# include <stdio.h>
int main ( )
int k;
for (k = 9; k > = 1 ; k - - )
Es por eso que la condición debe ser con >=1 y el incremento es de -1 ya que va
disminuyendo la variable.
2. Ingresar el día y la cotización del dólar durante un mes. Calcular y mostrar el día
donde hubo la mayor cotización.
4. Ingresar números hasta que dicho número sea negativo. Calcular y mostrar:
5. Ingresar la edad y sueldo de los empleados de una empresa hasta que ambas sean
cero. Calcular y mostrar:
6. Ingresar números hasta que dicho número sea negativo. Por cada número leído,
ingresar esa cantidad de números y obtener:
La división del código en funciones hace que las mismas se puedan reutilizar en su programa
y en otros programas.
Para reutilizar una función dentro de un programa, solo se necesita llamar a la función. tipo de retorno nombre parámetros
Si se agrupan funciones en bibliotecas otros programas pueden utilizar estas funciones
Las funciones en C no pueden anidarse es decir una función no se puede declarar dentro de float suma (float num1, float num2)
otra función. {
Dicho de otra forma: float res;
Una función proporciona una forma conveniente de encapsular algunos cálculos, que se res = num1 + num2;
pueden emplear después sin preocuparse de su implementación.
return res;
Una función es un subprograma que se llama dentro de un programa principal. Las
}
funciones son independientes del programa que la llama, por eso una función puede ser
utilizada varias veces dentro de un programa o ser utilizada dentro de otros programas.
Una definición de función tiene la siguiente forma: Tipo de retorno o resultado: Es el tipo de dato que vuelve la función y aparece antes del
nombre de la función
TIPO DE RETORNO NOMBRE ( TIPO 1 ARG1, TIPO 2 ARG2.....) Lista de parámetros: lista de parámetros tipificados (con tipo) tipo1 parametro1, tipo2
parametro2.
Cuerpo de la función: se encierra entre llaves {....} no hay punto y coma después de la llave
Argumentos formales
de cierre
ya que representan los nombres de los elementos que se transfieren a la función desde la
Declaración local: las constantes, tipo de datos y variables declaradas dentro de las
parte del programa que llama. También se los conoce como parámetros o parámetros
funciones son locales a la misma y se perderán fuera de ella
formales.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Valor devuelto por la función: mediante la palabra return se regresa el valor de la función. La última instrucción del cuerpo es return; o
return expresión;
Una llamada a una función produce la ejecución de las sentencias del cuerpo de la return para volver un valor al punto de llamada, el tipo de la expresión debe ser el mismo
función y un retorno a la unidad de programa llamadora después que la ejecución de la que se define como tipo de salida o retorno en la definición de la función.
función se ha terminado, normalmente cuando se encuentra una sentencia return. Una función no necesita regresar un valor, un return sin expresión hace que el control
regrese al programa sin pasar ningún valor al programa principal. En este caso, que no
Nombre de una función: El nombre de una función comienza con una letra y puede
contener hasta 32 letras. regresa nada, se coloca como tipo de retorno void.
Tipo de dato de retorno: Si la función no devuelve un valor “int”, se debe especificar el tipo Ejemplo 1:
de dato devuelto por la función. Dados dos números, mostrar el mayor (los números son distintos)
Una función puede devolver un único valor. El resultado se muestra con una sentencia }
“return”.
La función llamada que recibe el control del programa se ejecuta desde el principio y cuando
termina (se llega a la sentencia “return” o a la “ }” final).
Es decir:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
¿Cómo se utilizan las funciones en un programa?
long fac ( int n)
Si se utilizan funciones dentro de un programa, éstas deben estar en 3 formas distintas:
{ int i ;
la primera es el prototipo,
long prod = 1;
la segunda es la llamada de la función dentro del main(), y
if ( n > 1)
la tercera es la definición y desarrollo.
for ( i = 2; i < = n; i++ )
La primera es el Prototipo de una función. Es la declaración de una función.
prod * = i;
Los prototipos contienen la cabecera de una función pero terminan con punto y coma.
return prod ;
Se ubican normalmente al principio de un programa, antes de la definición del “main()”.
}
Cuando una función se declara se da su nombre y la lista de sus parámetros.
Ejemplo 3:
Cuando se define significa que existe un lugar en un programa donde existe la función
Calcular la suma de n números reales.
desarrollada.
Los nombres de los argumentos en los prototipos no tienen significado, son independientes.
int i;
float sum = 0.0, x; Los nombres de los argumentos formales o locales no tienen porque coincidir con los de los
reales.
printf(“Introduce %d números reales”, n);
{…
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
#include <stdio.h>
La segunda es la llamada de la función dentro del main(), int suma(int a, int b);
Cuando se llama a la función dentro del programa principal los argumentos se llaman int main()
argumentos reales, ya que definen la información real que se transfiere.
{
En la llamada los argumentos van sin su tipo, ya que ya fueron definidos al inicio del
int n1,n2,c;
programa.
…
Recordemos que los argumentos reales son variables que se utilizan en el programa o
valores constantes. c=suma (n1,n2);
La llamada a una función puede ser de 2 formas distintas, según retornen o no un valor. }
#include <stdio.h>
Si no se nombran parámetros, se toman como int
void mostrar(int n, int res);
int power ( );
int main()
{
La tercera es la definición y desarrollo.
int n,res;
Al terminar el int main() se hace el desarrollo de la función con su definición, su cuerpo
…
y su return.
mostrar(n,res);
La declaración prototipo y la definición de la función deben coincidir en cantidad de
… parámetros y formatos y el orden en que se enumeran.
} Los nombres de los parámetros no siempre coinciden, son optativos.
La función que se invoca no puede alterar directamente una variable de la función que hace
la llamada; sólo puede modificar su copia temporal.
Es decir, si entra una variable del programa principal y la modifico en la función, al volver
no llega modificada al programa principal si la función es void.
Ejemplo:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
Escribir a 2 columnas las potencias de 2 y de 3 con exponentes 0 al 9.
#include <stdio.h>
Cada llamada pasa 2 argumentos a power(), y cada vez regresa un entero p.
int power (int m,int n); /* función prototipo, luego se
desarrolla.*/ En el programa principal, los argumentos que se pasan a power() son uno por valor ya
que pasa una constante y uno por referencia ya que pasa una variable.
int main( )
Paso por valor (o paso por copia) significa que cuando “C” compila las funciones y el
{
código que llama a la función, la función recibe una copia de los valores de los parámetros.
int i,a,b;
En la definición o desarrollo de power() los nombres base y n son argumentos locales. Por
for (i = 0; i < 10; ++ i) el orden en que están, la constante se corresponde con base y la variable i con n
{if (i==0)
b=1;
{ Las variables i y p que se declaran en la función son variables locales, es decir variables que
a= power (2,i); /* llamadas a la función.*/ no se ven en el principal y que si no regresan pierden su valor al salir de la función.
b=power (3,i); En nuestro ejemplo p regresa su valor por estar declarada en el return y en el principal su
valor se asigna a una variable del mismo tipo, y la i como no regresa no modifica el valor de
}
la variable i del principal.
printf ("%3d %6d %6d \ n", i, a , b);
Sus ámbitos son distintos, una es global o general (la del programa principal) y la otra es
}/*fin del programa principal*/ local (de la función).
int power (int base, int n) /*definición (no va ;)*/
int i, p;
p = 1;
p *= base;
}
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 9 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 10
¿Cómo declarar los vectores en C?
Vectores en C
Se debe especificar el nombre del vector, el tipo y la cantidad de elementos.
Sintaxis
int a [7];
Definición guarda 7 lugares para guardar enteros o sea cada uno de 2 bytes.
Para referirse a una posición en particular o elemento dentro del vector, Inicializar un vector de 5 elementos en cero y mostrarlos con formato tabulado:
especificaremos el nombre del vector y el número de posición del elemento particular
# include < stdio . h >
dentro del mismo.
int main ( )
a: nombre del vector
{
3 5 8 6 0 4 3
int n [ 5 ];
0 1 2 3 4 5 6 posición
int i;
El elemento de orden i se conoce como a [i-1]. Los elementos de un vector también se pueden inicializar en la declaración del
El número que está entre los [ ] se llama subíndice y debe ser un entero o expresión entera. vector:
Para multiplicar el tercer elemento por 4 y asignarlo a una variable x sería: int a[6] = { 1, 3, 5, 3, 4, 6};
x = a [2] * 4; int a[6] = {0} inicializa el primer elemento a cero y los 5 restantes les pone en cero
automáticamente.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Si en la declaración no se coloca el tamaño asume la cantidad de elementos que
luego se cargan entre { }. #include <stdio.h>
int vec[ ] = {1, 2, 8, 4}; asume vec[4] int main ( )
int vec [ 50 ];
Operaciones con vectores:
int n1,i;
1) Cargar
do {
2) Recorrer
3) Mostrar printf ( "Ingrese la cantidad real de elementos");
4) Buscar un elemento
5) Desplazar scanf ( "%d", &n1);
6) Intercambiar
} while ( n1 > 50 || n1 < 1 );
7) Ordenar
for ( i=0 ; i < n1 ; i++ )
Para cargar un vector se usa una instrucción repetitiva, por ejemplo for. printf ( " Ingrese la componente % d ", i ) ;
Si no se sabe exactamente la cantidad de elementos que tendrá el vector, lo declaramos scanf( " %d ", &vec [ i ] ) ;
con la cantidad máxima de elementos posibles. }
int vec[50]; }
La cantidad de elementos que tendrá el vector la obtenemos ingresándola por teclado.
Luego validamos que no supere la cantidad máxima.
do {
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Como es posible que el elemento lo encontremos antes de terminar de recorrer el
...
vector no es conveniente hacerlo con un for. Es preferible utilizar un while pues nos
for ( i=0; i< n1; i++) permite comparar con la condición y cortar la búsqueda al encontrarlo.
sum + = vec [ i ]; La búsqueda de un elemento no significa que ese elemento esté en el vector. Por eso
la condición del while debe ser doble, una por la condición pedida y la otra para ver si
...
Por supuesto antes definimos sum como int y en cero. la posición no llegó al último elemento.
3) Mostrar un vector Por ejemplo, para decir en qué posición está el elemento cuyo contenido es 10.
Para imprimirlo también usamos un for pues debemos recorrerlo para mostrarlo.
...
... n=0;
... if (n == n1)
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
quiero desplazar. Pero el valor que está en el último lugar queda repetido en la posición
anterior, es por esto que muchas veces se aclara que hacer en esa posición, por ejemplo ...
reemplazar por 0.
for ( i = posfinal -1; i > = posinicial; i -- )
vec [ posfinal ] = 0;
El for comienza en posfinal-1 porque se asigna a la posición i+1 y si i valiese posfinal
... quedaría en una posición más que el máximo del vector que NO EXISTE.
6) Intercambiar
El for comienza en 1 porque se asigna a la posición i - 1 y si i valiese 0 quedaría
Para intercambiar dos elementos de un vector deben conocerse las dos posiciones que
posición -1 que NO EXISTE. Si el desplazamiento es hasta posfinal se copia el valor a la se quieren intercambiar.
posición anterior.
Supongamos que quiero intercambiar la pos1 con la pos2.
Si es más de un lugar el desplazamiento solo varía en lo que le restamos a la i y en el
Si ponemos
valor inicial del for.
vec [ pos2 ] = vec [ pos1 ];
Si lo hacemos hacia atrás un lugar, se pierde el último valor ya que en la posición
posfinal queda lo que está en la posición anterior a esa y así sucesivamente hasta la ¡En la pos2 queda el valor que está en la pos1, PERO CUIDADO!!! El valor que tenía
posición primera que quiero desplazar. Pero el valor que está en el primer lugar queda originalmente la pos2 se PERDIO y en la pos1 sigue quedando su valor original. Es decir
repetido en la posición siguiente, es por esto que muchas veces se aclara que hacer en no logramos lo pedido!!!
esa posición, por ejemplo reemplazar por 0. Para poder intercambiar, debemos declarar una variable auxiliar, para guardar allí el
En este caso tenemos que tener cuidado con el for, en que sentido? Si el for valor de pos2 antes de hacer la asignación.
incrementa la variable, es decir si vamos asignando desde la primera posición a la última Esto quedaría así:
pedida, perderíamos todos los valores y lograríamos repetir el primer valor a lo largo de
aux = vec [ pos2 ];
todo el intervalo. MAL!!!!
vec [ pos2 ] = vec [ pos1 ];
Que debemos hacer?
vec [ pos1 ] = aux;
Recorrer el for de atrás hacia adelante
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
7) Ordenar: La llamada a una función sería:
Para ordenar un vector sobre sí mismo hay varios métodos uno de ellos llamado x = maximo ( vec, n1 );
burbujeo es el siguiente:
Ejemplo:
Nombre del Cantidad de
Ordenar un vector de n1 elementos en forma ascendente.
vector elementos reales
vec [ j ] = aux;
Ahora bien:
}
En el prototipo y en el desarrollo si un argumento es un vector se debe escribir con su
... tipo, nombre y los corchetes.
Para que una función reciba un vector a través de una llamada de función la lista de
¿Cómo pasar vectores en funciones? parámetros de la función debe especificar que se va a recibir un vector.
Para pasar un vector como argumento real en la llamada de una función hay que Por ejemplo:
especificar el nombre del vector sin los corchetes.
el encabezado de la función máximo sería:
Ejemplo:
int maximo (int vec [ ], int n1)
si se declara:
indicando que máximo espera recibir un vector de enteros en vec y su cantidad de
int vec [ 10 ]; elementos en el parámetro entero n1.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 9 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 10
#include <stdio. h>
No es necesario colocar el tamaño del vector entre los [ ]. void mostrar ( int x [ ] , int n );
Recordar: el prototipo le indica al C la cantidad de parámetros y su tipo void ordenar ( int a [ ] , int n1 );
int main ( ){
Problema: vectores con funciones int n1, a [50], b [50], c [50];
Dados 2 vectores de n1 elementos, siendo n1 de a lo sumo 50, calcular: int i , x ;
a) El vector C como la suma del vector a + vector b, es decir do {
b) c [ i ] = a [ i ] + b [ i ] printf ( "Ingrese la cantidad real de elementos");
c) Indicar la posición del máximo elemento de a. scanf ( "%d", &n1);
d) Reemplazar por 1 (uno) los elementos de posición par de b.
e) Ordenar el vector a en forma ascendente. } while ( n1 > 50 || n1 < 1 );
cargar ( a, n1 ) ;
mostrar ( a, n1) ;
cargar ( b, n1 ) ;
mostrar ( b, n1) ;
vectorc ( a, b, c, n1 );
x = posmax ( a, n1 )
unos (b, n1 );
ordenar ( a, n1 );
mostrar ( a, n1 );
getch( );
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 11 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 12
void cargar ( int x [ ], int n ) void unos ( int b [ ], int n1 )
{ {
int i; int i;
{ b [ i ] = 1;
printf ("\n Ingrese el elemento %d del vector" , i ); for ( i = 0; i < n1; i++)
} return;
return; }
}
void ordenar(int a[ ], int n1)
{ int i, j, aux;
return; aux = a[ i ];
} a[ i ] = a [ j ];
a [ j ]= aux;
{ return;
int i; }
for ( i = 0 ; i < n1 ; i + + )
c[i]=a[i]+b[i];
}return;}
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 13 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 14
int posmax ( int a [ ] , int n1 )
{
a) Los datos ordenados de menor a mayor por número de cuenta
Guía de Ejercicios b) El nombre y apellido y el tipo de cuenta con menor saldo.
c) Generar un vector con todos los datos de aquellos clientes que
tienen saldo negativo. Mostrarlo.
Desarrollar un algoritmo y luego codificarlo en C para cada problema. d) El porcentaje de clientes que tiene un saldo en la cuenta mayor a
$100.000.
1. Se ingresan los datos de vuelos a distintas ciudades para obtener estadísticas. Para e) Se ingresan los datos de una cuenta nueva a insertarla en el vector
ello se pide: Día de vuelo, nombre de la ciudad, capacidad del avión y cantidad de de tal manera que la información siga ordenada por número de cuenta.
pasajes vendidos. Estos datos se ingresan hasta que el día de vuelo sea cero. (desplazando los elementos a derecha).
Calcular y mostrar:
2. Leer números enteros hasta cargar un arreglo de 10 elementos donde los primeros
5 son positivos y los restantes negativos.
3. Ingresar los datos de las cuentas de distintos clientes de un banco. Ellos son:
▪ Nro. de cuenta
▪ Nombre y Apellido
▪ Tipo de cuenta (1. caja de ahorro, 2. cuenta corriente)
▪ Saldo.
Calcular y mostrar:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
MUY IMPORTANTE: La indización comienza en 0 y es igual que en los vectores.
ARREGLOS MULTIDIMENSIONALES
Matrices
Funciones: Generar y mostrar una matriz en C
En matemática, una matriz es una disposición de números en filas y columnas:
Detallamos las funciones necesarias para generar una matriz con datos ingresados
2 7 −1 por teclado y mostrarla por pantalla.
(3 4 8)
−2 11 5
void GenerarMatriz (int A[][8], int filas, int cols){
La matriz A tiene 3 filas y 3columnas. Para denotar el elemento de la fila i columna j
se escribe Aij.. Podemos escribir entonces en este ejemplo que A12 =7 int i, j;
Diferencia con un arreglo: En la
for (i = 0; i < filas; i++)
También al programar podemos necesitar de tablas de valores dispuestas en filas y matriz, al pasarla por parámetro,
columnas. Por ejemplo, para representar una tabla de posiciones, una tabla de tarifas u { debe tener el número de
horarios de transportes, etc. Las matrices se usan entonces en programación y se conocen
columnas, sino es un error de
como arreglos multidimensionales. for (j = 0; j < cols; j++)
compilación
{
Matrices en C scanf(“%d”,&num);
A[i][j] = num;
}
Un arreglo bidimensional de 3 filas y 3 columnas como el del ejemplo anterior se
define en C indicando el tipo, el nombre del arreglo y entre corchetes la cantidad de filas y }
la cantidad de columnas: }
int array [3][3]; void MostrarMatriz (int A[][8], int filas, int cols){
Se puede inicializar en el mismo momento, de la siguiente manera: int i, j; Para que cada fila se
int array [3][3] = {{3, 4, 5}, for (i = 0; i < filas; i++) vea es un renglón
{5, 7, 8}, diferente
{ printf(“\n”);
{4, 3, 5}}; for (j = 0; j < cols; j++)
{
Para hacer referencia a un elemento particular, entre corchetes se indica la fila y la printf(“%d \t”,A[i][j]); \t de tabulación,
columna: } deja un espacio
array[0][0]vale 3 } entre los números
} de la matriz
array[0][1] vale 4
Programa principal
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Diagonal principal:
int main()
scanf(“%d”,&cols);
Simétrica
Traspuesta Ejemplo:
Se representa por At ó AT
1 2 1 3
𝐴=( ) 𝐴𝑡 = ( )
3 4 2 4
Opuesta
La matriz opuesta de una dada es la que resulta de sustituir cada elemento por su
opuesto. La opuesta de A es -A.
1 2 −1 −2
𝐴=( ) −𝐴 =( )
3 4 −3 −4
Cuadrada
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Guía de Ejercicios
a) la matriz transpuesta
b) El promedio de los elementos de las dos diagonales (principal y secundaria)
c) Multiplicar la matriz por su transpuesta.
d) Determinar cuántos números primos hay en la matriz.
scanf ( " % [ ^\n ] ", nombre La instrucción permite guardar en contenido de s2 en s1.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
- s1: cadena de caracteres destino Comparar
- s2: cadena de caracteres origen
La función strcmp (string compare) sirve para comparar el contenido de dos cadenas de
caracteres.
s2 y s1 deben ser del mismo tamaño.
Su sintaxis es:
Leer los nombres y promedios de diez alumnos. Mostrar el nombre del mejor alumno.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Hasta la " I ", las cadenas son iguales. Luego se compara la “E” de S1 con la "A" de S2. En Tratamiento de la cadena caracter a caracter
este caso, strcmp devuelve un numero positivo ( > 0), ya que el código ASCII de la "E" es
Nuestro propósito es, dada una cadena de caracteres, procesar caracter a caracter y
mayor al de la "A" y al restarlos el resultado es positivo.
mostrar algunas conclusiones.
Ejemplo
Ejercicio de aplicación
- Si ingresamos: La vida es maravillosa
Ingresar los nombres de los 10 alumnos de un curso y decir cuántos se llaman JUAN
Queremos conocer cuántas palabras terminan con la letra a, cuántas palabras tiene la
frase, cuántos blancos hay, sin utilizar arreglos ni matrices para guardar la frase. La idea es
procesar cada caracter y, una vez leído, se pierde (no se puede volver para atrás).
#include <stdio.h> ¿Cómo lo hacemos?
#include <string.h>
Hay dos funciones en C que permiten leer caracter a caracter y mostrarlo en pantalla.
int main() La función getchar() permite leer un caracter (solo uno). Esta función internamente
{ traduce el carácter leído al número que le corresponde en la tabla ASCII, es decir, procesa
char nombre[15]; ese número. Esto se hace así ya que con un entero podemos representar tanto el
int cont=0, i; conjunto de caracteres que cabe en el tipo carácter (normalmente el conjunto ASCII de
for(i=0; i<10;i++) caracteres) como el carácter EOF de fin de fichero. Estos caracteres se suelen representar
{ como un entero que va del 0 al 127 o 256. El carácter EOF entonces es representado con
printf("Ingrese el nombre del alumno\n"); un -1
scanf("%s",nombre); La función putchar() muestra el carácter en pantalla. Internamente traduce el valor
if(strcmp(nombre,"Juan")==0 || strcmp(nombre,"JUAN")==0) numérico a la letra que le corresponde en la tabla.
{
El esquema básico en C es:
cont++;
}
}
printf("\nEn el curso hay %d alumnos llamados Juan", cont);
return 0;
}
Observación
Veamos entonces un ejemplo: Ingresar una frase terminada en punto y contar cuántos
En el strcmp del ejercicio anterior, comparamos la variable nombre con una cadena
blancos tiene la frase.
determinada, por eso la cadena está escrita entre comillas.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
Ingresamos la frase y c
guarda el primer carácter
de la frase.
En este caso, al anidar los if se busca en
la frase el grupo ‘sa’ y los cuenta. Puede
Se empieza a recorrer la estar en cualquier lugar de la frase
frase hasta encontrar el
punto
Si el caracter es un
blanco, se incremente el
La variable c guarda el
contador
próximo carácter de la
frase.
Veamos ahora pequeños códigos que les van a ayudar a construir los programas del
trabajo práctico.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
13. Leer un texto carácter por carácter terminando en PUNTO y contar la cantidad de
Guía de Ejercicios letras iguales a la primera distinta de blanco.
14. Leer un texto carácter por carácter terminando en PUNTO. Contar grupos "TA".
Desarrollar un algoritmo y luego codificarlo en C para cada problema. Mostrar reemplazando por “TE”.
4. Leer un texto carácter a carácter, terminado en PUNTO y repetirlo reemplazando 17. Leer un texto carácter por carácter terminando en punto. Contar palabras
los grupos ‘vl’ por ‘bl’. terminadas en “n” y mostrarlas pasándolas al plural.
10. Leer un texto carácter por carácter terminando en PUNTO. Contar cuántas
palabras con 2 letras seguidas iguales hay.
11. Ingrese un texto carácter a carácter terminado en PUNTO contar cuantas palabras
tienen más de una vez repetida la primera vocal que aparece en el texto.
12. Ingrese un texto carácter a carácter terminado en PUNTO y repítalo agregando una
‘u’ entre cada letra ‘q’ seguida de ‘i’ o ‘e’.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Diseño de funciones recursivas
Recursividad Al diseñar un algoritmo recursivo hay que identificar:
una herramienta conveniente y muy útil para diseñar modelos informáticos de la anterior.
- siempre se finaliza en el caso base.
realidad que deseamos modelizar. Se dice que un sistema es recursivo cuando está
parcial o completamente definido en términos de sí mismo. Quizá todos nos hemos
Por todo lo anterior, es posible diseñar la función recursiva factorial:
planteado alguna vez una imagen recursiva: una fotografía que muestra a una
persona que sostiene entre sus manos esa fotografía, que muestra a esa persona que En C, dicha función resulta:
sostiene entre sus manos esa fotografía, que muestra a esa persona que sostiene
entre sus manos esa fotografía, que muestra…
Definición
Los algoritmos recursivos son aquellos que se invocan, directa o indirectamente a sí
mismos.
- Si n = 0, 0! = 1
- Si n > 0, n! = n * (n-1)!
Se observa que al definir factorial de un número se está basando en el factorial del
número anterior. También se puede observar que esto no es así indefinidamente,
sino que hay un caso particular que es el del cero que tiene su propia definición.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Si se invoca factorial con, por ejemplo 4, la secuencia de llamadas recursivas es:
factorial(4) = 4 * 6 24
factorial(4) = 4 * factorial(3)
factorial(3) = 3 * 2
factorial(3) = 3 * factorial(2)
factorial(2) = 2 * 1
factorial(2) = 2 * factorial(1)
factorial(0) = 1 * 1
factorial(1) = 1 * factorial(0)
factorial(0) = 1
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Guía de ejercicios
1. Diseñar un algoritmo recursivo que permita hacer la división por restas sucesivas.
3. Diseñar un algoritmo recursivo que permita sumar los dígitos de un número. Por
ejemplo, Entrada: 123 Resultado: 6.
5. Diseñar un algoritmo recursivo que permita sumar los elementos de una matriz.
10. Cargar una matriz de n filas y n columnas, calcular y mostrar el elemento máximo
de cada fila en forma recursiva.
11. Cargar una matriz de n filas y n columnas, calcular y mostrar el producto de los
elementos de la diagonal principal en forma recursiva.
12. Ingresar dos números y calcular el m.c.d. en los mismos en forma recursiva.
Contenido de cada posición de memoria Cuando se muestra pi, ocurren dos pasos diferenciables. En primer lugar, el programa
busca la dirección de memoria reservada para pi (en nuestro ejemplo sería la dirección
112). Hecho esto, en segundo lugar, el programa recupera el contenido de esa dirección
de memoria. Así, por un lado distinguimos la dirección de memoria asignada a una
variable y, por el otro, el contenido de la posición de memoria reservada.
Podemos acceder a la dirección de una variable utilizando el operador &, y así accedemos
111 112 113 114 115 116… Direcciones de memoria a la dirección de memoria de una variable. Esta dirección es un número en sistema
hexadecimal con el que podemos trabajar directamente.
Veamos un ejemplo:
Concepto
int main()
{ Como su nombre lo indica, un puntero es algo que apunta, es decir, nos indica la ubicación
de algo. Imaginemos que tenemos un gran organizador en el que guardamos informes.
float pi; // reserva memoria para la variable pi
Este organizador está dividido en compartimentos, cada uno de los cuales contiene uno
pi=3.14; // almacena o guarda el valor 3.14 de nuestros informes (esto sería equivalente a las variables con las que hemos trabajado
printf ("%.2f\n", pi); // muestra el contenido de pi hasta ahora -informes- que contienen información, y el organizador representa la
memoria; obviamente las variables se almacenan en la memoria). Sin embargo, otros
return 0;
compartimentos no contienen informes sino que una nota que nos dice dónde está ese
} informe.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Supongamos que, como máximo, trabajamos con cinco informes a la vez. Por lo tanto, num
reservamos cinco compartimentos en los que indicamos en qué compartimentos se
encuentran esos cinco informes. Estos cinco compartimentos serían nuestros punteros y
FA23FF01 FA23FF02
como ocupan un compartimento en el organizador (nuestra memoria) son realmente
variables, pero muy especiales. Estas variables punteros ocupan siempre un tamaño fijo y Un puntero podrá guardar la dirección donde comienza la variable num
contienen el número de compartimento en el que se encuentra el inicio de la información; (FA23FF01):
no contienen la información en sí.
pNum
Así, en nuestro supuesto de que solo trabajemos con cinco informes a la vez,
dispondríamos de cinco compartimentos en los que indicaríamos dónde se encuentran FA23FF01
esos informes que buscamos y, de esta forma, cuando terminemos con ellos y deseemos num
FA23FA21
trabajar con otros, solo tendremos que cambiar el contenido de esos cinco
compartimentos indicando dónde se encuentran los nuevos informes. 27
Por ejemplo:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Se dice que “el puntero real apunta a la variable real precio” cuando contiene la dirección
int main()
de memoria de la variable. Si un puntero contiene una dirección de memoria está
apuntando al dato guardado en dicha dirección. Para poder acceder a él, debe usarse el {
operador asterisco delante del puntero. int edad; // Declaramos una variable entera.
Ejemplo: int *puntero; // Declaramos un puntero a un valor entero.
Es importante no confundir el asterisco que se antepone al nombre del puntero al ¿Para qué usar punteros?
declararlo para indicar que es un puntero (en la zona de declaraciones de variables), y el
Supongamos que queremos intercambiar el valor de dos variables en una función y
asterisco antepuesto al nombre de un puntero dentro del código del programa para
mostrarlas en el programa principal (main).
indicar que se quiere obtener el dato almacenado en la dirección de memoria a la que
apunta el puntero.
Cuando un puntero apunta a una variable, puede obtenerse el valor almacenado en dicha
variable usando el operador asterisco, pero también se puede modificar dicho valor.
Ejemplo:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
Después de la ejecución de intercambio en esta zona de memoria, los valores están
void intercambio a,( int a,int b)
intercambiados, nuestro parámetro a se corresponde con la variable c en la llamada a
{ int t; intercambio contendrá el valor 75, y el parámetro b, correspondiente a d en la función
t = a; main, contendrá el valor 54. Esto es lo que se encuentra almacenado en la zona privada de
memoria de la función.
a = b;
Con este esquema, y cuando la función intercambio termine su ejecución y se devuelva el
b = t;
control al programa principal main, los valores de c y d no habrán cambiaron, puesto que
} los compartimientos o posiciones de memoria x e y no han sido tocados por la función
int main () intercambio, que solo ha actuado sobre el compartimiento z.
{ Ejemplo correcto
int c,d;
Si declaramos ahora nuestra función intercambio como sigue:
c = 54;
d = 75;
{ void intercambio (int *p1,int *p2)
intercambio (c,d);
{
int t;
return 0 ;
t = *p1; /*Metemos en t el contenido de p1 */
}
*p1 = *p2; /* Contenido de p1 = contenido de p2 */
*p2 = t;
Veamos que pasa en la memoria de nuestro ordenador. return;
- Función main() }
- Espacio para la variable c (posición de memoria x)
- Espacio para la variable d (posición de memoria y)
- Inicialización de las variables La llamada en el main sería:
- Intercambio (c,d) Intercambio(&c, &d);
- Fin de main()
Tendremos el mismo esquema de nuestra memoria que antes pero, en lugar de almacenar
- Función intercambio
en la zona privada de la función intercambio para los parámetros los valores 54 y 75,
- Código de la función intercambio
tenemos almacenados en ella los compartimientos en los que se encuentran, esto es,
- Espacio privado para almacenar los parámetros (posición de memoria z)
hemos almacenado las posiciones x e y en lugar de 54 y 75. De esta forma, accedemos
En este último compartimiento almacenamos los valores de nuestros parámetros, que mediante un puntero a las variables c y d del programa principal que se encuentran en las
serán respectivamente 54 y 75.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 7 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 8
posiciones x e y, modificándolas directamente de manera que, al regresar al programa
principal, sus valores se encuentran ahora intercambiados.
Inicialización
Un puntero puede inicializarse con la dirección de una variable existente. Otra Esto es lo mismo que realizar la siguiente asignación:
forma de inicializarlo es con NULL. El valor NULL es una constante definida en la
librería stdio.h que indica que el puntero es nulo, es decir, no apunta a ningún array [0]=5
lado aún.
array [1]=6
Hay una estrecha relación entre punteros y arreglos que hace que puedan usarse
array [2]=6
casi de manera indistinta.
Podríamos cambiar el contenido de la primera posición del arreglo efectuando: entero es de 4 bytes, deberá sumar 4 bytes a la dirección actual.
La aritmética de punteros nos permite acceder a los otros elementos del arreglo:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Para poder hacerlo, necesitamos de tres funciones en C:
Punteros y asignación dinámica de memoria
La función Malloc permite reservar memoria. Se encuentra en la librería stdlib.h y está
definida por:
Introducción
La asignación dinámica de memoria es una característica del lenguaje C. Consiste void *malloc (size_t_size)
en asignar la cantidad de memoria necesaria para almacenar un tipo de dato
Malloc devuelve un puntero genérico.
durante la ejecución del programa, en vez de hacerlo en la fase de compilación de
este. Cuando se crea un programa en el que es necesario manejar memoria La función Sizeof permite calcular cuántos bytes se quieren reservar.
dinámica el sistema operativo divide a la memoria en cuatro partes que son:
sizeof (int) calcula cuantos bytes necesita un entero
Memoria estática
int *p;
*p=10;
Pila (Stack)
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
4.
Guía de ejercicios
1.
2.
6. Escribir un programa efectúe las siguientes operaciones:
a) Declarar una matriz de 3x4 de tipo int. Cargar sus elementos y mostrarla.
b) Declarar un puntero a entero.
c) Asignar al puntero la dirección de la matriz.
d) Recorrer con el puntero la matriz, mostrando la dirección y el contenido de cada
posición.
a) ¿Cuál es el significado de x?
3. b) ¿Cuál es el significado de (x+2)?
c) ¿Cuál es el valor de *x?
d) ¿Cuál es el valor de (*x+2)?
e) ¿Cuál es el valor de *(x+2)?
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
a) ¿Qué valor representa A[4]?
b) ¿Qué valor representa *(&B[3])?
c) ¿Qué valor representa *(B+2)?
d) ¿Qué valor representa A[0]?
e) ¿Qué valor representa *(B+0)?
tipo, agrupadas bajo un único nombre. Esto posibilita su manipulación, por ejemplo, al ser
Introducción
pasadas como argumento o al retornarse de funciones. Se puede usar una estructura para
Hasta ahora hemos trabajado con vectores, o arreglos, que nos permiten agrupar con un
representar un registro de un archivo de empleados: apellido, nombre, documento,
mismo nombre una colección de elementos de un mismo tipo.
legajo, categoría pueden formar una única estructura. Otro ejemplo es para agrupar los
distintos componentes de una fecha: dia, mes, año.
Edades La sintaxis para declarar un tipo estructura es:
struct identificador
Elementos de tipo 23 31 28 … 26
{
tipo1 miembro1;
Sueldos
tipo2 miembro2;
struct fecha {
Puede ocurrir que necesitemos trabajar con colecciones de elementos, pero de distinto
tipo, como los datos personales de un alumno. int dia;
int mes;
Estructura int anio;
};
Nombre Juan Etcheverry 25789 21 5 Cantidad de materias A las variables que componen la estructura se las denomina miembros.
Para definir una variable de tipo estructura se escribe la palabra reservada struct seguida
Número de
Apellido legajo del identificador de la estructura y luego el nombre de la variable:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Por ejemplo
Typedef
La palabra reservada typedef permite redefinir un tipo bajo otro nombre. Es decir, crea
sinónimos. Por ejemplo, podríamos redefinir int como “entero” o podríamos redefinir la
estructura fecha:
int dia;
int mes;
int año;
} tFecha;
En nuestro ejemplo:
p miembroEstructura
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Caso contrario, apuntará al siguiente:
Listas simplemente enlazadas
Dato sig Dato
Concepto 2
1
Una lista es una secuencia de 0 o más nodos de un mismo tipo almacenados en memoria.
Son estructuras lineales: cada nodo (excepto el último) tiene sucesor y tiene anterior
(excepto el primero). Una lista se puede implementar de forma tal que los nodos no estén
físicamente contiguos, aunque se mantenga la relación de sucesión. Una implementación
La estructura de cada nodo en C la definiremos con Nodo
de este tipo es la de lista enlazada.
Una lista es una estructura dinámica ya que no es necesario reservar previamente
memoria como en los arreglos o las matrices. Durante la ejecución del código, se reserva typedef struct Lista{
Habrá que poner acá el tipo de dato que
memoria dinámica para cada nodo de una lista, y se libera cuando ya no se necesita. int clave ; compone la lista. Podríamos tener un int, un
float, un char, un arreglo o una estructura
En una lista enlazada, a diferencia de una lista contigua, cada elemento sabe quién le struct Lista *sig ;
do *
sigue. Podemos hacer la analogía con una sala de espera de un médico: cada persona sabe } Nodo ;
quién le sigue, aun cuando el siguiente no se haya sentado al lado.
dato sig
dato En este módulo vamos a detallar cómo se crea y se muestra una lista.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
- Asignar memoria para un elemento del tipo de dato definido en la estructura y sig 0
4
generar los siguientes nodos hasta que no haya más entrada de datos. 1
Prim
En el código:
En esta línea de código, reservamos memoria. La cantidad la indica sizeof y depende de la void crear (nodo *registro)
{
estructura definida. La dirección que devuelve malloc la recibe el puntero Prim.
registro->num =;
if (registro->num==0)
Prim registro->sig=NULL;
else
{
Registro, esto es: Registro recibe la dirección donde apunta Prim. crear (registro->sig);
}
return;
Prim }
int main()
{
Registro int i=0;
nodo *prin;
prin=(nodo*)malloc(sizeof(nodo));
- Le pedimos el dato al usuario y lo ingresamos a la lista. crear(prin);
mostrar (prin);
return 0;
}
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Mostrar una Lista
r
typedef struct lista { c)
int info;
p lista
struct lista * sig;
}nodo;
3 5 9
d)
lista p
p q i
p=q; qinfo=0;
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
4. Dada la siguiente lista simplemente enlazada que contiene la siguiente información: a) Crear y mostrar la lista (la carga finaliza cuando codmat=0). Se cargan todos los
códigos de materias iguales seguidos y ordenados.
DNI: entero positivo de hasta 8 dígitos.
b) Mostrar los alumnos que pertenecen a una materia.
Nombre: cadena de 15 caracteres
c) Mostrar el código de materia que cuenta con más alumnos.
Tipo de cuenta: carácter (C,E,A)
Saldo: real
Desarrollar un procedimiento que busque en la lista un nodo cuyo DNI sea igual a uno
dado. El mismo devolverá un puntero al nodo hallado o NULL, si no existiera tal nodo.
a) Crear y mostrar la lista. La carga de datos termina con dni=0. La carga de datos se hace
en forma ascendente por dni.
b) Generar otra lista con todos los saldos negativos.
int codmat;
} nodo;
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Insertar y eliminar nodos en una lista simplemente prim
enlazada
aux
Introducción
En este módulo, conoceremos en detalle cómo se insertan y se eliminan nodos en una r
lista. Esto se realiza durante la ejecución del programa, por ello las listas son estructuras
dinámicas: se reserva memoria para insertar datos y se libera la memoria para eliminarlos.
r=aux
aux->sig=r
Inserción
Para insertar un nodo en una lista, hay que seguir lo siguientes pasos:
Para insertar un nodo por cabeza de lista es necesario construir una función que permita
Código de la función insertar por cabeza de lista
devolver la dirección del puntero a cabeza de lista que se ha modificado, para indicárselo
al programa principal.
En la siguiente lista (solo como ejemplo) se detallan los enlaces necesarios para la nodo* insertar1(nodo *r)
{
inserción del nuevo nodo. El puntero a cabeza de lista es prim, pero al llamar a la función nodo *aux;
if()//condicion de insercion
insertar por cabeza de lista, esa dirección la recibe el puntero que denominaremos r. {
aux=(nodo *)malloc(sizeof(nodo));
aux->num=0;//valor a insertar
aux->sig=r;
r=aux;
}
return r;
}
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Inserción de un nodo en cualquier lugar de la de lista Eliminación de nodos en una lista
En este caso, no se modifica la dirección del puntero a cabeza de lista. Para eliminar un nodo en una lista hay que seguir lo siguientes pasos:
registro->sig=aux
aux Al eliminar nodos por cabeza de lista, se debe actualizar la dirección del puntero a cabeza
aux>sig=registro->sig de lista en el programa principal. Para esto, se debe construir una función que devuelva
esta dirección.
Gráficamente:
aux
void insertar2 (nodo *registro)
{nodo *aux=NULL;
while(p->sig!=NULL)
{
if() //condicion de insercion
{ Enlace y liberación de la memora:
aux=(nodo *)malloc(sizeof(nodo));
aux->num=0;//valor a insertar - aux=prim->sig
aux->sig=registro->sig; - free(prim)
registro->sig=aux;
- prim=aux
}
registro=registro->sig;
}
}
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Código de la función eliminar por cabeza de lista Código de la función eliminar en cualquier lugar de la lista
registro
prim
registro->sig=aux aux
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 5 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 6
Guía de ejercicios
3 5 6 9 11 22
5. Desarrollar un procedimiento para invertir una lista lineal, es decir, cambiar sus enlaces
3 5 6 9 11 12 para que aparezcan en orden inverso.
7 generar a partir de ella dos listas distintas, una con los valores pares y otra con los valores
impares.
c) De dos consecutivos, eliminar el primero.
7. Dadas dos listas con la estructura del ejercicio 1, intercalar los elementos de la segunda
lista en la primera, respetando el orden.
3 5 6 9 11 12
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
FILE *fp;
Archivos secuenciales en C fp = fopen(“miarchivo.txt”,”w”);
Dicha función toma un nombre real de archivo (una cadena de texto con la ubicación y el
nombre del archivo), efectúa la negociación correspondiente con el sistema operativo y Si hay un error, fopen retorna un puntero nulo (NULL) así que es conveniente siempre
retorna un puntero a una estructura que contiene la información necesaria para manejar validar si el puntero obtenido no es NULL:
dicho archivo. Permite almacenar información de la conexión entre el archivo físico y el
if((fp = fopen(“miarchivo.txt”, w))== NULL)
programa, por lo que podemos denominarlo el archivo lógico. Entre otras cosas, contiene
la ubicación del buffer, la posición del carácter actual en el buffer, un indicador que printf(”Error al abrir el archivo”);
muestra si el archivo está siendo escrito o leído, y si se ha alcanzado el fin de archivo. La
estructura depende del sistema operativo y se puede ver la estructura tipo FILE en la Lectura y grabación de datos en un archivo
librería stdio.h.
La biblioteca estándar de C provee funciones que facilitan la operación sobre archivos de
Ejemplo: texto. Así, para la lectura de caracteres de un archivo tenemos la función fscanf:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Esta función se usa para obtener valores con un determinado formato. Dichos valores se Código para crear y leer un archivo en C
obtienen del archivo y se almacenan en los argumentos variables.
fopen tiene dos parámetros:
la ubicación y el nombre del
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 4
Guía de ejercicios
1. Generar un vector de 30 números enteros y crear un archivo con los números pares.
Mostrarlo y mostrar el registro número 3.
‐ Código de artículo.
‐ Cantidad de artículos.
‐ Precio unitario.
Generar un vector con el precio total por artículo.
Mostrar el código de artículo con más cantidad.
3. Generar una matriz de 4*4 con números enteros. Calcular en forma recursiva cuántos
números primos hay y cargarlos en un archivo. Mostrar dicho archivo.
4. Generar una matriz de n*n con números enteros. Mostrarla. Generar un archivo con la
suma de los dígitos de cada número de la matriz.
multilistas
Multilistas
Introducción Una lista puede tener, como elemento, otra lista. Por ejemplo: se lee un archivo de texto
A veces es conveniente efectuar algunas modificaciones en la implementación de listas (solo palabras) y se quiere clasificar las palabras por su longitud, para luego efectuar
para facilitar ciertas operaciones sobre ellas. Además, podemos tener algunas cuyos ciertas estadísticas. Como máximo, una palabra puede tener 30 letras. Podríamos hacer
elementos posean, a su vez, otras listas enlazadas. En este módulo se verán algunas de un arreglo de 30 listas de palabras, pero desperdiciaríamos memoria. Entonces, es
esas variantes. conveniente hacer una lista ordenada por tamaño de las palabras y que cada elemento de
esa lista tenga las palabras de ese tamaño.
Al liberar memoria de la lista habrá que recorrer cada nodo de la lista principal y liberar
Listas doblemente enlazadas
cada lista que se encuentra ahí. En el ejemplo anterior, por cada tamaño libero su lista de
Si es necesario recorrer una lista en sentido directo y, luego, en sentido inverso es palabras y luego libero el nodo de ese tamaño.
conveniente que todo nodo tenga un puntero al anterior, además de tener un puntero al
siguiente. Dicha implementación de listas se conoce como listas doblemente enlazadas.
Estructura de una multilista
Supongamos que queremos guardar los vuelos de distintas aerolíneas. En la lista principal
guardaremos el nombre de la aerolínea y, para cada aerolínea, se almacenará el destino
del vuelo, la hora de partida y la hora de llegada. Definimos dos estructuras de la siguiente
manera:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Crear y mostrar una multilista c)
Introducción
Los pasos para crear una multilista son:
Veamos un ejemplo: se necesita generar una mulilista con los nombres de listas de
reproducción y los nombres de cada una de las canciones de esas listas.
d)
b)
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Para mostrar la mulitlista, primero mostramos el nodo de la lista principal (en este caso el
nombre de la lista de reproducción) y, luego, todas las canciones de esta lista para
después pasar al nombre de la siguiente lista de reproducción y así sucesivamente.
Como vimos en módulos anteriores un puntero es una variable que apunta a otra, El puntero p toma la
fácilmente podemos deducir que pueden existir punteros a punteros, y a su vez los dirección de la variable
segundos pueden apuntar a punteros, y así sucesivamente. Estos punteros se declaran a y el puntero q toma
colocando tantos asteriscos (‘*’) como sea necesario. Para especificar que una variable es el valor del puntero p,
un puntero a un puntero, la sintaxis que debemos utilizar es la siguiente: es decir 10
Tipo **variable;
donde Tipo especifica el tipo de dato apuntado después de una doble indirección. ¿Pero
qué es una doble indirección? Veamos el siguiente ejemplo:
El puntero q toma el contenido de la
int a, *p, **pp;
variable a. Esto es, la dirección de memoria
a=10;
donde se almacenó a (&a) ,*(&a) toma el
p=&a; //Puntero que apunta al dato contenido de a.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
Colas Pilas
Introducción Introducción
Una cola (queue) es una colección de elementos ordenada cronológicamente. Cada Una pila (stack) es una colección de elementos ordenada por orden de llegada. los
elemento se ubica detrás del anterior. El primero en ser utilizado es el que primero llegó. El elementos se añaden o quitan por la parte superior de la pila (la cima o tope). El último
primer elemento en entrar es el primero en ser eliminado o utilizado. Por eso estas elemento en entrar es el primero en ser eliminado. Por eso estas colecciones se denominan
colecciones se denominan FIFO (First In, First Out). LIFO (Last In, First Out).
Las aplicaciones de una cola son muy frecuentes en la vida diaria y en las ciencias de Las aplicaciones de una pila son muy frecuentes en la vida diaria y en las ciencias de
la computación. En la vida diaria, hacemos cola para el colectivo, en el banco, en el cine. En la computación: una pila de platos, las llamadas a funciones se manejan con una pila en
sistemas se manejan colas de impresión, colas de procesos, etc. memoria, los compiladores usan pilas para evaluar las expresiones, etc.
Implementación mediante listas simplemente enlazadas. Implementación mediante listas simplemente enlazadas.
Las colas se pueden implementar con arreglos o con listas implementadas con Las pilas se pueden implementar con arreglos o con listas implementadas con
punteros. Realizaremos esta última implementación. punteros. Realizaremos esta última implementación.
Los elementos que se pueden almacenar en una cola pueden ser de cualquier tipo. Los elementos que se pueden almacenar en una pila pueden ser de cualquier tipo.
La inserción de un elemento en la cola se la denomina ENCOLAR o ENQUEUE. En definitiva, trabajaremos con un caso particular de lista: una lista de elementos donde la
inserción y la eliminación se hace siempre por el mismo lugar.
La eliminación de un elemento de la pila se la denomina DESENCOLAR o DEQUEUE
La inserción de un elemento en la pila se la denomina APILAR o PUSH.
La observación (sin eliminación) del primer elemento de la cola la denominaremos
La eliminación de un elemento de la pila se la denomina DESAPILAR o POP.
PRIMERO o FIRST.
La observación (sin eliminación) del elemento superior de la pila la denominaremos
Para lograr una implementación eficiente, debemos poder acceder fácilmente al
TOPE o TOP.
lugar de inserción, y también fácilmente obtener el próximo elemento a eliminar.
Para ello, utilizaremos dos punteros: uno al inicio de la cola (apunta al primero a
eliminar) y otro al último (apunta al último elemento de la cola) Ejemplo:
Vacía:
MiPila = NULL
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3
Guía de Ejercicios Guía de Ejercicios
A: entero. A: entero.
SIG: puntero al próximo elemento de la pila. SIG: puntero al próximo elemento de la pila.
y calcular:
1) La cantidad de números múltiplos de 3. 1) Desarrollar un programa que permita dado un entero N, asignar el valor I al
2) El promedio de aquellos números divisores de 4. elemento N-ésimo desde la parte superior de la pila, volviendo a dejar los N-1
3) La sumatoria de aquellos números múltiplos del primer elemento ingresado a la pila. elementos inferiores donde se encontraban.
4) El número máximo y su posición en la pila.
5) El número mínimo y su posición en la pila.
2) Desarrollar un programa que permita eliminar el nodo que contenga la información
6) Ingresar un numero por teclado y calcular la cantidad de veces que está en la pila.
Z de la pila.
Si no está, mostrar una leyenda.
A: entero. 4) Desarrollar un programa que permita dadas dos pilas, concatenarlas eliminando los
SIG: puntero al próximo elemento de la cola. elementos repetidos.
y calcular:
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1
Para los siguientes ejercicios crear una cola con la siguiente información:
A: entero.
Los árboles binarios tienen, por cada nodo, como máximo dos hijos a los que llamaremos
Introducción
subárbol izquierdo y subárbol derecho.
Un árbol (tree) es una estructura no lineal que se presenta tanto en la vida cotidiana como
Un árbol binario de búsqueda es aquel en el que, para cualquier nodo, su valor es mayor
en la ciencia de la computación: árboles genealógicos, árbol de búsqueda, árbol de juegos,
que los valores de los nodos en su subárbol izquierdo y menor que los valores de los
un organigrama. Es una estructura no lineal que parte de un primer elemento, llamado
nodos en el subárbol derecho.
raíz, y luego se “ramifica” en dos o más líneas. Un árbol es un conjunto de nodos y líneas
(grafo). Cada nodo contiene información.
Implementación mediante listas simplemente enlazadas.
Características de los árboles Los árboles binarios se pueden implementar con arreglos o con estructuras enlazadas con
punteros. Realizaremos esta última implementación.
Los árboles tienen las siguientes propiedades:
Cada nodo tendrá la siguiente estructura:
‐ Existe un nodo distinguido llamado raíz.
‐ Todos los nodos, excepto la raíz, tienen una sola línea de entrada.
‐ Si hay una ruta de a a b, entonces b es hijo de a. typedef struct Arbol{
‐ Los nodos que no tienen hijos (nodos terminales) se llaman nodos hoja. int clave;
‐ El grado de un nodo es la cantidad de hijos que tiene. struct nodoArbol *izq;
struct nodoArbol *der;
‐ La fila en que reside un nodo es su nivel.
‐ La altura de un árbol es la cantidad de líneas en una ruta que empieza en la raíz y } *nodoarbol;
termina en el nodo más lejano. Un árbol que solo tiene un nodo (el raíz) tiene altura 0.
Con respecto al recorrido, como es una estructura no lineal, hay distintas maneras de
Tipos de árboles recorrer el árbol:
Hay distintos tipos de árbol: en orden:
Binario: todos sus nodos tienen como máximo dos hijos. ‐ Se recorre el subárbol izquierdo.
‐ binario de búsqueda.
‐ Se lee la raíz.
‐ binario de expresión. ‐ Se recorre el subárbol derecho.
‐ binario equilibrado. en preorden:
‐ AVL. ‐ Se lee la raíz.
Árbol B: pueden tener tres o más hijos cada nodo. ‐ Se recorre el subárbol izquierdo.
‐ Árbol B* ‐ Se recorre el subárbol derecho.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2
en postorden:
‐ Se recorre el subárbol izquierdo. Guía de ejercicios
‐ Se recorre el subárbol derecho.
‐ Se lee la raíz.
1. Diseñar una función que, dado un árbol binario y un valor, determine si el valor
pertenece al árbol.
2. Diseñar una función que, dado un árbol binario, calcule su cantidad de nodos.
raíz
3. Diseñar tres funciones para el recorrido de un árbol binario (pre orden, orden y post
8 orden).
4. Diseñar una función que, dado un árbol binario de búsqueda, calcule el promedio de
aquellos nodos múltiplos de la raíz.
5. Diseñar una función que, dado un árbol binario de búsqueda, calcule la cantidad de
nodos hojas divisores de la raíz.
6 12
6. Diseñar una función que, dado un árbol binario de búsqueda, calcule la sumatoria de
aquellos nodos pares con un solo hijo.
7. Diseñar una función que, dado un árbol binario de búsqueda, calcule la cantidad de
nodos impares con dos hijos.
10 13
Muy importante: El orden en que se ingresan los valores determina la forma del árbol.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 3 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1
Ejercicio: Modelo de Parcial
Dada:
Lista
Se pide:
Mostrar la lista.
No usar banderas.
Lista
Ejemplo:
Lista original:
5 7 14 6 2 9 3 21 3 6 2 4 8
Nueva Lista:
5 7 9 3 21 3
Promedio: 6
Lista Modificada
7 9 21
No usar banderas.
Lista 1
Ejemplo:
Ingreso:
potencia (int)
Lista 2
potencia (int)
No usar banderas.
© Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 1 © Universidad de Palermo. Prohibida la reproducción total o parcial de imágenes y textos. 2