C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Rearranging a Vector

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
raisenero
Guest





PostPosted: Tue Aug 02, 2005 12:47 pm    Post subject: Rearranging a Vector Reply with quote



I'm looking to improve the way I'm rearranging a vector, switching the
contents of the first half with the second half (i.e. The first half of
the vector is now the second half, and the second half is now the first
half.)

My code works, but it just seems long and clunky to me, like I'm going
about doing it in a more complicated way than is necessary. I know
this is probably a very basic question, but I just don't have the
programming experience. Most of my coding always seems to come down to
"Keep typing until the program eventually does what I want.", so my
solutions to things like this don't seem as elegant as I think they
should be.

I thought maybe I could use the generic algorithm "copy" to solve the
problem, but I just didn't seem to be getting the results I expected so
this is the best I've done so far.

Thanks very much for any insight. I've included the source for the
smallest functioning program that illustrates what I've done.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
vector<int> source;

// populate source with values
for(int i = 0; i != 10; ++i)
{
source.push_back(i);
}

// output the contents of the source vector
for(vector<int>::const_iterator csi = source.begin(); csi !=
source.end(); ++csi)
{
cout << *csi;
}

cout << endl;

// ** This section of code just seems like there ought
// to be an easier way. The code is switching the contents
// of the first half with the second half of the source vector

vector vector<int> temp2;
vector<int>::iterator si = source.begin();

// make si denote the middle of the source vector
for(int i = 0; i != 5; ++i)
{
si++;
}

// make temp hold the contents of the second half of the vector
// while temp2 holds the contenst of the first half.
temp.insert(temp.end(), si, source.end());
temp2.insert(temp2.end(), source.begin(), si);

// make source now hold the second half of the original vector
// followed by inserting the first half of the original vector
source = temp;
source.insert(source.end(), temp2.begin(), temp2.end());

// ** End Section that I think seems too complicated

for(vector<int>::const_iterator csi = source.begin(); csi !=
source.end(); ++csi)
{
cout << *csi;
}

return 0;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Éric Malenfant
Guest





PostPosted: Tue Aug 02, 2005 2:37 pm    Post subject: Re: Rearranging a Vector Reply with quote



std::swap_ranges may be what you're looking for:

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>

const std::vector<int>::size_type half_size = 5;
std::vector<int> tst;
std::fill_n(std::back_inserter(tst), half_size, 0);
std::fill_n(std::back_inserter(tst), half_size, 1);
std::cout << "Before swapping:n";
std::copy(tst.begin(), tst.end(),
std::ostream_iterator std::cout << std::endl;

std::swap_ranges(tst.begin(), tst.begin() + half_size,
tst.begin() + half_size);

std::cout << "After swapping:n";
std::copy(tst.begin(), tst.end(),
std::ostream_iterator std::cout << std::endl;

HTH,

Éric Malenfant


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
velthuijsen@hotmail.com
Guest





PostPosted: Tue Aug 02, 2005 2:41 pm    Post subject: Re: Rearranging a Vector Reply with quote



You might want to look at <algorithm>
It has a function named rotate.

The function rotate which works as follows:
std::rotate(Source.begin(), Source.begin()+OffsetValue,
Source.end());

The only thing left is to sort out what to store in OffsetValue.
It is either Source.size()/2 or (Source.size()+1)/2
It depends on where you want to assign the middle value of an odd sized
array.
The first option assigns the middle value to the lower part (of the
result), the second option to the upper part (of the result).


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Stefan Vetsch
Guest





PostPosted: Tue Aug 02, 2005 2:42 pm    Post subject: Re: Rearranging a Vector Reply with quote

hi [insert your real name here]

how about that (i think the swapVectorChunks is the most interesting
part for you):

#include <vector>
#include <iostream>

template <class _T>
void swapVectorChunks (_T & rclVector)
{
const _T::size_type xiOldSize = rclVector.size();
const _T::size_type xiHalf = xiOldSize / 2;

rclVector.resize(rclVector.size() + xiHalf, _T::value_type());

copy(rclVector.begin(),
rclVector.begin() + xiHalf,
rclVector.begin() + xiOldSize);

rclVector.erase(rclVector.begin(), rclVector.begin() + xiHalf);
}

inline std::ostream & operator <<(std::ostream & rclOs,
const std::vector {
std::vector<int>::const_iterator xIx;

rclOs << "{";

for(xIx = crclVec.begin(); xIx != crclVec.end(); ++xIx)
{
if(xIx != crclVec.begin())
rclOs << ", ";

rclOs << *xIx;
}

rclOs << "}";

return(rclOs);
}

int main()
{
std::vector
for(int xIx = 0; xIx < 10; ++xIx)
xclTheVec.push_back(xIx);

std::cout << xclTheVec << std::endl;

swapVectorChunks(xclTheVec);

std::cout << xclTheVec << std::endl;

return(0);
}

regards stefan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
rwp
Guest





PostPosted: Tue Aug 02, 2005 2:42 pm    Post subject: Re: Rearranging a Vector Reply with quote

Hi!
Something like this may be what you want


vector<int>::iterator si = source.begin();
vector<int>::iterator se = source.end();
ptrdiff_t d = distance(si, se);
vector<int>::iterator sm = si;
advance(sm, d/2);

for (; sm != se; ++si,++sm)
{
swap(*si, *sm);
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Liton
Guest





PostPosted: Tue Aug 02, 2005 2:43 pm    Post subject: Re: Rearranging a Vector Reply with quote

I would have rather used the following:

swap_ranges(source.begin(), source.begin()+5, source.begin()+5);


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
tony_in_da_uk@yahoo.co.uk
Guest





PostPosted: Tue Aug 02, 2005 2:47 pm    Post subject: Re: Rearranging a Vector Reply with quote

I'd suggest you simply call std::swap() on the elements you need to
exchange. E.g. Given a vector with elements [0] through [10], you'd
want to swap [0..4] with [6..11]:

typedef std::vector<T> Ts;
Ts ts;
ts.push_back( lots and lots );
Ts::size_type size = ts.size();
for (Ts::size_type i = 0; i <= size / 2; ++i)
std::swap(ts[i], ts[size - i]);

Cheers, Tony


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Allan W
Guest





PostPosted: Tue Aug 02, 2005 8:27 pm    Post subject: Re: Rearranging a Vector Reply with quote

[email]velthuijsen (AT) hotmail (DOT) com[/email] wrote:
Quote:
You might want to look at <algorithm
It has a function named rotate.

The function rotate which works as follows:
std::rotate(Source.begin(), Source.begin()+OffsetValue,
Source.end());

Your answer was by far the most elegant. Yes, the OP's original
problem is practically a textbook example of when to use rotate().

Quote:
The only thing left is to sort out what to store in OffsetValue...
[snip]


Quote:
From the OPs code, we can see that the size of source is exactly
10, so this is not an issue.


Here's the entire program, with rotate() substituted for the
entire "middle section", plus a few other modifications such
as comments and common code factoring.

#include #include <iostream>
#include <vector>

typedef std::vector<int> vecint;

void display(vecint &v) {
for(vecint::const_iterator csi=v.begin(); csi!=v.end(); ++csi)
std::cout << *csi;
std::cout << std::endl;
}

int main() {
vecint source;

// populate source with values
for(int i = 0; i != 10; ++i)
source.push_back(i);
display(source); // Display what we have so far

// Do the rotate
std::rotate(source.begin(), source.begin()+5, source.end());
display(source); // Display the results
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Francis Glassborow
Guest





PostPosted: Tue Aug 02, 2005 8:31 pm    Post subject: Re: Rearranging a Vector Reply with quote

In article <1122984015.787256.271810 (AT) z14g2000cwz (DOT) googlegroups.com>,
raisenero <iveymi (AT) gmail (DOT) com> writes
Quote:
I'm looking to improve the way I'm rearranging a vector, switching the
contents of the first half with the second half (i.e. The first half of
the vector is now the second half, and the second half is now the first
half.)
Use std::reverse() on the whole vector, then use it again on each half.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Dietmar Kuehl
Guest





PostPosted: Wed Aug 03, 2005 9:53 am    Post subject: Re: Rearranging a Vector Reply with quote

raisenero wrote:
Quote:
I'm looking to improve the way I'm rearranging a vector, switching the
contents of the first half with the second half (i.e. The first half of
the vector is now the second half, and the second half is now the first
half.)

This question nicely fits into the thread discussing the use of algorithms
versus the use of hand crafted loops: 'std::rotate()' it this the
algorithms you are looking for:

std::vector<T> v(...);
std::rotate(v.begin(), v.begin() + v.size() / 2, v.end());

Looks pretty clear to me. The only interesting part is when 'v' does not
contain an even number of elements. If you know that your sequence
actually contains an even number of elements, you can also use
'std::swap_ranges()' which would be clearer in this case.

Quote:
Most of my coding always seems to come down to
"Keep typing until the program eventually does what I want.",

You should, however, stop this practice as much as possible. Although
I do this occasionally, too, most of the time it is more effective to
think about the problem first and solve it with some clean approach.
Normally, I just need to fix compile-time errors before arriving at a
working solution.
--
<mailto:dietmar_kuehl (AT) yahoo (DOT) com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Pete Becker
Guest





PostPosted: Sat Aug 06, 2005 11:21 am    Post subject: Re: Rearranging a Vector Reply with quote

raisenero wrote:
Quote:
I'm looking to improve the way I'm rearranging a vector, switching the
contents of the first half with the second half (i.e. The first half of
the vector is now the second half, and the second half is now the first
half.)

My code works, but it just seems long and clunky to me, like I'm going
about doing it in a more complicated way than is necessary.

Good instinct. <g>

The simplest way to do what you've described is to use the algorithm
std::reverse. That will put the elements in the back half at the front,
and the elements in the front half at the back. However, it also changes
their relative order, which might not be what you want.

But think about it in a little more detail: if N is the index of the
middle element, you want to exchange element 0 with element N, element 1
with element N+1, element 2 with element N+2, continuing until you reach
the end.

But dont' implement it with indices like that, because that only works
for arrays. Once you see what's going on, use iterators instead. Get an
iterator pointing to the first element and an iterator pointing to the
middle element. Swap the elements they point to, then increment both
iterators. Repeat until the second one reaches the end of the range. Now
you've got an algorithm that works with forward iterators.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.