C++ Trying to Swap Values in a Vector

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



Leave a reply



Submit