domingo, 22 de noviembre de 2015

sábado, 21 de noviembre de 2015

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 INSERCION  
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.





iinserccion

#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 SELECCIÓN 

El ordenamiento por selección (Selection Sort en ings) es un algoritmo de ordenamiento que requiere O
(n^2)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();
}


EJERCICIOS METODO DE ORDENAMIENTO Ejercicio 1:
#include <stdio.h>
#define SIZE 7
void main(void) {
  int vector[SIZE];
  int j, i, temp;
  printf("Introduce los %d valores para ordenar:\n", SIZE);
  for(i=0; i<SIZE; i++) {
     printf("%d: ", i+1);
     scanf("%d", &vector[i]);
     printf("\n");
  }
  /* se aplica el algoritmo de la burbuja */
  for(i=0; i<(SIZE-1); i++) {
     for (j=i+1; j<SIZE; j++) {
        if(vector[j]<vector[i]) {
            temp=vector[j];
            vector[j]=vector[i];
            vector[i]=temp;
        }
     }
  }
  printf("El vector ordenado es:\n");
  for(i=0; i<SIZE ; i++) {
     printf("%d ", vector[i]);
  }
  printf("\n");
}
 
EJERCIO 02
 
#include <stdio.h>

#include <stdlib.h>

#include <string.h>
 

void OrdenaBurbuja (float v[], int n)

{

int t, h, e;

for (h=1; h<n; h++)

{

for(e=0; e<n;e++)

{

if (v[e]>v[e+1])

{

v[e+1] = t;

v[e] = v[e+1];

t= v[e];

}

}

}

}
 
 

void ImprimirVector(float v[], int n)

{

int i; 

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

{

printf("%f ", v[i]);

}

}
 

int main(int argc, char *argv[])

{

if(strcmp(argv[1], "burbuja")==0)

{

int n, i, m=2, o;

float *v;

{

n=argc-2; 

v =(float *)malloc(n*sizeof(float));

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

{

v[i] = atof(argv[i+2]);

}

}

OrdenaBurbuja(v, n);

ImprimirVector(v, n);

}

system("PAUSE"); 

return 0;
}


               vídeos ayuda




 


LINK CON PDF CON METDOS DE ODENAMIENTOS: http://es.tldp.org/Tutoriales/doc-programacion-algoritmos-ordenacion/alg_orden.pdf









            
                " ESPERO QUE HAYA SIDO DE TU AYUDA TODO EL MATERIAL"

MATRICES EN C++


                        MATRICES EN C++




















Las matrices o como algunos las llaman "arreglos 
multidimensionales" son una estructura de datos bastante similar a los vectores o arreglos; de hecho una matríz no es más que una serie de vectores contenidos en en otro (u otros), es decir, una matriz es un vector cuyas posisiones son otros vectores. Hablemos con más detalle de esto para quedar más claros.









Nota: Te recomiendo ver y comprender la ENTRADA DE VECTORES, antes de iniciar con este artículo para poder dominar el tema de éste con más facilidad.

Primero dejemos claro qué es una matriz. En términos generales, una mátriz es una estructura conformada por filas y conlumnas, idealmente más de dos filas y columnas, de hecho podemos decir que si una "matriz" tiene una única fila o una única columna, entonces estamos hablando de un vector.

La intersección de una fila y una columna de la matriz son las casillas y cada una de ellas podrá poseer información, simple o compleja (ya dependerá de nuestras necesidades).
Ahora, tal como dije antes un vector posee una única fila (o columna, como lo quieras ver) y de este modo un grupo de vectores unidos conforman una matríz, es por esto que al comienzo dije que una matríz es un vector conformado por otra serie de vectores.
Viendolo desde el punto de vista de la programación, una matriz entonces, es un vector cuyas posiciones (de la cero a la n) son, cada una de ellas, otro vector
Como siempre, la mejor forma de comprender algo es viendo un ejemplo en acción, así que veamos un buen ejemplo de matrices en C++

Matrices en C++ un buen ejemplo





Muy bien voy a dar el ejemplo de donde teníamos la necesidad de almacenar los titulos y los autores de una serie de libros dada.
en el ejemplo anterior se tiene que crear una matríz que almacenará en la primera columna los títulos, y en la segunda columna los autores; cada fila será entonces la información completa de un libro.

Para solucionar este problema, aprendamos primero algunas normas básicas para poder crear y usar matrices en C++.

¿Cómo se crea una Matriz en C++?


Declarar una matriz en C++ es muy similar a la de un vector, se deben seguir las mismas normas para declarar una variable pero una vez más con un pequeño cambio en la sintaxis. Primero necesitaremos saber el tipo de los datos que irán al interior de este (números, decimales o cadenas de texto, etc.) necesitamos también, como siempre, un nombre para la matriz y un tamaño máximo tanto para las filas como para las columnas. La sintaxis para declarar una matriz en C++ es la siguiente:

Nota: Recuerda que en C++, no es posible crear de una manera sencilla un vector (y por ende una matriz)capaz de almacenar una cantidad de información indefinida, es necesario ingresar con antelación la cantidad de datos (filas y columnas) que la matriz tendrá.

Tenemos entonces, como podrás ver, que la sintáxis es casi la misma excepto que hemos añadido un par de corchetes "[]" más esta vez y al interior de los éstos debemos poner el número de filas y columnas máximas de la matriz, respectivamenteque. Veamos un ejemplo en el cual pondré la declaración de varias matrices de diferentes tipos y tamaños en C++.

Declaración de una matriz en C++


 
int myMatriz1[10][5];
float myMatriz2[5][10];
string myMatriz3[15][15];
bool myMatriz4[1000][3];
 
Veamos que representa cada línea del código anterior.

Línea 1

Esta línea contiene la declaración de una matriz llamada myMatriz1 que tendrá 10 filas y 5 columnas y cada una de las 50 casillas tendrá datos de tipo entero.

Línea 2

Esta línea contiene la declaración de una matriz llamada myMatriz2 que tendrá 5 filas y 10 columnas y cada una de las 50 casillas tendrá datos de tipo flotante.

Línea 3

Esta línea contiene la declaración de una matriz llamada myMatriz3 que tendrá 15 filas y 15 columnas (una matríz cuadrada) y cada una de las 225 casillas tendrá datos de tipo string.

Línea 4

Esta línea contiene la declaración de una matriz llamada myMatriz4 que tendrá 1000 filas (sí, leíste bien) y 3 columnas y cada una de las 3000 casillas (también leíste bien, tres mil casillas) tendrá datos de tipo boleano.
Ya que está claro cómo se declara una matriz, vamos a inicializarla, es decir darle un valor a cada casilla, según su tipo de dato.

¿Cómo inicializar una matriz en C++?


En cuanto tenemos declarado una matriz, es posible asignarle valores a cada una de sus casillas, evidentemente estos valores deben coincidir con el tipo de dato que le asignamos a dicha matriz
Voy a mostrar a continuación formas distintas de inicializar una matriz, todas son validas, ya es cuestión de nuestras necesidades y conocimientos determinar cuál es útil y en qué momento. Veamos entonces:

Forma 1 de declarar una matriz:


 
int myMatriz1[2][2] = {{1,2},{3,4}};
 
Aquí hemos declarado una matriz de tipo int de dos filas y dos columnas y la hemos inicializado con diferentes valores. El valor inicial corresponde a la casilla 0,0 (fila cero, columna cero) y tiene el valor de 1, en la fila cero columna uno tenemos el valor de 2, en la fila uno columna cero el valor de 3 y finalmente en la fila uno columna uno el valor de 4. Es importante notar que el primer tanto la fila como la columna comienzan desde cero y no desde uno, por esto la primer casilla corresponde a la fila y columna cero.
Bien! Ya sabemos cómo declarar una matriz en C++, sin embargo aun no sabemos cómo acceder a lso datos que estas contienen. Veámoslo:

Obtener el valor de una casilla específica


Para acceder al valor de una casilla nuevamente haremos uso de los corchetes, pero esta vez no para declar tamaños (porque eso ya lo hicimos) sino para indicar posiciones (fila y columna).
 
int myMatriz1[2][2] = {{1,2},{1,1}}; //Matriz con 4 elementos
int fila1Casilla1 = myMatriz[1][1]; //Para acceder a la casilla 1,1 se usan dichos indices
int primerNumero = myMatriz[0][0]; //La primer casilla siempre será la de la fila 0 columna 0
 
Como podemos ver, para acceder a un valor específico conociendo el índice de la casilla, solo basta con escribir dicho índice entre los corchetes "[][]", recuerda que el índice comienza desde cero, así por lo tanto en una matriz de vector de 2 por 2 (como el ejemplo), el último elemento está en el índice 1 y el primer elemento en el índice 0.

Recorrer una matriz en C++


Para obtener todos los datos que se encuentran al interior de una matriz, debemos acceder a cada posición y esto se hace fácilmente con dos ciclos for (anidados). La lógica de este procedimiento es la siguiente, el primer ciclo for comenzará desde cero e ira hasta el número de filas, de modo que la variable de control que generalmente llamamos "i", será la que va a ir variando entre cero y el tamaño del array, de esta forma al poner la i al interior de los corchetes, estaremos accediendo al valor de cada fila y el segundo ciclo irá de cero al número de columnas y normalmente se usa la variable llamada j para acceder a cada columna, veamos:
Nota:En el código acontinuación uso una forma sencilla y rápida de obtener la cantidad o número de filas de una matriz y también cómo obtener el número o cantidad de columnas de una matriz. Ten en cuenta que esto es importante, pues a veces no tenemos la certeza del tamaño de la matriz.
 
#include 

using namespace std;

int main()
{
    int edades[3][2] = {{1,2},{9,8},{14,21}};
    int filas = (sizeof(edades)/sizeof(edades[0]));
    int columnas = (sizeof(edades[0])/sizeof(edades[0][0]));
    for (int i = 0; i < filas; i++)
    {
        for (int j = 0; j < columnas; j++)
        {
            cout<<edades[i][j]<<endl;
        }
    }
}
 
Vamos a ver de forma resumida en qué consiste y que hace cada una de estas líneas

Línea 1:

Tenemos en la primera línea la declaración de una matriz que contiene las edades de tres parejas de personas y asignamos cada uno de los valores.

Líneas 2 y 3:

En estas líneas, tenemos la declaración del número de filas y columnas de la matriz, que serán el límite del primer y segundo ciclo, respectivamente. Para mas detalles de esto, verifica la información sobre el operador sizeof.

Líneas 4 a 7:

Aquí, tenemos entonces un ciclo for que comienza en cero y termina en el número de filas y luego tenemos otro ciclo for (anidado) que irá de cero hasta el número de columnas (es importante notar que la condición usada en ambos ciclos es estrictamente menor "<" y no menor o igual "<="), al interior del segundo ciclo, es donde accedemos a cada uns de las casillas de la matriz usando loc corchetes.

Línea 8:

La octava línea es quizá la más vital aunque sin las demás no tendríamos nada. En esta línea, estamos accediendo a cada una de las casillas de la matriz, fila por fila y columna por columnaaccedemos a cada elemento poniendo entre los corchetes la variable i y j, que son las que están cambiando a medida que los ciclos van "girando", así estaremos accediendo a todos los elementos e imprimiéndolos por pantalla por medio de cout.
Muy bien, llegó el momento de afianzar nuestros conocimientos viendo un ejemplo. Ahora que tenemos claro como declarar un vector en C++, como recorrerlo y como acceder a sus datos, vamos a ver un ejemplo basado en el problema que planteé al inicio de esta sección (el de los libros).

Ejemplo de Matrices en C++


El problema es simple, queremos crear un programa con el cual podamos guardar los títulos y los autores de diferentes libros sin perder ninguno de ellos. El usuario es el encargado de suministrar la información de cada libro. Vamos a suponer que el usuario solo podrá ingresar un máximo de 5 libros, para así tener un tamaño de vector fijo. Veamos entonces cómo se haría esto usando matrices:
 
#include "iostream"
#include "stdio.h"
#include "string"

using namespace std;

int main()
{
    string libros[5][2];
    cout << "Por favor ingrese la siguiente información de los Libros: \n";
    string titulo ,autor;
    for(int i = 0; i < 5; i++)
    {
        cout << "\n******* Libro " << i + 1 << "********:\n";
        cout << "Titulo: ";
        getline(cin,titulo);
        cout << "Autor: ";
        getline(cin,autor);
        libros[i][0] = titulo;
        libros[i][1] = autor;
    }

    system("pause");

    return 0;
}
 
Notar que en el código anterior, debido a que tenemos la completa certeza de sólo usar dos columnas, no es necesario usar otro ciclo for (de hecho, eso complicaría todo) basta con poner de manera explícita que el valor del título va en la columna cero y el del autor en la columna uno.

 DECLARACION DE MATRICES:





DETERMINANTE DE UNA MATRIZ:





Nota: Recuerda que si no comprender alguna cosa, detectas algún error, tienes alguna sugerencia o simplemente tienes algo que comentarme, puedes hacerlo con total tranquilidad en la sección de comentarios o a mi correo.

VECTORES EN C++



INTRODUCCIÓN A VECTORES




Con cadenas, podemos rellenar un objeto string sin saber cuanta memoria se va a necesitar. El problema de introducir líneas de un fichero en objetos string es que se sabe cuántas cadenas habrá - solamente lo sabemos cuando ya hemos leido el fichero entero. Para resolver este problema necesitamos un nuevo tipo de datos que pueda crecer automáticamente para contener las cadenas que le vayamos introduciendo.


De hecho, ¿por qué limitarnos a manejar objetos string? Parece que este tipo de problema - no saber la cantidad de cosas a manejar mientras está escribiendo el problema - ocurre a menudo. Y este objeto «contenedor» podría resultar más útil si pudiera manejar cualquier clase de objeto. Afortunadamente, la Librería Estándar de C++ tiene una solución: las clases contenedor (container). Las clases contenedor son uno de los puntos fuertes del Estándar C++.


A menudo existe un poco de confusión entre los contenedores y los algoritmos en la librería Estándar de C++, y la STL. La Standard Template Library fue el nombre que usó Alex Stepanov(que en aquella época estaba trabajando en Hewlett-Packard) cuando presentó su librería al Comité del Estándar C++ en el encuentro en San Diego, California, en la primavera de 1994. El nombre sobrevivió, especialmente después de que HP decidiera dejarlo disponible para la descarga pública. Posteriormente el comité integró las STL en la Librería Estándar de C++ haciendo un gran número de cambios. 


El desarrollo de las STL continúa en Silicon Graphics (SGI; ver www.sgi.com/Technology/STL). Las SGI STL divergen de la Librería Estándar de C++ en muchos detalles sutiles. Aunque es una creencia ampliamente generalizada, el C++ Estándar no "incluye" las STL. Puede ser confuso debido a que los contenedores y los algoritmos en el C++ Estándar tienen la misma raíz (y a menudo el mismo nombre) que en el SGI STL. En este libro, intentaré decir «la librería Estándar de C++» o «Librería Estándar de contenedores», o algo similar y eludiré usar el término STL.


A pesar de que la implementación de los contenedores y algoritmos de la Librería Estándar de C++ usa algunos conceptos avanzados, que se cubren ampliamente en dos largos capítulos en el segundo volumen de este libro, esta librería también puede ser potente sin saber mucho sobre ella. Es tan útil que el más básico de los contenedores estándar, el vector, se introduce en este capítulo y se usará a lo largo de todo el libro. Verá que puede hacer muchas cosas con el vector y no saber cómo está implementado (de nuevo, uno de los objetivos de la POO). Los programas que usan vector en estos primeros capítulos del libro no son exactamente como los haría un programador experimentado, como comprobará en el volumen 2. Aún así, encontrará que en la mayoría de los casos el uso que se hace es adecuado.


La clase vector es una plantilla, lo que significa que se puede aplicar a tipos de datos diferentes. Es decir, se puede crear un vector de figuras, un vector de gatos, un vector de strings, etc. Básicamente, con una plantilla se puede crear un vector de «cualquier clase». Para decirle al compilador con qué clase trabajará (en este caso que va a manejar el vector), hay que poner el nombre del tipo deseado entre «llaves angulares». Por lo que un vector de string se denota comovector<string>. Con eso, se crea un vector a medida que solamente contendrá objetos string, y recibirá un mensaje de error del compilador si intenta poner otra cosa en él.


Como el vector expresa el concepto de «contenedor», debe existir una manera de meter cosas en él y sacar cosas de él. Para añadir un nuevo elemento al final del vector, se una el métodopush_back(). Recuerde que, como es un método, hay que usar un '.' para invocarlo desde un objeto particular. La razón de que el nombre de la función parezca un poco verboso - push_back() en vez de algo más simple como put - es porque existen otros contenedores y otros métodos para poner nuevos elementos en los contenedores. Por ejemplo, hay un insert() para poner algo en medio de un contenedor. vector la soporta pero su uso es más complicado y no necesitamos explorarla hasta el segundo volumen del libro. También hay un push_front() (que no es parte de vector) para poner cosas al principio. Hay muchas más funciones miembro en vector y muchos más contenedores en la Librería Estándar, pero le sorprenderá ver la de cosas que se pueden hacer con sólo un par de características básicas.


Así que se pueden introducir elementos en un vector con push_back() pero ¿cómo puede sacar esos elementos? La solución es inteligente y elegante: se usa la sobrecarga de operadores para que el vector se parezca a un array. El array (que será descrito de forma más completa en el siguiente capítulo) es un tipo de datos que está disponible prácticamente en cualquier lenguaje de programación por lo que debería estar familiarizado con él. Los arrays son agregados lo que significa que consisten en un número de elementos agrupados. La característica distintiva de un array es que estos elementos tienen el mismo tamaño y están organizados uno junto a otro. Y todavía más importante, que se pueden seleccionar mediante un índice, lo que significa que puede decir: «Quiero el elemento número n» y el elemento será producido, normalmente de forma rápida. A pesar de que existen excepciones en los lenguajes de programación, normalmente se indica la «indexación» mediante corchetes, de tal forma que si se tiene un array a y quiere obtener el quinto elemento, sólo tiene que escribir a[4] (fíjese en que la indexación siempre empieza en cero).


Esta forma compacta y poderosa de notación indexada se ha incorporado al vector mediante la sobrecarga de operadores como el << y el >> de los iostreams. De nuevo, no hay que saber cómo se ha implementado la sobrecarga de operadores - lo dejamos para un capítulo posterior - pero es útil que sea consciente que hay algo de magia detrás de todo esto para conseguir que los corchetes funcionen con el vector.


Con todo esto en mente, ya puede ver un programa que usa la clase vector. Para usar un vector, hay que incluir el fichero de cabecera <vector>:



//: C02:Fillvector.cpp
// Copy an entire file into a vector of string
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

int main() {
  vector<string> v;
  ifstream in("Fillvector.cpp");
  string line;
  while(getline(in, line))
    v.push_back(line); // Add the line to the end
  // Add line numbers:
  for(int i = 0; i < v.size(); i++)
    cout << i << ": " << v[i] << endl;
} ///:~


Casi todo este programa es similar al anterior; se abre un fichero abierto y se leen las líneas en objetos string (uno cada vez). Sin embargo, estos objetos string se introducen al final del vector v. Una vez que el bucle while ha terminado, el fichero entero se encuentra en memoria dentro de v.


La siguiente sentencia en el programa es un bucle for. Es parecido a un bucle while aunque añade un control extra. Como en el bucle while, en el for hay una «expresión de control» dentro del paréntesis. Sin embargo, esta expresión está dividida en tres partes: una parte que inicializa, una que comprueba si hay que salir del bucle, y otra que cambia algo, normalmente da un paso en una secuencia de elementos. Este programa muestra el bucle for de la manera más habitual: la parte de inicialización int i = 0 crea un entero i para usarlo como contador y le da el valor inicial de cero. La comprobación consiste en ver si i es menor que el número de elementos del vector v. (Esto se consigue usando la función miembro size() -tamaño- que hay que admitir que tiene un significado obvio) El último trozo, usa el operador de «autoincremento» para aumentar en uno el valor de i. Efectivamente, i++ dice «coge el valor de i añádele uno y guarda el resultado en i». Conclusión: el efecto del bucle for es aumentar la variable i desde cero hasta el tamaño del vectormenos uno. Por cada nuevo valor de i se ejecuta la sentencia del cout, que construye un linea con el valor de i (mágicamente convertida a un array de caracteres por cout), dos puntos, un espacio, la línea del fichero y el carácter de nueva línea que nos proporciona endl. Cuando lo compile y lo ejecute verá el efecto de numeración de líneas del fichero.


Debido a que el operador >> funciona con iostreams, se puede modificar fácilmente el programa anterior para que convierta la entrada en palabras separadas por espacios, en vez de líneas:



//: C02:GetWords.cpp
// Break a file into whitespace-separated words
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

int main() {
  vector<string> words;
  ifstream in("GetWords.cpp");
  string word;
  while(in >> word)
    words.push_back(word); 
  for(int i = 0; i < words.size(); i++)
    cout << words[i] << endl;
} ///:~


La expresión:
while (in >> word)
es la que consigue que se lea una «palabra» cada vez, y cuando la expresión se evalúa como «falsa» significa que ha llegado al final del fichero. De acuerdo, delimitar una palabra mediante caracteres en blanco es un poco tosco, pero sirve como ejemplo sencillo. Más tarde, en este libro, verá ejemplos más sofisticados que le permiten dividir la entrada de la forma que quiera.
Para demostrar lo fácil que es usar un vector con cualquier tipo, aquí tiene un ejemplo que crea un vector de enteros




//: C02:Intvector.cpp
// Creating a vector that holds integers
#include <iostream>
#include <vector>
using namespace std;

int main() {
  vector<int> v;
  for(int i = 0; i < 10; i++)
    v.push_back(i);
  for(int i = 0; i < v.size(); i++)
    cout << v[i] << ", ";
  cout << endl;
  for(int i = 0; i < v.size(); i++)
    v[i] = v[i] * 10; // Assignment  
  for(int i = 0; i < v.size(); i++)
    cout << v[i] << ", ";
  cout << endl;
} ///:~

Para crear un vector que maneje un tipo diferente basta con poner el tipo entre las llaves angulares (el argumento de las plantillas). Las plantillas y las librerías de plantillas pretenden ofrecer precisamente esta facilidad de uso.
Además este ejemplo demuestra otra característica esencial del vector en la expresión
v[i] = v[i] * 10;


Puede observar que el vector no está limitado a meter cosas y sacarlas. También puede asignar(es decir, cambiar) cualquier elemento del vector mediante el uso de los corchetes. Eso significa que el vector es un objeto útil, flexible y de propósito general para trabajar con colecciones de objetos, y haremos uso de él en los siguientes capítulos.



EJEMPLOS DE VECTORES: