2012-07-05 21 views
6

Estoy tratando de rotar un vector de elementos en C++. lo que quiero decir con eso es que tengo un vector<point> Quiero que el último elemento se convierta en el primero.Girar un vector (matriz)

ejemplo:

[1,2,3] convertido en [3,1,2] y luego [2,3,1]

Para que trataron de hacer lo siguiente:

//Add the last element at index 0 
ObjectToRotate.insert(0, ObjectToRotate.at(ObjectToRotate.size()-1)); 
//Remove Last element 
ObjectToRotate.erase(ObjectToRotate.size()-1); 

pero me sale este error:

Error 6 error C2664: 'std::_Vector_iterator<_Myvec> std::vector<_Ty>::insert<cv::Point_<_Tp>&>(std::_Vector_const_iterator<_Myvec>,_Valty)' : cannot convert parameter 1 from 'int' to 'std::_Vector_const_iterator<_Myvec>' 

¿Cómo puedo solucionarlo?

Gracias

Respuesta

13

Hay una std::rotate algorithm en la biblioteca estándar:

std::rotate(ObjectToRotate.begin(), 
      ObjectToRotate.end()-1, // this will be the new first element 
      ObjectToRotate.end()); 
+1

o utilizar un 'std :: deque' y la '.rotate (1)' función de miembro. –

+4

@CharlesBeattie: 'deque' no tiene función de miembro' rotar'. –

+0

Vaya. Tengo una versión que tiene una rotación (std :: deque es lenta). –

3

Los argumentos a insert y erase son iteradores, no indexa:

ObjectToRotate.insert(ObjectToRotate.begin(), ObjectToRotate.back()); 
ObjectToRotate.pop_back(); // or erase(ObjectToRotate.end()-1), if you prefer 

Pero puede ser más eficiente para eliminar el último elemento primero (después de tomar una copia), para evitar la posibilidad de reasignación:

auto back = ObjectToRotate.back(); 
ObjectToRotate.pop_back(); 
ObjectToRotate.insert(ObjectToRotate.begin(), back); 

o utilizar std::rotate:

std::rotate(ObjectToRotate.begin(), ObjectToRotate.end()-1, ObjectToRotate.end()); 

Si' Al hacer esto mucho, entonces deque podría ser una mejor opción de contenedor, ya que permite una inserción y extracción eficiente en ambos extremos. Pero, si la velocidad es importante, asegúrese de medir y verificar que esto realmente sea una mejora; si la secuencia no es muy grande, la sobrecarga del diseño de memoria más complicado puede hacer que deque sea más lento.

+0

Re 'deque', uno pensaría que sí, no lo haría. De hecho, para los contenedores con pocos elementos de bajo costo para copiar, resulta que 'vector' es aún más rápido. (Mediciones hechas con 'vector ' y 'deque ', con alrededor de diez elementos.) Algo así como me sorprendió, pero así fue. –

+0

@JamesKanze: De hecho, debería agregar el descargo de responsabilidad habitual sobre la optimización prematura o sin medición. –

+0

En este caso ... Yo diría que dado el uso, 'std :: deque' debería ser el contenedor predeterminado --- estás insertando o quitando en ambos extremos. Es, de hecho, lo que había usado inicialmente. Como mi uso se encontraba en una ubicación crítica, terminé perfilando y experimentando con otras soluciones. Con lo que fueron, al menos para mí, resultados algo sorprendentes. Las indirecciones adicionales, etc., en un 'deque' terminan costando más que copiando algunos POD. –

6

Las recomendaciones para usar std::rotate son, por supuesto, totalmente correctas; usando una función existente siempre es la solución preferida cuando está disponible. Sin embargo, vale la pena señalar por qué su solución no funcionó. Los contenedores en la biblioteca estándar, como std::vector, toman información de posición en forma de iteradores, no de índices. El manera idiomática de escribir su funcionamiento sería el siguiente:.

v.insert(v.begin(), v.back()); 
v.erase(std::prev(v.end())); 

(Si usted no tiene C++ 11, que es bastante simple para escribir su propia versión de prev O en el caso de vector, se puede simplemente escribir v.end() - 1.)

1

para hacer [1,2,3] a [2.3.1] Aquí está el código

vector<int> Solution::rotateArray(vector<int> &A, int B) { 
vector<int> ret; 
for (int i = 0; i < A.size(); i++) { 
    ret.push_back(A[(i + B) % A.size()]); 
} 
return ret; 

}

aquí A es [1,2,3] y B es 1 para cambiar 1 posición

Cuestiones relacionadas