Reputation: 6998
I have an array of lists (array<list<Client*>, 10>
) and I want to see which list has the lowest item count in it so I can add to that. I'm doing a small balancing system here and as clients come in I want to add them to 1 or the 10 lists which has the lowest number of other clients to keep the lists level.
Would I have to do a bubble sort here or is there some sweet stl way to handle something like this?
Upvotes: 2
Views: 103
Reputation: 490663
If all the clients are serviced (removed from the lists) at the same rate, then round-robin scheduling is the obvious answer.
If, however, there's variability (e.g., you're simulating customers who take different lengths of time) you probably want something like a priority queue of collections, using the length of each collection as the priority. This will place the current highest priority item (shortest list) in a known location (usually the first item in the queue). After you insert a new item, you (potentially ) "sift" that down the heap to maintain the heap property.
This allows you to insert or remove an item with O(log N) complexity, where something like std::min_element
would require O(N) complexity.
As an aside: if you care about speed, chances are pretty good that list
isn't a great choice either. A list has individually allocated nodes, and each node contains two pointers. These factors tend to lead to poor locality of reference, which generally implies poor cache usage. A priority_queue of vectors instead (for only one possibility) will often work better.
Upvotes: 1
Reputation: 41220
If you actually need it sorted such that the list with the lowest item count appears first (and not std::min_element
to simply get the lowest item like Barry suggested), then you could use std::partial_sort, e.g.:
std::array<int,10> myArray{10,9,8,7,6,5,4,3,2,1};
std::partial_sort(myArray.begin(),myArray.begin()+1,myArray.end(),
[](const int& lhs, const int& rhs){return lhs < rhs;});
Where the last parameter here is a lambda for comparison. You'd replace it with something like
[](const list<Client*>& lhs, const list<Client*>& rhs){return lhs.size() < rhs.size();)
Upvotes: 1
Reputation: 1125
If the lists start at zero elements when you start adding to them and you want to keep them perfectly balanced, consider just adding to the lists round robin style:
Pseudo Code:
index = 0
list to add to = lists[index % list length]
index++
Upvotes: 5
Reputation: 303890
That's precisely what std::min_element
is for:
std::array<std::list<Client*>, 10> arr;
auto it = std::min_element(arr.begin(), arr.end(),
[](const std::list<Client*>& a, const std::list<Client*>& b){
return a.size() < b.size();
});
That'll give you an iterator into which list
has the fewest elements.
Upvotes: 5