how do I swap the values at index 2 and index 3 in a vector of type integer in C++?
Version 1: Using std::swap
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> vec= { 33,12,11,13,54,65,23,67,22,10};
std::swap(vec[2], vec[3]);
for(const int &elem: vec)
{
std::cout<<elem<<std::endl;
}
return 0;
}
Version 2: Manually using a temp
variable
#include <iostream>
#include <vector>
//define a function template that takes the first argument as a vector of arbitrary type and second argument as first index to swap and the third argument as the second index to swap
template<typename T>
void mySwap(std::vector<T>&vec, std::size_t indexOne, std::size_t indexTwo )
{
T temp = vec.at(indexOne);
vec.at(indexOne) = vec.at(indexTwo);
vec.at(indexTwo) = temp;
}
int main()
{
std::vector<int> vec= { 33,12,11,13,54,65,23,67,22,10};
mySwap(vec, 2,3);
for(const int &elem: vec)
{
std::cout<<elem<<std::endl;
}
return 0;
}
The second version is given just to illustrate how you can achieve the same effect as std::swap
.
C++: Swap two elements of two different vectors
std::swap
expects references, not iterators:
std::swap(v1[m], v2[n]);
Swap two values in a vector
If I have understood correctly what you are trying to achieve then you can use the following approach
#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>
int main()
{
std::vector<std::pair<int, int>> v =
{
{ 3, 5 }, { 5, 2 }, { 8, 7 }, { 1, 3 }
};
for (const auto &p : v)
{
std::cout << "(" << p.first << ", " << p.second << ") ";
}
std::cout << std::endl;
auto mostLeft = [](const auto &a, const auto &b) { return a.first < b.first; };
std::swap(v[0], *std::min_element(v.begin(), v.end(), mostLeft));
for (const auto &p : v)
{
std::cout << "(" << p.first << ", " << p.second << ") ";
}
std::cout << std::endl;
}
The program output is
(3, 5) (5, 2) (8, 7) (1, 3)
(1, 3) (5, 2) (8, 7) (3, 5)
Swap values and indexes of a vector
Given N
at compile time and given the array contains each index in [0,N)
exactly once,
it's relatively straight forward (as long as it doesn't have to be in-place, as mentioned in the comments above) :
Construct a new array so that v'[n] = find_index(v, n)
and assign it to the old one.
Here I used variadic templates with std::index_sequence
to roll it into a single assignment:
template<typename T, std::size_t N>
std::size_t find_index(const std::array<T,N>& arr, std::size_t index) {
return static_cast<std::size_t>(std::distance(arr.begin(), std::find(arr.begin(), arr.end(), index)));
}
template<typename T, std::size_t N, std::size_t... Index>
void swap_index_value(std::array<T,N>& arr, std::index_sequence<Index...> seq){
arr = { find_index(arr, Index)... };
}
template<typename Integer, std::size_t N>
void swap_index_value(std::array<Integer,N>& arr) {
swap_index_value(arr, std::make_index_sequence<N>{});
}
The complexity of this is does not look great though. Calling find_index(arr, n)
for each n in [0,N)
will take N * (N+1) / 2 comparisons total (std::sort
would only take N * log(N)).
However, since we know each index is present in the array, we could just fill out an array of indices
as we walk over the original array, and assuming T is an integral type we can skip some std::size_t <-> T conversions, too:
template<typename T, std::size_t N>
void swap_index_value(std::array<T,N>& arr){
std::array<T, N> indices;
for (T i = 0; i < N; ++i)
indices[arr[i]] = i;
arr = indices;
}
We're still using twice the space and doing some randomly ordered writes to our array,
but essentially we're down to 2*N assignments, and the code is simpler than before.
Alternatively, we could also std::sort
if we keep a copy to do lookups in:
template<typename T, std::size_t N>
void swap_index_value(std::array<T,N>& arr){
std::sort(arr.begin(), arr.end(), [copy = arr](const T& lhs, const T& rhs) {
return copy[lhs] < copy[rhs];
});
}
First version here,
second version here,
std::sort version here
Benchmarking which one is faster is left as an exercise to the reader ;)
Is it safe to swap two different vectors in C++, using the std::vector::swap method?
It is safe because nothing is created during the swap operation. Only data members of the class std::vector
are swapped.
Consider the following demonstrative program that makes it clear how objects of the class std::vector
are swapped.
#include <iostream>
#include <utility>
#include <iterator>
#include <algorithm>
#include <numeric>
class A
{
public:
explicit A( size_t n ) : ptr( new int[n]() ), n( n )
{
std::iota( ptr, ptr + n, 0 );
}
~A()
{
delete []ptr;
}
void swap( A & a ) noexcept
{
std::swap( ptr, a.ptr );
std::swap( n, a.n );
}
friend std::ostream & operator <<( std::ostream &os, const A &a )
{
std::copy( a.ptr, a.ptr + a.n, std::ostream_iterator<int>( os, " " ) );
return os;
}
private:
int *ptr;
size_t n;
};
int main()
{
A a1( 10 );
A a2( 5 );
std::cout << a1 << '\n';
std::cout << a2 << '\n';
std::cout << '\n';
a1.swap( a2 );
std::cout << a1 << '\n';
std::cout << a2 << '\n';
std::cout << '\n';
return 0;
}
The program output is
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4 5 6 7 8 9
As you see only data members ptr
and n
are swapped in the member function swap. Neither additional resources are used.
A similar approach is used in the class std::vector
.
As for this example
std::vector<Widget> WidgetVector;
std::vector<Widget2> Widget2Vector;
then there are objects of different classes. The member function swap is applied to vectors of the same type.
Swapping elements efficiently in C++ vector
It looks like you need std::rotate
:
#include <algorithm> // std::rotate
#include <iostream>
int main() {
std::vector<int> vect = {1,2,3,4,5,6,7};
std::rotate(vect.begin(), vect.begin() + 5, vect.end());
// ^^^^^^^^^^^^^^^^
// the new first position
for(auto v : vect) std::cout << v << ' ';
}
Demo
Using std::swap on a vector of int
This should do the trick
assert(!vec.empty());
std::swap(vec.front(), vec.back());
vector - swap two elements when elements have const members
Based on this thread following works:
#include <vector>
#include <iostream>
class Foo {
public:
const int value;
Foo(const int &&from) : value(std::move(from)){}
Foo(const Foo &&other) : value(std::move(other.value)){}
Foo & operator=(Foo && source) {
this -> ~ Foo ();
new (this) Foo(std::move(source));
return *this;
}
};
int main() {
std::vector<Foo> v;
v.emplace_back(1);
v.emplace_back(2);
v.emplace_back(3);
v.emplace_back(4);
std::cout << (v.begin() + 1)->value << "," <<v.rbegin()->value << std::endl;
std::iter_swap(v.begin() + 1, v.rbegin());
std::cout << (v.begin() + 1)->value << "," <<v.rbegin()->value << std::endl;
return 0;
}
Related Topics
Template Metaprogramming - Difference Between Using Enum Hack and Static Const
Broken C++ Std Libraries on MACos High Sierra 10.13
Reading an Application's Manifest File
Openmp: What Is the Benefit of Nesting Parallelizations
Gcc: Difference Between -O3 and -Os
Is the Typedef-Name Optional in a Typedef Declaration
How Make File* from Handle in Winapi
C++: Fastest Method to Check If All Array Elements Are Equal
How to Enable_Shared_From_This of Both Parent and Derived
What Is the Branch in the Destructor Reported by Gcov
Why Isn't There an Operator[] for a Std::List
Creating Array of Objects on the Stack and Heap
Creating a Thread Pool Using Boost
In C++ Main Function Is the Entry Point to Program How to Change It to an Other Function