views:

203

answers:

5

Hi,

I've got a std::vector which I need to sort by selected algorithms for certain operations, but to maintain its original state (e.g. items ordered by when they were entered) the rest of the time.

Obviously I can use std::copy to create a temporary vector and sort that, but I'm wondering if there's a better way, possibly by timestamping the items entered.

Cheers

+15  A: 

You could create a std::vector that holds all the indexes of the first vector. You could then sort the index-vector as you like. This should be fast and most importantly, doesn't mean you have to copy the first vector (which is probably more costly!).

monoceres
+1 for fastest fingers, was posting more or less the same answer.
Binary Worrier
I would have used an old fashioned malloc'd array of pointers and called qsort but this works too.
Joshua
@Joshua: most of the time, this will work better -- qsort is usually quite a bit slower than std::sort.
Jerry Coffin
I bet generating the vector of indices takes longer than copying the original vector!
I'll take that bet, @Stingray. I get to provide the class we're storing in the vector. (In particular, I get to define the copy constructor and assignment operator.) I also get to choose how many of them we're storing. (Lots!)
Rob Kennedy
@Rob: Sorry, I was assuming POD types...
Sounds good, could you describe how to do that? Code example would help.
deworde
+2  A: 

Any given vector will be sorted in at most one way at any time.

There are two alternatives:

Copy to a temporary vector and sort that as desired. Unless the vector is very large and you've got limited space, this is almost certainly the best way. Even if you're concerned about performance, the cost of making a copy is going to be smaller than the cost of sorting, and if the cost of copying is significant the sorting's going to be a lot slower than the copying.

Alternatively, you could keep some way (the timestamp you mentioned?) of being able to sort the vector back to the original order. This is going to be slow, since you'd only want to do this if the vector was very large, but if you can't make a temporary vector this is the only way to do it.

David Thornley
Copying could be expensive if it's not a vector of pointers, also depends on how the copy ctor is implmented.
Binary Worrier
@Binary Worrier: I think David's point is that the sort operation on the vector does a bunch of copies when it's moving elements around. If the sort is O(n log n) adding an O(n) copy operation initially doesn't change the overall time complexity.
Michael Burr
If copying is expensive, then sorting is more so. How do you expect to get a sorted vector without copying each element to its new place? (Actually, the copy constructor could be far more expensive than the assignment operator, in which case the proper thing to do is to fix the copy constructor. I'm not thinking of any case where the copy constructor should be that much more expensive.)
David Thornley
By a) sorting a vector of pointers or b) indirectly sorting the vector by sorting an array/vector of ints that map to the positions of the objects in the original vector. No copying.
Binary Worrier
A: 

Whatever item you are sorting, you could wrap it in a structure that has multiple sort-fields.

struct someThing
{
    int sortOrder1;
    int sortOrder2;
    ...
    int sortOrderN;
    //payload data object here
} //note: this code may have some sytax errors (I haven't actually tried compiling this ;), but hope the idea is clear

(or maybe add the sort orders to the base structure itself?)

Then when you need can calculate the different sort orders, and re-order your list depending on which sort-order you need.

FrustratedWithFormsDesigner
+4  A: 

If you don't mind a little bit of Boost you can use the MultiIndex library. See this answer from me where you'll find some example code.

Basically, it allows you to keep several "views" of the same data, each with a different order. In your case you'll be able to keep a "sequence" view, where the data is in order of insertion (like a vector) and a "sorted" view in which the data is sorted according to some criterion (like a map).

Manuel
A: 

I suggest storing smart pointers, to the original data, in each vector. std::vector allows you to supply different methods for sorting. Also, with smart pointers, they will be destroyed automatically when all references to the item are removed.

Thomas Matthews