jueves, 10 de julio de 2014

EVAP 7





METODOS DE ORDENAMIENTO




METODOS DE ORDENAMIENTO 

Debido a que las estructuras de datos son utilizadas para almacenar información, para poder recuperar esa información de manera eficiente es deseable que aquella esté ordenada. Existen varios métodos para ordenar las diferentes estructuras de datos básicas.
En general los métodos de ordenamiento no son utilizados con frecuencia, en algunos casos sólo una vez. Hay métodos muy simples de implementar que son útiles en los casos en dónde el número de elementos a ordenar no es muy grande (ej, menos de 500 elementos). Por otro lado hay métodos sofisticados, más difíciles de implementar pero que son más eficientes en cuestión de tiempo de ejecución.

Los métodos sencillos por lo general requieren de aproximadamente n x n pasos para ordenar n elementos.

Los métodos simples son: insertion sort (o por inserción directa) selection sort, bubble sort, y shellsort, en dónde el último es una extensón al insertion sort, siendo más rápido. Los métodos más complejos son el quick-sort, el heap sort, radix y address-calculation sort. El ordenar un grupo de datos significa mover los datos o sus referencias para que queden en una secuencia tal que represente un orden, el cual puede ser numérico, alfabético o incluso alfanumérico, ascendente o descendente.

Se ha dicho que el ordenamiento puede efectuarse moviendo los registros con las claves. El mover un registo completo implica un costo, el cual se incrementa conforme sea mayor el tamaño del registro. Es por ello que es deseable evitar al máximo el movimiento de los registros. Una alternativa es el crear una tabla de referencias a los registros y mover las referencias y no los datos. A continuación se mostrarán los métodos de ordenamiento empezando por el más sencillo y avanzando hacia los mas sofisticados 
La eficiencia de los algoritmos se mide por el número de comparaciones e intercambios que tienen que hacer, es decir, se toma n como el número de elementos que tiene el arreglo a ordenar y se dice que un algoritmo realiza O(n2) comparaciones cuando compara n veces los n elementos, n x n = n2. 

ORDENAMIENTO DE BURBUJA

La Ordenación de burbuja (Bubble Sort en inglés) es un sencillo algoritmo de ordenamiento. Funciona revisando cada elemento de la lista que va a ser ordenada con el siguiente, intercambiándolos de posición si están en el orden equivocado. Es necesario revisar varias veces toda la lista hasta que no se necesiten más intercambios, lo cual significa que la lista está ordenada. Este algoritmo obtiene su nombre de la forma con la que suben por la lista los elementos durante los intercambios, como si fueran pequeñas "burbujas". También es conocido como el método del intercambio directo. Dado que solo usa comparaciones para operar elementos, se lo considera un algoritmo de comparación, siendo el más sencillo de implementar.

Burbuja

#include<stdio.h> 
#include<conio.h> 
int a[3]={3,2,1}; 
int i,j,aux,n=3; 
void main(){ 
clrscr(); 
for(i=0;i<=n;i++){ 
for(j=0;j<n-1;j++){ 
if(a[j]>a[j+1]){ 
aux=a[j]; 
a[j]=a[j+1]; 
a[j+1]=aux; 



for(i=0;i<3;i++) 

printf("%d",a);
}
getch();

ORDENAMIENTO SHELL El ordenamiento Shell (Shell sort en inglés) es un algoritmo de ordenamiento. El método se denomina Shellen honor de su inventor Donald Shell. Su implementación original, requiere O(n2) comparaciones e intercambios en el peor caso. Un cambio menor presentado en el libro de V. Pratt produce una implementación con un rendimiento de O(n log2 n) en el peor caso. Esto es mejor que las O(n2) comparaciones requeridas por algoritmos simples pero peor que el óptimo O(n log n). Aunque es fácil desarrollar un sentido intuitivo de cómo funciona este algoritmo, es muy difícil analizar su tiempo de ejecución. El algoritmo Shell sort mejora el ordenamiento por inserción comparando elementos separados por un espacio de varias posiciones. Esto permite que un elemento haga "pasos más grandes" hacia su posición esperada. Los pasos múltiples sobre los datos se hacen con tamaños de espacio cada vez más pequeños. El último paso del Shell sort es un simple ordenamiento por inserción, pero para entonces, ya está garantizado que los datos del vector están casi ordenados.
 
#include<stdio.h> 
#include<conio.h> 
int a[5]; 
int n=5; 
void main() 

int inter=(n/2),i=0,j=0,k=0,aux; 
clrscr(); 
for (i=0; i<5; i++) 

printf("INSERTA UN VALOR DEL INDICE %d", i); 
scanf("%d",& a);
}
while(inter>0){
for(i=inter;i<n;i++)
{
j=i-inter;
while(j>=0) {
k=j+inter;
if(a[j]<=a[k]){
j--;
}
else{
aux=a[j];
a[j]=a[k];
a[k]=aux;
j=j-inter;
}
}
}
inter=inter/2;
}
for(i=0;i<5;i++)
{
printf("%d n",a);
getch();
}
}  
 
ORDENAMIENTO POR INSERCIÓN  
El ordenamiento por inserción (insertion sort en inglés) es una manera muy natural de ordenar para un ser humano, y puede usarse fácilmente para ordenar un mazo de cartas numeradas en forma arbitraria. Requiere O(n²) operaciones para ordenar una lista de n elementos.

Inicialmente se tiene un solo elemento, que obviamente es un conjunto ordenado. Después, cuando hay k elementos ordenados de menor a mayor, se toma el elemento k+1 y se compara con todos los elementos ya ordenados, deteniéndose cuando se encuentra un elemento menor (todos los elementos mayores han sido desplazados una posición a la derecha) o cuando ya no se encuentran elementos (todos los elementos fueron desplazados y este es el más pequeño). En este punto se inserta el elemento k+1 debiendo desplazarse los demás elementos.



Inserccion 
#include<stdio.h> 
#include<conio.h> 
int a[4]={4,1,7,2}; 
int n=4; 
int i,j,aux; 
void main(){ 
clrscr(); 
for(i=1;i<n;i++) 

j=i; 
aux=a;
while(j>0 && aux<a[j-1])
{
a[j]=a[j-1];
j--;
}
a[j]=aux;
}
for(i=0;i<4;i++)
{
printf("%d",a);
}
getch();


ORDENAMIENTO POR SELECCION  
El ordenamiento por selección (Selection Sort en inglés) es un algoritmo de ordenamiento que requiere operaciones para ordenar una lista de n elementos.

Su funcionamiento es el siguiente:

  • Buscar el mínimo elemento de la lista
  • Intercambiarlo con el primero
  • Buscar el mínimo en el resto de la lista
  • Intercambiarlo con el segundo
Y en general:

  • Buscar el mínimo elemento entre una posición i y el final de la lista
  • Intercambiar el mínimo con el elemento de la posición i
De esta manera se puede escribir el siguiente pseudocódigo para ordenar una lista de n elementos indexados desde el 1:

para i=1 hasta n-1
    minimo = i;
    para j=i+1 hasta n
        si lista[j] < lista[minimo] entonces
            minimo = j /* (!) */
        fin si
    fin para
    intercambiar(lista[i], lista[minimo])
fin para 
 

 
  Seleccion  #include<stdio.h>  #include<conio.h>  int x[4]={1,4,8,6};  int n=4,j=0,i=0;  int temp=0,minimo=0;  void main() clrscr();  for(i=0;i<n-1;i++)  minimo=i;  for(j=i+1;j<n;j++)   if(x[minimo] > x[j])  minimo=j;   temp=x[minimo]; x[minimo]=x x=temp;  }  for(i=0;i<n;i++)  {  printf("%d",x);  }  getch();  }


EVAP 6



Matrices


Una matriz es una estructura de datos, o más técnicamente, un espacio de memoria que permite almacenar una colección de elementos, todos del mismo tipo. La diferencia con los arreglos está en que, en las matrices, los elementos no están organizados linealmente sino que su organización es bidimensional, es decir, en filas y columnas. Conviene imaginar una matriz como una organización de celdas de memoria, o casillas, en cada una de las cuales se puede guardar un elemento de la colección. Además, es usual dibujarla como lo ilustra la figura siguiente:



La numeración de las filas y las columnas determina que cada una de las casillas de una matriz tiene asociados dos números que la identifican de manera única. A estos números se les llama índice de fila e índice de columna, respectivamente. En el seudolenguaje, y también en C y C++, las filas y las columnas se numeran desde 0.

Los lenguajes como C y C++, permiten que el programador declare matrices de cualquier tipo y prácticamente de cualquier tamaño. En el seudolenguaje, un matriz se declara usando el siguiente formato:

<NOMBRE> : matriz [<N>][<M>] de <TIPO>

En este formato aparecen en mayúsculas y entre los caracteres < y > los componentes que el programador puede determinar. Así por ejemplo, si se quiere declarar una matriz con nombre mat, de dimensión 15x4 y que pueda almacenar datos de tipo caracter, se debe escribir la siguiente línea.

mat : matriz [15][4] de caracter

Según el formato anterior, el programador debe bautizar la matriz (ponerle un nombre significativo), debe decir cuál es su dimensión, y también debe decir de qué tipo son los elementos que almacenará.

Enseguida se dan algunos ejemplos de declaraciones de matrices.

• Si se necesita guardar la información relacionada con el tablero de un juego de tic tac toe (el tradicional triqui), se puede declarar la siguiente matriz:

tablero : matriz [3][3] de caracter

Si se requiere guardar las notas que han sacado 35 estudiantes en los 5 talleres y en los 5 laboratorios del curso de Programación de Computadores se pueden declarar las siguientes matrices.

talleres : matriz [35][5] de real
laboratorios : matriz [35][5] de real

Note que, en ambas matrices, cada fila guarda las notas de un estudiante del curso.

• Si se quiere guardar las letras que conforman una sopa de letras, como aquellas que vienen en los pasatiempos, se puede declarar la siguiente matriz.

sopa : matriz [10][15] de caracter

Note que la sopa de letras más grande que se puede guardar es de 10 filas por 15 columnas.

Los índices se crearon para permitir que el programador se pueda referir, de forma específica y directa, a una cualquiera de las casillas de la matriz, tanto para guardar un dato en esa casilla, como para obtener el dato almacenado en ella. En el seudolenguaje, para referirse a una casilla particular de una matriz se debe seguir el siguiente formato:

<NOMBRE>[<INDICE-DE-FILA>][<INDICE-DE-COLUMNA>]

Es decir, se debe escribir el nombre de la matriz seguido por el índice de fila y por el índice de columna, ambos entre paréntesis cuadrados, de la casilla que se quiere consultar.

Ejemplo completo

Una matriz mágica es una matriz cuadrada (tiene igual número de filas que de columnas) que tiene como propiedad especial que la suma de las filas, las columnas y las diagonales es igual. Por ejemplo:

2 7 6
9 5 1
4 3 8


En esta matriz las sumas son 15.

Considere el problema de construir un algoritmo que compruebe si una matriz de datos es mágica o no, y en caso de que sea mágica escribir la suma. El usuario ingresa el tamaño de la matriz máximo hasta 10. Además debe guardar la suma de las filas, las columnas y las diagonales en un arreglo en el orden siguiente:

Figura con un arreglo de n columnas.

Las entradas (datos conocidos) para el algoritmo son:

􀂾 La dimensión de la matriz.
􀂾 Los números que contiene la matriz.

La salida esperada (datos desconocidos) es:

􀂾 La matriz es mágica o no, y si es mágica cuál es el valor de la suma.

En este problema, los arreglos son útiles para guardar los datos que conforman la matriz.
Los números que contiene la matriz se pueden guardar en una variable entera.

La siguiente gráfica resume las entradas y salidas del algoritmo que se pretende diseñar.
Además bautizan todas las variables mencionadas.

Las condiciones iniciales y finales se pueden expresar mediante las cláusulas REQUIERE y GARANTIZA:

REQUIERE:

La dimensión de la matriz que debe ser máximo 10x10
Cada elemento de la matriz debe ser un número entero.

GARANTIZA:

Muestra en pantalla si es mágica o no, y si lo es cual es el valor de la suma.
Una primera versión del algoritmo puede ser la siguiente:

Inicio
Paso 1: Leer el tamaño de la matriz
Paso 2: Leer los elementos de la matriz
Paso 3: Determinar si la matriz es mágica o no
Paso 4: Si la matriz es mágica mostrar el valor de la suma.
Fin

Los pasos 1 y 2 son interacciones con el usuario que permiten capturar los datos de entrada. La versión inicial se puede refinar detallando estos pasos y además defiendo las variables para hacerlos:

Procedimiento principal

variables
i, j, aux, tam, suma: enteros //i señala las filas
//j señala las columnas
magica: matriz [10][10] de enteros
Inicio
escribir(“Por favor digite el número de filas de la matriz (entre 2 y 10): ”)
leer(tam)

para (i=0 hasta tam-1) hacer
para(j=0 hasta tam-1) hacer
escribir(“Por favor digite el dato en la posición”)
escribir(i,j)

leer(magica[i][j])

fin_para
fin_para
Paso 3

Paso 4

Se puede observar que el primer ciclo para tiene como contador la variable i, esto indica que se llenará la matriz por filas, el segundo ciclo para que tiene como contador la variable j, recorrerá la fila columna a columna para ubicar allí el dato correspondiente.

La parte nuclear de la solución es el paso 3. En este problema en particular se sabe que el número de filas y de columnas es igual y que hay dos diagonales. Para el ejemplo mostrado al inicio sería 3 filas, 3 columnas y dos diagonales. Para almacenar las sumas en un arreglo este tendrá una dimensión de 2*tam+2. La     declaración del arreglo sumas es:

sumas: arreglo [22] de enteros


Ahora para calcular las sumas se puede hacer lo siguiente:

Paso 3.1: Inicializar el arreglo de sumas en cero.
Paso 3.2: Sumar fila por fila, columna por columna y las diagonales y guardar su valor en el arreglo.

para(i=0 hasta 2*tam+2) hacer
sumas[i]:=0
fin_para

//Sumas correspondientes a las filas

para(i=0 hasta tam-1) hacer
         para(j=0 hasta tam-1) hacer
         sumas[i]=magica[i][j]+sumas[i]
fin_para

fin_para

//Sumas correspondientes a las columnas

para(j=0 hasta tam-1) hacer
para(i=0 hasta tam-1) hacer
sumas[j+tam]=magica[i][j]+sumas[j+tam]
fin_para

fin_para

//Sumas correspondientes a las diagonales

para(i=0 hasta tam-1) hacer
sumas[2*tam]=magica[i][i]+sumas[2*tam]
fin_para
para(i=0 hasta tam-1) hacer
sumas[2*tam+1]=magica[i][(tam-1)-i]+sumas[2*tam+1];
fin_para

sábado, 21 de junio de 2014

EVAP 5


VECTORES



Introducción

 En C a los vectores también se les llama arrays o arreglos. 
 Los arrays son :
– Conjuntos de variables del mismo tipo… 
– … que tienen el mismo nombre… 
– … y se diferencian en el índice 
 Es un modo de manejar una gran cantidad de datos del mismo tipo bajo un mismo nombre             o identificador. 
 Para realizar operaciones matemáticas sobre un array (como en Matlab) debemos operar sobre 
cada elemento del array .
Los vectores son una forma de almacenar datos que permiten contener una serie de valores del mismo tipo, cada uno de los valores contenidos tiene una posición asociada que se usará para accederlos. Está posición o índice será siempre un número entero positivo.
En C la cantidad de elementos que podrá contener un vector es fijo, y en principio se define cuando se declara el vector. Los vectores se pueden declarar de la siguiente forma:
 tipo_elemento nombre[largo];
Esto declara la variable nombre como un vector de tipo_elementos que podrá contener largo cantidad de elementos, y cada uno de estos elemento podrá contener un valor de tipo tipo_elemento.
Por ejemplo:
 double valores[128];
En este ejemplo declaramos un vector de 128 elementos del tipo double, los índices de los elementos irían entre 0 (para el primer elemento y 127 para el último).
De la misma forma que con las otras declaraciones de variables que hemos visto se le puede asignar un valor iniciar a los elementos.
O también se pueden declarar:
 tipo_elemento nombre[largo]={valor_0, valor_1, valor_2};
En caso estamos asignadole valores a los primeros 3 elementos del vector nombre. Notar que largo debe ser mayor o igual a la cantidad de valores que le estamos asignando al vector, en el caso de ser la misma cantidad no aporta información, por lo que el lenguaje nos permite escribir:
 tipo_elemento nombre[]={valor_0, valor_1, valor_2};
Que declarará nombre como el vector de largo 3.
Para acceder a un elemento accederemos a través de su posición. Es decir:
 tipo_elemento elemento;
 ...
 elemento = nombre[2];
Asumiendo que tenemos el vector anterior definido estaríamos guardando valor_2 en elemento.
Veamos algunos ejemplos:
/*
 * Ejemplo : El producto escalar de dos vectores
 */
#include <stdio.h>
 
double producto_escalar(double v1[], double v2[], int d);
 
int main()
{ 
 const int largo = 3;
 double vector_1[] = {5,1,0};
 double vector_2[] = {-1,5,3};
 
 double resultado = producto_escalar(vector_1, vector_2, largo);
 
 // imprime el resultado
 printf("(%f, %f, %f) . (%f, %f, %f) = %f\n",
  vector_1[0], vector_1[1], vector_1[2],
  vector_2[0], vector_2[1], vector_2[2],
  resultado);
 return 0;
}
 
/* producto escalar entre dos vectores */
double producto_escalar(double v1[], double v2[], int d)
{
 double resultado = 0;
 int i;
 for (i=0; i < d; i++) {
  resultado += v1[i] * v2[i];
 }
 return resultado;
}
En el ejemplo anterior usamos los vectores de C para representar vectores matemáticos y calcular el producto escalar entre ellos. Una peculiaridad que se puede notar es que al recibir un arreglo en una función no se especifica el largo, volveremos a esto en un capítulo posterior.
Otra función clásica es la búsqueda de un máximo o mínimo, que podemos escribirla de la siguiente manera:
int buscar_maximo(double valores[], int num_valores)
{
 int maximo_pos = 0;
 for (int i = 1; i < num_valores; i++) {
  if (valores[i] > valores[maximo_pos]) {
   maximo_pos = i;
  }
 }
 return maximo_pos;
}
Otro ejemplo sencillo, calcular el promedio de los valores.
double promedio(double valores[], int largo)
{
 double suma=0;
 for (int i=0;i<largo;i++) {
  suma+=valores[i];
 }
 return suma/largo;
}
Cuando una función recibe un vector por parámetro y cambia su contenido y el cambio es permanente (se ve aún fuera de la función). Esto puede parecer extraño después del énfasis que pusimos en resaltar que todos los parámetros de una función se reciben por valor, pero se aclarará en el siguiente capitulo.
Mientras tanto usemos esto para definir una función que le aplique otra función que recibe por parámetro a cada elemento del vector, guardando el resultado en el mismo vector y una llamada de ejemplo a esta.
void cuadrados(double vector[], int largo)
{
 for (int i=0;i<largo;i++) {
  vector[i]=cuadrado(vector[i]);
 }
}
...
double cuadrado(double valor) {
 return valor*valor;
}
...
 cuadrados(elementos,num_elem);
...
De la misma forma que venimos usando vectores de tipos básicos, podemos tener vectores de vectores, estos se declaran de la siguiente forma:
int matriz[3][7];
int tabla[3][4]={ { 1, 2, 3, 4}, { 5, 6, 7, 8}, /* los espacios y saltos de líneas no son tomados en cuenta */ { 9,10,11,12} }; double v[2][2][2]; ... printf("tabla[0][1]: %i\n", tabla[0][3]); // Imprime 4 printf("tabla[2][0]: %i\n", tabla[2][0]); // Imprime 9 ...
En este ejemplo tabla es un vector de longitud 3, cuyos elementos son vectores de longitud 4 de elementos de tipo int.
En resumen, suponiendo que v[n] es un vector de cualquier tipo de dato con n cantidad de posiciones, al vector v se le aplican las siguientes reglas:
  1. La primera posición siempre será v[0]
  2. La última posición es v[n-1]
  3. En versiones previas a C99 n es una constante definida antes de la declaración de v[n]

sábado, 10 de mayo de 2014

EVAP 4

Algorítmica y Lenguajes de Programación
Funciones y subrutinas





Funciones y subrutinas. Introducción


  • El diseño descendente permite obtener un programa que resuelva un problema dividiendo este en subproblemas cada vez más sencillos.
  • Cada subproblema tiene asociado un pseudocódigo de alto nivel compuesto por acciones no primitivas.
  • Cuando una de estas acciones no primitivas se repite en varios puntos del algoritmo es interesante darle un nombre y reutilizarla.
  • Estas acciones con nombre se denominan subprogramas, pudiendo ser, a su vez, funciones y subrutinas.


Funciones y subrutinas. Ventajas

Las ventajas de los subprogramas son múltiples:


  • Facilitan la modularidad y estructuración de los algoritmos.
  • Facilitan la lectura e inteligibilidad de los algoritmos.
  • Permiten economizar el esfuerzo del programador al permitir reutilizar el mismo código en varios puntos del mismo algoritmo.
  • Facilitan la depuración y mantenimiento de los programas.


Funciones y subrutinas. Funciones (i)


  • Las funciones son subprogramas con 0 ó más argumentos que siempre devuelven un valor de retorno.
  • Las funciones pertenecen entonces a un tipo determinado.
  • La invocación de una función puede formar parte de:
               Una expresión.
               La parte derecha de una asignación.
  • Una invocación de una función no puede formar:
               Una sentencia aislada.
               La parte izquierda de una asignación.

Funciones y subrutinas. Funciones (ii)
  • Funciones intrínsecas:
  • Las funciones intrínsecas son proporcionadas directamente por el lenguaje de programación.
  • La mayor parte de funciones intrínsecas son funciones matemáticas como la raíz cuadrada, los logaritmos o funciones trigonométricas.
  • Por cada una de las funciones intrínsecas más habituales en FORTRAN existe una función o un operador equivalentes en la notación algorítmica.

Funciones y subrutinas. Funciones (iii)
  • Funciones de usuario (i):

                 En muchas ocasiones el usuario estará interesado en definir sus propias funciones.
                 Las funciones de usuario deben estar definidas dentro del algoritmo principal:

definiciones de constantes                                                
declaraciones de variables
      inicio
          sentencias del algoritmo
 DEFINICIONES DE FUNCIONES
fin


program nombre_programa
    variables y constantes
    sentencias del programa
contains
DEFINICIONES DE FUNCIONES
end


Funciones y subrutinas. Funciones (iv)
  • Funciones de usuario (ii):
  • Para definir una función es necesario:

                   El nombre de la función.
                   El tipo de la función.
                   Los argumentos de la función y el tipo de los mismos.

  • Sintaxis de definición de funciones:


tipo funcion nombre (arg1ÎÎtipo1,..., argNÎÎtipoN)
inicio
sentencia1
sentencia2
...
sentenciaN
fin


tipo function nombre (arg1, ..., argN)
declaración arg1
...
declaración argN
sentencia1
sentencia2
...
sentenciaN
end


Funciones y subrutinas. Funciones (v)


  •            Ejemplos de funciones de usuario:


logical function siempreVerdad ()
siempreVerdad=.true.
end function

integer function maximo (a, b)
integer a,b
if (a>b) then
maximo=a
else
maximo=b
end if
end function

Funciones y subrutinas. Ámbitos (i)
  • Las funciones pueden acceder a una serie de variables:
  •          Argumentos.
  •          Variables definidas dentro de la función.
  • Estas variables se denominan locales por contraposición a las variables declaradas dentro del algoritmo principal denominadas globales.
  • Las variables locales sólo “existen” mientras la función se está ejecutando.
  • Si una variable local se denomina igual que una variable global la función sólo puede acceder a la primera.
  • En FORTRAN las subrutinas pueden modificar los valores de los argumentos recibidos; este fenómeno se denomina efecto lateral y hay que manejarlo con precaución.


Funciones y subrutinas. Subrutinas (i)
  • Subrutinas o procedimientos:
          Las subrutinas son subprogramas con 0 ó más argumentos que nunca devuelven un valor de retorno.
          Las subrutinas, por tanto, no tienen tipo.
          La invocación de una subrutina sólo puede aparecer en una sentencia de llamada a procedimiento                 (llamar/call).
          Una invocación de subrutina no puede formar:
                                         
                                          Una expresión.
                                          La parte derecha de una asignación.
                                          La parte izquierda de una asignación.
   
Funciones y subrutinas. Subrutinas (ii)
  • Ejemplos de subrutinas:


accion intercambio (a,b ÎÎ  entero)
inicio
temporal ÎÎ  entero
temporal ßß a
a ßß b
b ßß temporal
fin


Funciones y subrutinas. Resumen (i)

1. Los subprogramas facilitan la utilización de técnicas de diseño descendente para la construcción de               programas.
2. Los subprogramas:
          · Facilitan la modularidad y estructuración de los algoritmos.
          · Facilitan la lectura e inteligibilidad de los algoritmos.
          · Permiten una economización del esfuerzo del programador al poder escribir
            código reutilizable en muchas partes de un mismo algoritmo.
          · Facilitan la depuración y mantenimiento de los programas.
3. Los subprogramas pueden ser funciones y subrutinas.
4. Las funciones son subrutinas con 0 ó más argumentos y que devuelven un único valor de retorno.
5. Las funciones pueden formar parte de expresiones o aparecer en la parte derecha de una sentencia de           asignación pero nunca pueden constituir una sentencia aislada o aparecer en la parte izquierda de una           asignación.
6. Las funciones son invocadas mediante su nombre seguido de los argumentos entre paréntesis.

Funciones y subrutinas. Resumen (ii)

7. Existen dos tipos de funciones: intrínsecas y definidas por el usuario.
8. Las funciones intrínsecas son funciones de uso muy común: raíz cuadrada, logaritmos, funciones               trigonometricas, etc
9. Las funciones definidas por el usuario deben describirse dentro del algoritmo principal.
10. Los argumentos y variables declaradas dentro del cuerpo de una función (o subrutina) se denominan             variables locales, las variables declaradas dentro del programa principal son variables globales. Los
      subprogramas tienen acceso a las variables globales aunque en el caso de que una variable local se               denomine igual que una variable global tiene preferencia la primera.
11. Las subrutinas son subprogramas que no devuelven ningún resultado; sin embargo, gracias a la utilización       de los efectos laterales es posible su utilización para permitir el “retorno” de varios resultados.