Custom sort vector of pair based on their values

I would NOT use std::sort for this. Let me explain why.

1) Your sort depends on information about ALL the members to be sorted, not a pairwise comparison. In your example, the reason [0,1] comes before [4,5] is the presence of [1,4] in the list. If you had instead had [5,0] in the list, it would have implied [0,1] comes AFTER [4,5]. Worse, if both are in the list, you have no clear basis for selecting which should come first.

2) Your sorting method is not well defined. You haven't explained, for example, why [0,1] should appear before [0,2] and not after. Similarly, if you have [[0,1],[1,2],[1,3]], there is no way to know whether [1,2] or [1,3] should be second.

One other important consideration. It feels like you may be doing some sort of pathfinding/chaining problem. It's possible your data structure is not well suited to your problem, overall. That's just an observation, but perhaps worth considering.


You can think of this problem as a graph problem. Each of your pairs represents an edge in a directed graph. For example, the pair (0, 2) means "there's an edge from node 0 to node 2," and the pair (2, 5) means "there's an edge from node 2 to node 5."

If you think of things this way, a series of edges where the second element of each pair matches the first element of the next pair corresponds to a path in the graph. For example, the sorted ordering you've given has two paths in it: 0 -> 1 -> 4 -> 5 -> 6 and 0 -> 2 -> 3 -> 4. Consequently, the problem you're trying to solve is the following: how do you break the edges in the graph apart into the smallest number of edge-disjoint paths? Once you've solved that, you can then output those paths in any order you'd like to form a sorted ordering along the lines of what you're trying to do.

You can't solve this problem with std::sort. As an example, suppose that you have the edges (0, 1), (0, 2), (2, 3), and (1, 3). In that case, both of these orderings are valid:

(0, 1)          (0, 2)
(1, 3)          (2, 3)
(0, 2)          (0, 1)
(2, 3)          (1, 3)

This is a problem. Because (0, 1) precedes (0, 2) in the first ordering and (0, 2) precedes (0, 1) in the second ordering, the only way the comparator could be a strict weak ordering is if (0, 1) and (0, 2) are incomparable. That means that in any sorted ordering, all the elements between (0, 1) and (0, 2) (inclusive) must also be incomparable because of transitivity of incomparability. In other words, we should be able to take any ordering, permute the elements between (0, 1) and (0, 2) (inclusive), and get back a new ordering. This would mean that this should be a valid ordering, even though it isn't because there's a vastly better solution:

(0, 1)          (0, 1)
(1, 3)   -->    (0, 2)
(0, 2)          (1, 3)
(2, 3)          (2, 3)

So there's no way to solve this using std::sort.

What I'm not sure about is what the best way to solve this is. This seems related to a flow problem, but I'm not sure how to set it up. If I think of anything, I'll update this answer. Thanks for posting something so interesting!