Minimum distance between two nodes in tree - c++

Given a unweighted and undirected tree with N nodes and N-1 edges I need to find minimum distance between source S and destination D.
Code :
vector<vector<int> >G(110);
bool check(int node,vector<int>path)
{
for(int i=0;i<path.size();++i)
{
if(path[i]==node)
return false;
}
return true;
}
int findMinpath(int source,int target,int totalnode,int totaledge)
{
vector<int>path;
path.push_back(source);
queue<vector<int> >q;
q.push(path);
while(!q.empty())
{
path=q.front();
q.pop();
int lastNode=path[path.size()-1];
if(lastNode==target)
{
return path.size()-1;
}
for(int i=0;i<G[lastNode].size();++i){
if(check(G[lastNode][i],path)){
vector<int>new_path(path.begin(),path.end());
new_path.push_back(G[lastNode][i]);
q.push(new_path);
}}}
return 1;
}
And then in main :
int N,S,E;
cin>>N>>S>>E;
for(int i=1;i<=N-1;++i)
{
int u,v;
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
cout<<findpaths(S,E,N,N-1)<<"\n";
Can it be further optimised as I need just minimum distance between S and E

You seem to be pushing vectors to your queue, each vector containing the actual path so far. But you can get away with only pushing nodes, since you only use the last node in those vectors anyway, and instead store the distance to each node from the source.
This will be much faster because you won't be copying vectors at each step.
Keep track of the distances in an array and also use them to make sure you don't visit a node multiple times.
Untested, but should get the point across:
int distance[110 + 1]; // d[i] = distance from source to i, initialize with a large number
int findMinpath(int source,int target,int totalnode,int totaledge)
{
for (int i = 0; i <= totalnode; ++i)
{
distance[i] = 2000000000;
}
queue<int> q;
q.push(source);
distance[source] = 0;
while(!q.empty())
{
node=q.front();
q.pop();
if(node==target)
{
return distance[node];
}
for(int i=0;i<G[node].size();++i){
if(distance[node] + 1 < distance[ G[node][i] ]){
distance[ G[node][i] ] = distance[node] + 1
q.push(G[node][i]);
}}}
return 1;
}

Related

Find the Largest Distance between nodes of a Tree ? Can someone explain me the approach for this

Link to problem
InterviewBit solution to the problem
int Solution::solve(vector<int> &A)
{
vector<int> hgt(A.size(),0);
int ans=0,maxx=0;
for(int i=A.size()-1;i>0;i--)
{
ans=max(ans,hgt[A[i]]+hgt[i]+1);
hgt[A[i]]=max(hgt[i]+1,hgt[A[i]]);
}
return ans;
}
Can someone explain to me the above code as well as their approach where they said as follows :
Pick any node u.
Find the node which is farthest from u, call it x.
Find the node which is farthest from x, call it q.
The answer will be the length of a path from x to q.
Basically the problem is to find out the diameter of a tree.
Diameter of a Tree - It is the longest path between two nodes in a
tree.
Longest path will always occur between two leaf nodes.
Let's say, from given array you have made the tree.
Now you can use 2 DFS or BFS to do it.
Procedure:
Start BFS from a random node (let's say we run from root node) and
find out the farthest node from it. Let the farthest node be X. It is
clear that X will always be a leaf node.
Now if we start BFS from X and check the farthest node from it (like
we did previously), we will get the diameter of the tree.
Sample code:
#define MAX 40001
vector<int> adj[MAX];
int dist[MAX];
int totalNode;
pair<int, int> _bfs(int startingNode) {
for(int i=0; i <= totalNode; i++) {
dist[i] = 0;
}
dist[startingNode] = 1;
int maxDistance = 0, farthestNode;
queue<int> q;
q.push(startingNode);
while(!q.empty()) {
int currNode = q.front();
q.pop();
int sz = adj[currNode].size();
for(int i = 0; i < sz; i++) {
int nextNode = adj[currNode][i];
if(dist[nextNode] == 0) {
dist[nextNode] = dist[currNode] + 1;
q.push(nextNode);
if(dist[nextNode] > maxDistance) {
maxDistance = dist[nextNode], farthestNode = nextNode;
}
}
}
}
return {farthestNode, maxDistance};
}
int _getDiameter(int &rootNode) {
// Running the first BFS from the root node (as explained in the procedue 1)
pair<int, int> pii = _bfs(rootNode);
// Running the second BFS from the furthest node we've found after running first BFS (as explained in the procedure 2)
pair<int, int> pii2 = _bfs(pii.first);
return pii2.second;
}
int Solution::solve(vector<int> &A) {
totalNode = A.size();
int rootNode;
if(totalNode == 1) return 0;
if(totalNode == 2) return 1;
for(int i = 0; i < totalNode; i++) adj[i].clear();
for(int i = 0; i < totalNode; i++) {
int n = A[i];
if(n == -1) rootNode = i;
else adj[i].push_back(n), adj[n].push_back(i);
}
return _getDiameter(rootNode) - 1;
}
Reference:
Diameter of a tree using DFS
Finding Diameter of a Tree using DFS with proof

Get path between 2 vertices using BFS in C++

I have written a code for this but it gives segmentation fault for disconnected graphs. It works fine for graphs that are connected.
How can I overcome this error?
vector<int> getPathBFS(int V, int** edges,int v1, int v2, int* visited, unordered_map<int,int> t)
{
queue<int> q;
q.push(v1);
visited[v1]=1;
int done=0;
while(!q.empty() && done==0)
{
for(int i=0;i<V;i++)
{
int front=q.front();
q.pop();
if(edges[front][i]==1 && visited[i]!=1)
{
q.push(i);
t[i]=front;
visited[i]=1;
if(i==v2)
{
done=1;
break;
}
}
}
}
vector<int> a;
if(done==0)
return a;
else
{
int k=v2;
a.push_back(v2);
while(k!=v1)
{
k=t[k];
a.push_back(k);
}
return a;
}
}
int main()
{
int V, E;
cin >> V >> E;
int** edges=new int*[V];
for(int i=0;i<V;i++)
{
edges[i]=new int[V];
for(int j=0;j<V;j++)
{
edges[i][j]=0;
}
}
for(int i=0;i<E;i++)
{
int f,s;
cin>>f>>s;
edges[f][s]=1;
edges[s][f]=1;
}
int v1,v2;
cin>>v1>>v2;
int* visited=new int[V];
for(int i=0;i<V;i++)
visited[i]=0;
unordered_map<int,int> t;
t[v2]=0;
vector<int> ans=getPathBFS(V,edges,v1,v2,visited,t);
for(int i=0;i<ans.size();i++ && !ans.empty())
{
cout<<ans[i]<<" ";
}
delete [] visited;
for(int i=0;i<V;i++)
{
delete [] edges[i];
}
delete [] edges;
return 0;
}
I did a dry run of the code. It will first create adjacency matrix edges and mark all the edges in it. Visited array is used to keep track of all the vertices that have been visited till now so that there is no infinite loop.
For the test case given below it will work till the queue contains 1 then it will pop 1 and the loop will end because there is no edge left that is connected to 1 and is not visited. After this the while loop should ideally break and as done==0 it should return an empty vector. I can't understand why the segmentation fault is coming.
The map is being used to keep track of which vertex was put in the queue by which vertex.
Doesn't work for the test case:
6 3
5 3
0 1
3 4
0 3
Below is the image of the graph for the above test case:
Here we need to find the path from vertex 0 to 3.
The input format is :
Number of Vertices in the graph, Number of edges
Edges between the vertices (for E lines),
Vertices between which we need to find the path.
You are popping the BFS queue incorrectly. Instead of the inner for loop, which is executed |V| times for each entry in the queue, you should pop the queue in the outer loop, which is executed once for each element in the queue.
vector<int> getPathBFS(int V, int** edges,int v1, int v2, int* visited, unordered_map<int,int> t)
{
queue<int> q;
q.push(v1);
visited[v1]=1;
int done=0;
while(!q.empty() && done==0)
{
int front=q.front();
q.pop();
for(int i=0;i<V;i++)
{
if(edges[front][i]==1 && visited[i]!=1)
{
q.push(i);
t[i]=front;
visited[i]=1;
if(i==v2)
{
done=1;
break;
}
}
}
}
vector<int> a;
if(done==0)
return a;
else
{
int k=v2;
a.push_back(v2);
while(k!=v1)
{
k=t[k];
a.push_back(k);
}
return a;
}
}
Also, in main function of your code, there is a redundant expression !ans.empty() in the for loop where you are printing the answer(s).

How to write code for Breadth-first search in C++

I have been trying to do a graph search for a problem from Hackerrank. Lastly, I have come up with
#include <cstdio>
#include <list>
using namespace std;
void bfs(list<int> adjacencyList[], int start, int countVertices) {
// initialize distance[]
int distance[countVertices];
for(int i=0;i < countVertices; i++) {
distance[i] = -1;
}
list<int>::iterator itr;
int lev = 0;
distance[start-1] = lev; // distance for the start vertex is 0
// using start -1 since distance is array which are 0-indexed
list<int> VertexQueue;
VertexQueue.push_back(start);
while(!VertexQueue.empty()) {
int neighbour = VertexQueue.front();
itr = adjacencyList[neighbour].begin();
while(itr != adjacencyList[neighbour].end()) {
int vertexInd = (*itr) - 1;
if(distance[vertexInd] == -1) { // a distance of -1 implies that the vertex is unexplored
distance[vertexInd] = (lev + 1) * 6;
VertexQueue.push_back(*itr);
}
itr++;
}
VertexQueue.pop_front();
lev++;
}
// print the result
for(int k=0;k< countVertices;k++) {
if (k==start-1) continue; // skip the start node
printf("%d ",distance[k]);
}
}
int main() {
int countVertices,countEdges,start,T,v1,v2;
scanf("%d", &T);
for(int i=0; i<T; i++) {
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
// input edges in graph
for(int j=0; j<countEdges; j++) {
scanf("%d%d",&v1,&v2);
adjacencyList[v1].push_back(v2);
adjacencyList[v2].push_back(v1); // since the graph is undirected
}
scanf("%d",&start);
bfs(adjacencyList, start, countVertices);
printf("\n");
}
return 0;
}
However, this is resulting in 'Segmentation Fault' and I cannot figure out where I am going wrong.
Also, I have comes across segmentation fault a lot of times, but have no idea how to debug it. Would be great if someone can give me an idea of that.
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
Above code appears wrong. If your indices start with 1, either make adjacencyList of size countVertices + 1 or decrease u and v before putting them in the list.
You can also use a (an unordered) map mapping vertex to a list which will not segfault.
Also not that VLA are not part of standard C++, so avoid them even if your compiler support them as extension.

Trouble with Dijkstra , finding all minimum paths

We have a problem here, we're trying to find all the shortest paths in graph from one node to another. We have already implemented dijkstra but we really dont know how to find them all.
Do we have to use BFS?
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
typedef pair <int, int> dist_node;
typedef pair <int, int> edge;
const int MAXN = 10000;
const int INF = 1 << 30;
vector <edge> g[MAXN];
int d[MAXN];
int p[MAXN];
int dijkstra(int s, int n,int t){
for (int i = 0; i <= n; ++i){
d[i] = INF; p[i] = -1;
}
priority_queue < dist_node, vector <dist_node>,greater<dist_node> > q;
d[s] = 0;
q.push(dist_node(0, s));
while (!q.empty()){
int dist = q.top().first;
int cur = q.top().second;
q.pop();
if (dist > d[cur]) continue;
for (int i = 0; i < g[cur].size(); ++i){
int next = g[cur][i].first;
int w_extra = g[cur][i].second;
if (d[cur] + w_extra < d[next]){
d[next] = d[cur] + w_extra;
p[next] = cur;
q.push(dist_node(d[next], next));
}
}
}
return d[t];
}
vector <int> findpath (int t){
vector <int> path;
int cur=t;
while(cur != -1){
path.push_back(cur);
cur = p[cur];
}
reverse(path.begin(), path.end());
return path;
}
This is our code, we believe we have to modify it but we really don't know where.
Currently, you are only saving/retrieving one of the shortest paths that you happen to find. Consider this example:
4 nodes
0 -> 1
0 -> 2
1 -> 3
2 -> 3
It becomes clear that you cannot have a single p[] value for each position, as in fact the 4th node (3) has 2 previous valid nodes: 1 and 2.
You could thus replace it with a vector<int> p[MAXN]; and work as follows:
if (d[cur] + w_extra < d[next]){
d[next] = d[cur] + w_extra;
p[next].clear();
p[next].push_back(cur);
q.push(dist_node(d[next], next));
}
else if(d[cur] + w_extra == d[next]){
p[next].push_back(cur); // a new shortest way of hitting this same node
}
You will also need to update your findpath() function as it will need to deal with "branches" resulting in several multiple paths, possibly an exponentially huge amount of paths depending on the graph. If you just need to print the paths, you could do something like this:
int answer[MAXN];
void findpath (int t, int depth){
if(t == -1){ // we reached the initial node of one shortest path
for(int i = depth-1; i >= 0; --i){
printf("%d ", answer[i]);
}
printf("%d\n", last_node); // the target end node of the search
return;
}
for(int i = p[t].size()-1; i >= 0; --i){
answer[depth] = p[t][i];
findpath(p[t][i], depth+1);
}
}
Note you'll need to do p[s].push_back(-1) at the beginning of your dijkstra, besides clearing this vector array between cases.

What is an efficient way to sort a graph?

For example suppose there are 3 nodes A,B,C and A links to B and C, B links to A and C, and C links to B and A. In visual form its like this
C <- A -> B //A links to B & C
A <- B -> C //B links to A & C
B <- C -> A //C links to B & A
Assume the A,B,C are held in an array like so [A,B,C] with index starting at 0. How can I efficiently sort the array [A,B,C] according to the value held by each node.
For example if A holds 4, B holds -2 and C holds -1, then sortGraph([A,B,C]) should return [B,C,A]. Hope its clear. Would it be possible if I can somehow utilize std::sort?
EDIT: Not basic sort algorithm. Let me clarify a bit more. Assume I have a list of Nodes [n0,n1...nm]. Each ni has a left and right neighbor index. For example, n1 left neight is n0 and its right neighbor is n2. I use index to represent the neighbor. If n1 is at index 1, then its left neighbor is at index 0 and its right neighbor is at index 2. If I sort the array, then I need to update the neighbor index as well. I don't want to really implement my own sorting algorithm, any advice on how to proceed?
If I understand the edited question correctly your graph is a circular linked list: each node points to the previous and next nodes, and the "last" node points to the "first" node as its next node.
There's nothing particularly special you need to do the sort that you want. Here are the basic steps I'd use.
Put all the nodes into an array.
Sort the array using any sorting algorithm (e.g. qsort).
Loop through the result and reset the prev/next pointers for each node, taking into account the special cases for the first and last node.
Here is a C++ implementation, hope is useful (it includes several algorithms like dijkstra, kruskal, for sorting it uses depth first search, etc...)
Graph.h
#ifndef __GRAPH_H
#define __GRAPH_H
#include <vector>
#include <stack>
#include <set>
typedef struct __edge_t
{
int v0, v1, w;
__edge_t():v0(-1),v1(-1),w(-1){}
__edge_t(int from, int to, int weight):v0(from),v1(to),w(weight){}
} edge_t;
class Graph
{
public:
Graph(void); // construct a graph with no vertex (and thus no edge)
Graph(int n); // construct a graph with n-vertex, but no edge
Graph(const Graph &graph); // deep copy of a graph, avoid if not necessary
public:
// #destructor
virtual ~Graph(void);
public:
inline int getVertexCount(void) const { return this->numV; }
inline int getEdgeCount(void) const { return this->numE; }
public:
// add an edge
// #param: from [in] - starting point of the edge
// #param: to [in] - finishing point of the edge
// #param: weight[in] - edge weight, only allow positive values
void addEdge(int from, int to, int weight=1);
// get all edges
// #param: edgeList[out] - an array with sufficient size to store the edges
void getAllEdges(edge_t edgeList[]);
public:
// topological sort
// #param: vertexList[out] - vertex order
void sort(int vertexList[]);
// dijkstra's shortest path algorithm
// #param: v[in] - starting vertex
// #param: path[out] - an array of <distance, prev> pair for each vertex
void dijkstra(int v, std::pair<int, int> path[]);
// kruskal's minimum spanning tree algorithm
// #param: graph[out] - the minimum spanning tree result
void kruskal(Graph &graph);
// floyd-warshall shortest distance algorithm
// #param: path[out] - a matrix of <distance, next> pair in C-style
void floydWarshall(std::pair<int, int> path[]);
private:
// resursive depth first search
void sort(int v, std::pair<int, int> timestamp[], std::stack<int> &order);
// find which set the vertex is in, used in kruskal
std::set<int>* findSet(int v, std::set<int> vertexSet[], int n);
// union two sets, used in kruskal
void setUnion(std::set<int>* s0, std::set<int>* s1);
// initialize this graph
void init(int n);
// initialize this graph by copying another
void init(const Graph &graph);
private:
int numV, numE; // number of vertices and edges
std::vector< std::pair<int, int> >* adjList; // adjacency list
};
#endif
Graph.cpp
#include "Graph.h"
#include <algorithm>
#include <map>
Graph::Graph()
:numV(0), numE(0), adjList(0)
{
}
Graph::Graph(int n)
:numV(0), numE(0), adjList(0)
{
this->init(n);
}
Graph::Graph(const Graph &graph)
:numV(0), numE(0), adjList(0)
{
this->init(graph);
}
Graph::~Graph()
{
delete[] this->adjList;
}
void Graph::init(int n)
{
if(this->adjList){
delete[] this->adjList;
}
this->numV = n;
this->numE = 0;
this->adjList = new std::vector< std::pair<int, int> >[n];
}
void Graph::init(const Graph &graph)
{
this->init(graph.numV);
for(int i = 0; i < numV; i++){
this->adjList[i] = graph.adjList[i];
}
}
void Graph::addEdge(int from, int to, int weight)
{
if(weight > 0){
this->adjList[from].push_back( std::make_pair(to, weight) );
this->numE++;
}
}
void Graph::getAllEdges(edge_t edgeList[])
{
int k = 0;
for(int i = 0; i < numV; i++){
for(int j = 0; j < this->adjList[i].size(); j++){
// add this edge to edgeList
edgeList[k++] = edge_t(i, this->adjList[i][j].first, this->adjList[i][j].second);
}
}
}
void Graph::sort(int vertexList[])
{
std::pair<int, int>* timestamp = new std::pair<int, int>[this->numV];
std::stack<int> order;
for(int i = 0; i < this->numV; i++){
timestamp[i].first = -1;
timestamp[i].second = -1;
}
for(int v = 0; v < this->numV; v++){
if(timestamp[v].first < 0){
this->sort(v, timestamp, order);
}
}
int i = 0;
while(!order.empty()){
vertexList[i++] = order.top();
order.pop();
}
delete[] timestamp;
return;
}
void Graph::sort(int v, std::pair<int, int> timestamp[], std::stack<int> &order)
{
// discover vertex v
timestamp[v].first = 1;
for(int i = 0; i < this->adjList[v].size(); i++){
int next = this->adjList[v][i].first;
if(timestamp[next].first < 0){
this->sort(next, timestamp, order);
}
}
// finish vertex v
timestamp[v].second = 1;
order.push(v);
return;
}
void Graph::dijkstra(int v, std::pair<int, int> path[])
{
int* q = new int[numV];
int numQ = numV;
for(int i = 0; i < this->numV; i++){
path[i].first = -1; // infinity distance
path[i].second = -1; // no path exists
q[i] = i;
}
// instant reachable to itself
path[v].first = 0;
path[v].second = -1;
while(numQ > 0){
int u = -1; // such node not exists
for(int i = 0; i < numV; i++){
if(q[i] >= 0
&& path[i].first >= 0
&& (u < 0 || path[i].first < path[u].first)){ //
u = i;
}
}
if(u == -1){
// all remaining nodes are unreachible
break;
}
// remove u from Q
q[u] = -1;
numQ--;
for(int i = 0; i < this->adjList[u].size(); i++){
std::pair<int, int>& edge = this->adjList[u][i];
int alt = path[u].first + edge.second;
if(path[edge.first].first < 0 || alt < path[ edge.first ].first){
path[ edge.first ].first = alt;
path[ edge.first ].second = u;
}
}
}
delete[] q;
return;
}
// compare two edges by their weight
bool edgeCmp(edge_t e0, edge_t e1)
{
return e0.w < e1.w;
}
std::set<int>* Graph::findSet(int v, std::set<int> vertexSet[], int n)
{
for(int i = 0; i < n; i++){
if(vertexSet[i].find(v) != vertexSet[i].end()){
return vertexSet+i;
}
}
return 0;
}
void Graph::setUnion(std::set<int>* s0, std::set<int>* s1)
{
if(s1->size() > s0->size()){
std::set<int>* temp = s0;
s0 = s1;
s1 = temp;
}
for(std::set<int>::iterator i = s1->begin(); i != s1->end(); i++){
s0->insert(*i);
}
s1->clear();
return;
}
void Graph::kruskal(Graph &graph)
{
std::vector<edge_t> edgeList;
edgeList.reserve(numE);
for(int i = 0; i < numV; i++){
for(int j = 0; j < this->adjList[i].size(); j++){
// add this edge to edgeList
edgeList.push_back( edge_t(i, this->adjList[i][j].first, this->adjList[i][j].second) );
}
}
// sort the list in ascending order
std::sort(edgeList.begin(), edgeList.end(), edgeCmp);
graph.init(numV);
// create disjoint set of the spanning tree constructed so far
std::set<int>* disjoint = new std::set<int>[this->numV];
for(int i = 0; i < numV; i++){
disjoint[i].insert(i);
}
for(int e = 0; e < edgeList.size(); e++){
// consider edgeList[e]
std::set<int>* s0 = this->findSet(edgeList[e].v0, disjoint, numV);
std::set<int>* s1 = this->findSet(edgeList[e].v1, disjoint, numV);
if(s0 == s1){
// adding this edge will make a cycle
continue;
}
// add this edge to MST
graph.addEdge(edgeList[e].v0, edgeList[e].v1, edgeList[e].w);
// union s0 & s1
this->setUnion(s0, s1);
}
delete[] disjoint;
return;
}
#define IDX(i,j) ((i)*numV+(j))
void Graph::floydWarshall(std::pair<int, int> path[])
{
// initialize
for(int i = 0; i < numV; i++){
for(int j = 0; j < numV; j++){
path[IDX(i,j)].first = -1;
path[IDX(i,j)].second = -1;
}
}
for(int i = 0; i < numV; i++){
for(int j = 0; j < this->adjList[i].size(); j++){
path[IDX(i,this->adjList[i][j].first)].first
= this->adjList[i][j].second;
path[IDX(i,this->adjList[i][j].first)].second
= this->adjList[i][j].first;
}
}
// dynamic programming
for(int k = 0; k < numV; k++){
for(int i = 0; i < numV; i++){
for(int j = 0; j < numV; j++){
if(path[IDX(i,k)].first == -1
|| path[IDX(k,j)].first == -1){
// no path exist from i-to-k or from k-to-j
continue;
}
if(path[IDX(i,j)].first == -1
|| path[IDX(i,j)].first > path[IDX(i,k)].first + path[IDX(k,j)].first){
// there is a shorter path from i-to-k, and from k-to-j
path[IDX(i,j)].first = path[IDX(i,k)].first + path[IDX(k,j)].first;
path[IDX(i,j)].second = k;
}
}
}
}
return;
}
If you are looking for sorting algorithms you should just ask google:
http://en.wikipedia.org/wiki/Sorting_algorithm
My personal favourite is the BogoSort coupled with parallel universe theory. The theory is that if you hook a machine up to the program that can destroy the universe, then if the list isn't sorted after one iteration it will destroy the universe. That way all the parallel universes except the one with the list sorted will be destroyed and you have a sorting algorithm with complexity O(1).
The best ....
Create a struct like this:
template<typename Container, typename Comparison = std::less<typename Container::value_type>>
struct SortHelper
{
Container const* container;
size_t org_index;
SortHelper( Container const* c, size_t index ):container(c), org_index(index) {}
bool operator<( SortHelper other ) const
{
return Comparison()( (*c)[org_index], (*other.c)[other.org_index] );
}
};
This lets you resort things however you want.
Now, make a std::vector<SortHelper<blah>>, sort it, and you now have a vector of instructions of where everything ends up going after you sort it.
Apply these instructions (there are a few ways). An easy way would be to reuse container pointer as a bool. Walk the sorted vector of helpers. Move the first entry to where it should go, moving what you found where it should go to where it should go, and repeat until you loop or the entire array is sorted. As you go, clear the container pointers in your helper struct, and check them to make sure you don't move an entry that has already been moved (this lets you detect loops, for example).
Once a loop has occurred, proceed down the vector looking for the next as-yet-not-in-right-place entry (with a non-null container pointer).