 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
raisenero Guest
|
Posted: Tue Aug 02, 2005 12:47 pm Post subject: Rearranging a Vector |
|
|
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
|
Posted: Tue Aug 02, 2005 2:37 pm Post subject: Re: Rearranging a Vector |
|
|
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
|
Posted: Tue Aug 02, 2005 2:41 pm Post subject: Re: Rearranging a Vector |
|
|
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
|
Posted: Tue Aug 02, 2005 2:42 pm Post subject: Re: Rearranging a Vector |
|
|
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
|
Posted: Tue Aug 02, 2005 2:42 pm Post subject: Re: Rearranging a Vector |
|
|
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
|
Posted: Tue Aug 02, 2005 2:43 pm Post subject: Re: Rearranging a Vector |
|
|
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
|
Posted: Tue Aug 02, 2005 2:47 pm Post subject: Re: Rearranging a Vector |
|
|
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
|
Posted: Tue Aug 02, 2005 8:27 pm Post subject: Re: Rearranging a Vector |
|
|
[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
|
Posted: Tue Aug 02, 2005 8:31 pm Post subject: Re: Rearranging a Vector |
|
|
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
|
Posted: Wed Aug 03, 2005 9:53 am Post subject: Re: Rearranging a Vector |
|
|
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
|
Posted: Sat Aug 06, 2005 11:21 am Post subject: Re: Rearranging a Vector |
|
|
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 |
|
 |
|
|
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
|
|