Vectores - básico
¿Cómo se puede manejar un vector, básicamente?
#include <iostream>
using namespace std;
int main()
{
int v[] = { 45, 23, 22, 12, 11, 10, -1 };
for(int i = 0; v[ i ] != -1; ++i) {
cout << v[ i ] << endl;
}
return 0;
}
Un posible programa que maneje un vector es éste, publicado ya la semana pasada.
Los
vectores son espacios contíguos en memoria, de manera que podemos
acceder a sus elementos utilizando el nombre del vector, los corchetes,
y la posición.
v[ 0 ] = 11;
cout << v[ 0 ] << endl;
En
el programa anterior, se utiliza un centinela para indicar el fin del
vector, puesto que en C/C++ (al contrario que en Java) no tenemos de un
"miembro" length que nos indique el número de elementos.
De hecho, es bastante típico crear constantes que nos indiquen el número de elementos que contiene un vector:
#include <iostream>
using namespace std;
const int MaxElementos = 6;
int main()
{
int v[] = { 45, 23, 22, 12, 11, 10 };
for(int i = 0; i < MaxElementos; ++i) {
cout << v[ i ] << endl;
}
return 0;
}
Vectores de tipos complejos
Finalmente, no es necesario que el tipo del vector (o matriz) sea un tipo básico, como int. También puede ser una estructura. Por ejemplo:
#include <iostream>
using namespace std;
const int MaxDimensiones = 2;
struct Complejo {
int a;
int b;
};
void muestra(Complejo v[][MaxDimensiones])
{
for(int i = 0; i < MaxDimensiones; ++i) {
for(int j = 0; j < MaxDimensiones; ++j) {
cout << v[ i ][ j ].a
<< '+' << v[ i ][ j ].b << 'i' << endl;
}
}
}
int main()
{
Complejo v[MaxDimensiones][MaxDimensiones];
v[0][0].a = 1; v[0][0].b = 2;
v[0][1].a = 6; v[0][1].b = 7;
v[1][0].a = 88; v[1][0].b = 99;
v[1][1].a = 56; v[1][1].b = 78;
muestra( v );
return 0;
}
En este ejemplo se utilizan los números complejos para ilustrar una estructura usada dentro de un vector.
Eficiencia
Para ir practicando con ésto de los vectores que se pueden manejar con punteros, supongamos este programa:
#include <iostream>
using namespace std;
int main()
{
int v[] = { 45, 23, 22, 12, 11, 10, -1 };
for(int i = 0; v[ i ] != -1; ++i) {
cout << v[ i ] << endl;
}
return 0;
}
Que, como ya hemos visto, es equivalente a:
#include <iostream>
using namespace std;
int main()
{
int v[] = { 45, 23, 22, 12, 11, 10, -1 };
for(int i = 0; *(v + i) != -1; ++i) {
cout << *(v + i ) << endl;
}
return 0;
}
Ese trozo de *(v + i)
es lo que se conoce como aritmética de punteros (a un puntero se le
puede sumar uno para que llegue a la siguiente posición, lo cuál, en
este caso, al ser un vector (contíguo en memoria), es correcto) ...
¿Cómo
podríamos hacer que el bucle fuese eficiente, es decir, que se evitase
hacer una suma (en este caso, incluso dos) por cada vuelta de bucle?
Pista: recordad que ++i es más eficiente que i += x.
Respuesta
La
respuesta es que, en el anterior trozo de código, para cada
posición que recorre el bucle, se recalcula la posición
del vector sobre la que se va a actuar. Sería mejor hacer
avanzar alguna variable que sirviera de cursor, de manera que, ya que
el vector utiliza espacio contíguo en memoria, podamos recorrer
todas las posiciones de esta manera.
#include <iostream>
using namespace std;
int main()
{
int v[] = { 45, 23, 22, 12, 11, 10, -1 };
for(int * i = v; *i != -1; ++i) {
cout << *i << endl;
}
return 0;
}
Esta
versión es muchísimo más eficiente, puesto que
sólo es necesario incrementar en uno la variable i, que es un
puntero que va señalando sucesivamente, por cada vuelta de
bucle, el elemento que se va a tratar.