I'm beginning programming, so sorry for my lack of knowledge. How can I set elements in vector in a specific order? I would like to swap elements in the way that there won't be same elements next to each other. For example vector contains:
{1, 2, 2, 2, 3, 3, 4, 4, 4}
and I'd like it to be like:
{1, 2, 4, 3, 4, 2, 3, 2, 4}
Thanks for help.
edit: Hello again, I found not the best solution, maybe you can take a look and correct it?
map<unsigned,unsigned> Map;
for(vector<unsigned>::iterator i=V.begin();i!=V.end();++i)
{
map<unsigned,unsigned>::iterator f=Map.find(*i);
if(f==Map.end()) Map[*i]=1;
else ++f->second;
}
for(bool more=true;more;)
{
more=false;
for(map<unsigned,unsigned>::iterator i=Map.begin();i!=Map.end();++i)
{
if(i->second)
{
--i->second;
cout<<i->first<<", ";
more=true;
}
}
}
Now, for { 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 } it gives me { 1, 2, 3, 4, 2, 3, 4, 2, 4, 4, 4, 4 } instead of eg { 4, 1, 4, 2, 4, 3, 4, 2, 4, 3, 4, 2 }. How can it be done? Thanks
credits: _13th_Dragon
In order to achieve (1), one can simply use std::map<V, unsigned>
. However, for the second, one needs an ordered set of std::pair<V, unsigned int>
, ordered by the second value. Since we want to keep track of how many times we need to use a given value, the second value cannot be constant. Also, we don't want to change the order if we happen to decrease the count of a given value much. All in all we get
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
// In the pair, first is the original value, while
// second is the number occurrences of that value.
typedef std::pair<int, unsigned> value_counter;
int main(){
std::vector<int> sequence = { 0, 1, 3, 3, 4, 1, 2, 2, 2, 2 , 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 };
std::map<int, unsigned> count;
for( auto i : sequence){
count[i]++;
}
std::vector<value_counter> store( count.size() );
std::copy(count.begin(), count.end(), store.begin());
// Sort by the second value
std::sort(store.begin(), store.end(),
[](const value_counter& a, const value_counter& b){
return a.second > b.second;
});
std::vector<int> result;
// We need two indices, one for the current value
// and the other one for the alternative
for(unsigned i = 0, j = 1; i < store.size(); ++i){
while(store[i].second > 0){
result.push_back(store[i].first);
store[i].second--;
if(store[i].second == 0)
continue;
if( j <= i)
j = i + 1;
while(j < store.size() && store[j].second == 0)
++j;
if(j >= store.size()){
std::cerr << "Not enough elements for filling!" << std::endl;
return 1;
}
else {
result.push_back(store[j].first);
store[j].second--;
}
}
}
for( auto r : result){
std::cout << r << " ";
}
}
Instead of using a typedef
you could create an alternative counter which has better names than first
and second
, but that makes copying from the map a little bit more verbose.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.