Академический Документы
Профессиональный Документы
Культура Документы
Curso 20092010
INTRODUCCIN.
Hasta ahora, los datos manejados en los programas han sido los denominados datos simples (numricos, carcter,...). En numerosas ocasiones es necesario utilizar un conjunto de datos relacionados entre s. Por ejemplo, si se quiere manipular una lista de 100 edades de personas, es conveniente tratar este conjunto de datos de forma unitaria en lugar de utilizar 100 variables, una para cada edad. Un conjunto de datos homogneos (del mismo tipo) que se tratan como una sola unidad se denomina estructura de datos. Si una estructura de datos reside en la memoria central del ordenador se denomina estructura de datos interna. Recprocamente, si reside en un soporte externo, se denomina estructura de datos externa. Las estructuras de datos internas pueden ser de dos tipos: - Estticas: Tienen un nmero fijo de elementos que queda determinado desde la declaracin de la estructura en el comienzo del programa. - Dinmicas: Tienen un nmero de elementos que vara a lo largo de la ejecucin del programa. La estructura de datos interna ms importante, desde el punto de vista de su utilizacin, es un array (array), que existe en casi todos los lenguajes de programacin. Esta estructura se corresponde con los conceptos matemticos de vector (1 dimensin), matriz (2 dimensiones) y poliedro (3 o ms dimensiones). Un array consiste en un nmero fijo y finito de elementos, todos del mismo tipo y bajo un nombre comn para todos ellos.
El nombre de un array es un identificador comn para todos sus elementos distinguindose cada uno por una lista de ndices que complementan a dicho nombre para referenciarlos individualmente. Se denomina componentes a los elementos de un array. Un array se puede estructurar en una, dos o ms dimensiones, segn el nmero de ndices necesarios para acceder a sus elementos. Por tanto, la dimensin de un array coincide con el nmero de ndices que utiliza. Longitud o tamao de un array es el nmero de componentes que contiene. El tipo de un array es el tipo de sus componentes (numricos, carcter, cadena, etc). Los componentes de un array se utilizan de la misma forma que cualquier otra variable de un programa, pudiendo por tanto intervenir en instrucciones de asignacin, entrada/salida, etc.
1 4
Antes de utilizar un array habremos de definirla en el entorno. Los arrays se clasifican segn su dimensin en: - Unidimensionales - Bidimensionales - Multidimensionales
1 4
Para acceder a la lluvia cada el 4 da escribiramos ltrs_dia[3] 7. Un array es una estructura interna, es decir, existe como tal estructura en la memoria principal del ordenador. Como ya sabemos, la memoria principal tiene una capacidad limitada, por tanto, los arrays sern conjuntos finitos. 8. Un array es un conjunto fijo de elementos y, evidentemente, el nmero de estos elementos depende del valor definido en el programa. Dicho en otras palabras, el espacio que ocupar en memoria un array cuando el programa se est ejecutando no podr cambiarse. Si se necesitara un nmero distinto de elementos (otro tamao) sera necesario editar el programa fuente, cambiar la definicin de un array y volver a traducir el programa. Por esto se dice que un array es una estructura esttica. Ejemplo: Si un programa necesitase operar con la temperatura media en una ciudad a lo largo del ao necesitara un array bidimensional (matriz) numrico real de 12 x 31 elementos que podra llamarse Tmp. Podra representarse como una matriz matemtica, donde cada fila correspondera a un mes y cada columna a un da. Los nombres de los elementos representados en un array son: DIAS 0 1 2 ... 30 0 Tmp[0][0] Tmp[0][1] Tmp[0][2] ... Tmp[0][30] 1 Tmp[1][0] Tmp[1][1] Tmp[1][2] ... Tmp[1][30] 2 Tmp[2][0] Tmp[2][1] Tmp[2][2] ... Tmp[2][30] 3 Tmp[3][0] Tmp[3][1] Tmp[3][2] ... Tmp[3][30] MESES ... ... ... ... ... ... 11 Tmp[11][0] Tmp[11][1] Tmp[11][2] ... Tmp[11][30] El 1 ndice representa la fila, y el 2, la columna a que pertenece. Para referenciar a la temperatura media del 3 da del 4 mes escribiramos: Tmp[3][2]. Sin embargo, la distribucin de datos realizada en este ejemplo no es obligatoria y se poda haber elegido otra: una matriz de 31 x 12 donde las filas corresponderan a los das y las columnas a los meses.
1 4
PROGRAMACIN EN LENGUAJE C ARRAYS Y MATRICES Ejemplo: Un programa necesita guardar en un vector los nombres de los distintos autores de los libros de que dispone una biblioteca de 1.000 volmenes. No se sabe el nmero de autores distintos: puede que cada libro sea de un autor distinto o puede que slo haya 100 autores distintos cada uno de los cuales haya escrito 10 de los libros que hay en esa biblioteca. Por ello, suponiendo que se de el caso ms desfavorable, habr que declarar un vector de 1.000 elementos de tipo cadena. Obsrvese que si se da el otro caso descrito se utilizar slo el 10 % del tamao del vector. De todos modos, este tamao del vector servir slo si el programa se aplica a esa biblioteca; es decir, para otra biblioteca distinta, con un nmero distinto de volmenes, habra que modificar el programa fuente para adecuar ese valor mximo. Es conveniente pues declarar el valor que indica el tamao de un array como una constante de modo que slo haya cambiar un valor.
10.
Hay que tener en cuenta que, al sobredimensionar, se est desperdiciando memoria, sobre todo, si habitualmente no se utilizan todos los elementos de un array. Ejemplo: Un programa debe almacenar en un array los nombres de las asignaturas que imparte cada profesor de una ciudad y el curso a quien lo imparte. Supongamos que hay, como mucho, 1000 profesores y cada uno puede tener asignadas un mximo de 10 asignaturas distintas. Se necesitar, por tanto, un array bidimensional (matriz) de tipo cadena de 15 caracteres de 1000 filas (una por profesor) y de 10 columnas. Si el nmero medio de asignaturas distintas asignadas a cada profesor es 5, realmente se utilizar el 50 % del espacio ocupado en memoria por un array; es decir, se desperdician un total de 5 * 1000 * 15 bytes = 75 Kb, aproximadamente. Seguramente la estructura elegida no es la ms adecuada. 11. Las operaciones que se suelen realizar habitualmente sobre un array son:
Recorrido: Procesamiento de cada elemento de un array. Bsqueda: Obtener la posicin ocupada por un elemento con un determinado valor. Ordenacin: Organizar los elementos de un array de acuerdo con algn criterio. Solo se realiza sobre arrays unidimensionales: vectores.
Tambin se pueden insertar y/o borrar elementos de un array, pero slo de una forma lgica, nunca fsica. Puesto que los arrays son habitualmente fciles de recorrer y de buscar en ellas y de ordenar, suelen utilizarse para almacenar conjuntos de datos relativamente fijos.
1 4
Definicin
Para definir un vector es necesario indicar: - Clase de almacenamiento - Tipo de cada uno de los elementos - Identificador del vector - Nmero de elementos (entre corchetes). La sintaxis es: clase tipo identificador[num_elementos] Ejemplo: int meses[12]; Se est definiendo meses[] como un vector de tipo entero con 12 elementos. Para referenciar cada uno de ellos se usarn los ndices desde 0 hasta 11. Es importante, pues, recordar que el 1 elemento de un vector corresponde al ndice 0. La definicin de un vector sirve, evidentemente, para indicar al compilador la cantidad de memoria que tiene que reservar para los datos que vaya a contener. El compilador lo calcula multiplicando el nmero de elementos por el espacio que ocupa cada uno que depender del tipo del vector. Pueden inicializarse tanto vectores globales (externos) como locales, sean estticos o no. Los arrays estticas y las externas son inicializadas a 0 por defecto; o sea, si no se les da ningn valor todos los elementos valdrn 0. Para inicializarlos se coloca la lista de valores entre llaves y separados por comas.
1 4
PROGRAMACIN EN LENGUAJE C ARRAYS Y MATRICES Cuando el nmero de valores es menor que el tamao del vector, el resto de los elementos no inicializados lo hacen a 0. En cambio, si el nmero de valores es mayor que el tamao declarado se produce un error. Si se emplean corchetes vacos cuando se inicializa un vector, el compilador cuenta el nmero de valores de la lista, y ese ser su tamao. short int meses[] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; Por otra parte, el operador sizeof proporciona el tamao en bytes del vector. Por ejemplo: tam_array = sizeof meses; //asignara 24, ya que cada entero corto ocupa 2 bytes Luego, para obtener el nmero de elementos de cualquier vector se usar en general: sizeof identif_array / (sizeof (tipo_array)) Ejemplo:
#include <stdio.h> #include <conio.h> short int meses[]={31,28,31,30,31,30,31,31,30,31,30,31}; void main(void) { int indice; extern short int meses[]; //declaracion opcional for(indice=0; indice < sizeof meses/(sizeof(short int));indice++) printf ("Mes %2d = %d dias.\n", indice+1, meses[indice]); getch(); }
En C no se comprueban los lmites de los arrays: Cuando en un programa queremos hacer referencia a un elemento de un array tenemos que colocar una expresin entre los corchetes; pues bien, se supone que el programador habr colocado una expresin tal que no pueda tomar valores fuera del rango definido. El compilador no se va a entretener en comprobar que el valor que toma esa expresin est dentro de esos lmites.
1 4
PROGRAMACIN EN LENGUAJE C ARRAYS Y MATRICES A continuacin se implementa una funcin que calcula una media aritmtica:
#include <stdio.h> #include <conio.h> #define NUM_ALUMNOS 10 float fmedia2 (float vector[] , int); float fmedia (float vector[] , int); void main(void) { float notas[NUM_ALUMNOS], nota_media; int i; for (i=0; i < NUM_ALUMNOS; i++ ) { printf("NOTA %d : ",i+1); scanf("%f", ¬as[i]); // scanf necesita la direccin } nota_media = fmedia (¬as[0], NUM_ALUMNOS); //Tb. nota_media=fmedia(notas,NUM_ALUMNOS); printf("Nota media = %5.2f ", nota_media ); getch(); } /* fmedia es una funcin general que halla la media de los elementos de cualquier vector de tipo entero. Tambin es vlido: float fmedia (float vector[10], int num_elem )*/ float fmedia ( float vector[] , int num_elem ) { float totnotas; int indice; for (indice=0, totnotas=0.0; indice<num_elem ; indice++) totnotas += vector[indice]; return ( totnotas / num_elem ) ;
El vector notas[] es un vector de reales, local a la funcin principal y cuyo tamao es de 10 elementos. Sin embargo, el vector vector[] NO EXISTE. La llamada a la funcin fmedia le pasa como argumento un puntero -una direccin-: notas, o lo que es lo mismo, ¬as[0]. Por tanto, todas las operaciones que afectan a vector[] estn trabajando realmente sobre el vector notas[]. Hay que tener en cuenta que la funcin fmedia no tiene forma de conocer el tamao del vector que se le ha pasado como parmetro. Luego la llamada a la funcin fmedia tiene tambin que incluir como argumento el tamao del vector.
1 4
1 4
PROGRAMACIN EN LENGUAJE C ARRAYS Y MATRICES (no en memoria), como pueden ser discos duros, disquetes, etc. Nosotros abordaremos en este tema tres mtodos de ordenacin interna sobre vectores de elementos (aunque pueden aplicarse perfectamente sobre estructuras de datos ms complejas). La eficiencia de un mtodo de ordenacin suele determinarse en base a dos factores: el nmero de comparaciones, C, y el nmero de movimientos de las mismas, M. Ambos son funcin del nmero N de elementos que componen el vector a ordenar. Una clasificacin de estos algoritmos puede ser la siguiente: - Mtodos directos: Suelen ser algoritmos cortos y fciles de entender, aunque algo lentos: - Mtodo de insercin directa - Mtodo de seleccin directa - Mtodos de intercambio - burbuja - sacudida - con incrementos decrecientes. Mtodo Shell. - Mtodos Avanzados: Mucho ms complejos que los anteriores. Entre ellos encontramos el mtodo QuickSort, basado en un algoritmo recursivo (tcnica de programacin que permite la llamada de funciones a s mismas). Todos los mtodos relacionados aqu se utilizan con estructuras de datos internas unidimensionales (arrays), es decir, no se utilizan para el caso de ficheros en disco. Adems, por claridad se utilizan datos numricos en los arrays, lo cual no quiere decir que no pueda hacerse con cualquier otro tipo de datos donde pueda establecerse una ley de ordenacin (caracteres, cadenas, etc). Se considera que en los vectores no hay valores repetidos (considrense las diferencias que puedan haber en cada caso si no se cumple esta premisa).
siendo N el nmero de elementos y v el vector. Todos los algoritmos estn expresados en forma de funcin, que devuelve el ndice del elemento a buscar o 1 en caso de que el elemento no se encuentre en el vector. Intuitivamente, el algoritmo de bsqueda lineal es el siguiente: Se recorre el vector desde el primer elemento al ltimo hasta encontrar un elemento cuyo valor coincida con el buscado o hasta que se acabe el vector. En este ltimo caso, el algoritmo debe indicar la no existencia de dicho valor en el vector
1 4
int Busqueda_Lineal_Desordenado(int v[],int elementos, int valor_a_buscar) { int i; for (i=0;v[i]!=valor_a_buscar && i<elementos-1;i++); if (v[i]==valor_a_buscar) return (i); else return -1; }
1 4
PROGRAMACIN EN LENGUAJE C ARRAYS Y MATRICES Cuando el vector de bsqueda est ordenado se consigue un algoritmo ms eficiente con slo modificar la condicin de terminacin de la instruccin for:
int Busqueda_Lineal_Ord_Ascen(int v[],int elementos, int valor_a_buscar) { int i; for (i=0;v[i]<valor_a_buscar && i<elementos-1;i++); if (v[i]==valor_a_buscar) return (i); else return -1; }
La ventaja que se obtiene es que, una vez sobrepasado el valor buscado, no es necesario recorrer el resto del vector para saber que el valor no existe. En caso de haber valores repetidos, se encontrar el valor situado en primer lugar segn el orden ascendente del vector. Sin embargo, para realizar una bsqueda sobre un vector ya ordenado es mucho ms ventajoso utilizar el algoritmo de bsqueda binaria o dicotmica pues el nmero de intentos para encontrar un valor dado es drsticamente ms bajo con la consecuente mejora en velocidad, si bien, en caso de que el vector sea pequeo (10 elementos o menos) una bsqueda lineal no es un mal recurso.
1 4
int izq=0, der=elementos-1, cen=(izq+der)/2; while (v[cen]!=valor_a_buscar && izq<der) { if (v[cen]>valor_a_buscar) der=cen-1; else izq=cen+1; cen=(izq+der)/2; } if (v[cen]==valor_a_buscar) return cen; else return -1; }
1 4
aux=v[i]; j=i-1; while (v[j]>aux && j>0) { v[j+1]=v[j]; j--; } if (v[j]>aux) { v[j+1]=v[j]; v[j]=aux; } else v[j+1]=aux; } }
1 4
Intercambio directo
Es una mejora de los mtodos de intercambio directo en la que se comprueba mediante un switch (interruptor o bandera) si el vector est totalmente ordenado despus de cada pasada, terminando la ejecucin en caso afirmativo. La comprobacin de la ordenacin en cada pasada consiste en detectar si se han producido intercambios o no, de tal forma que slo se realizarn las pasadas necesarias que dependern del grado de desorden existente en los datos iniciales.
void Ordena_Burbuja_Switch(int v[], int elem) { int i,j,aux,sw; i=0; sw=1; while (i<elem-1 && sw) { sw=0; for (j=elem-1;j>i;j--) if (v[j]<v[j-1]) { aux=v[j]; v[j]=v[j-1]; v[j-1]=aux; sw=1; } i++; } }
1 4
con
El mtodo burbuja acerca cada elemento a la posicin que le corresponde paso a paso. Su tiempo de ejecucin para vectores pequeos puede ser aceptable. Un algoritmo mucho ms eficaz y ms apropiado para la ordenacin de grandes vectores es la ordenacin Shell, denominado as en honor a su inventor. Consiste en comparar, no elementos consecutivos como lo haca el de la burbuja, sino los que estn separados por un intervalo grande, de modo que cada uno se acerca al lugar que le corresponde de forma ms rpida. Inicialmente, ese intervalo o salto corresponde con la mitad de la longitud del vector. Posteriormente, cuando ya todos los elementos separados por esa distancia estn ordenados, se divide ese intervalo por dos y se opera de igual forma hasta que, finalmente, el salto se reduzca a 1. Entonces, el proceso de ordenacin funciona exactamente como el de la burbuja: comparando elementos adyacentes. Los elementos que vamos a utilizar dentro de nuestro algoritmo son los siguientes: - d es una variable que indica la distancia de comparacin. - sw comprueba la ordenacin a distancia d, con los siguientes posibles valores: 1 = desordenado a distancia d. 0 = ordenado a distancia d.
void Ordena_Shell(int v[], int elem) { int i,d,sw,aux; d=elem; while (d!=1) { d/=2; sw=1; while (sw) { sw=0; for (i=0;i<elem-d;i++) if (v[i]>v[i+d]) { aux=v[i]; v[i]=v[i+d]; v[i+d]=aux; sw=1; }
1 4
} } }
1 4