Removing elements from an unordered_multimap - c++

I have an unordered_multimap that represents an adjacency list, and several edges that have self loops. For example:
edges_ might be:
edges_.insert(Edges::value_type(1, std::make_pair(1, 0.0)));
edges_.insert(Edges::value_type(1, std::make_pair(1, 0.0)));
edges_.insert(Edges::value_type(1, std::make_pair(1, 0.0)));
edges_.insert(Edges::value_type(1, std::make_pair(2, 0.0)));
I would like to remove the 3 duplicate (1, (1, 0.0)) values. If I break after the edges_.erase(it) line only one of the three duplicates is removed.
If I advance through the iteration, regardless of whether I increment the iterator or not, it seems to crash after that. How can I remove all three?
template <typename T_NodeLabel, typename T_EdgeWeight>
class Graph
{
public:
using NodeId = unsigned int;
using Nodes = std::unordered_map<NodeId, T_NodeLabel>;
using AdjacencyList = std::pair<NodeId, T_EdgeWeight>;
using Edges = std::unordered_multimap<NodeId, AdjacencyList>;
void RemoveSelfLoops(NodeId node)
{
auto edges = edges_.equal_range(node);
for (auto it = edges.first; it != edges.second;)
{
if (it->second.first == node)
{
edges_.erase(it);
}
else
{
++it;
}
}
}
private:
Nodes nodes_;
Edges edges_;
};

After call to erase, your iterator is invalidated. And then you try to use it on the next iteration.
You need to use a return value of erase as the new iterator.

Related

Find all Hamiltonian Cycles using BFS

I know there's so many threads about this topic, but none of the ones I have found had helped me.
I have to find all the Hamiltonian cycles on a undirected graph using BFS. I have the code that search for a cycle (not hamiltonian), now I need to modify it and here's my problem. I'm not sure how to do this in a proper manner without thinking recursiverly.
My thoughts are that in order to find all Hamiltonian cycles using BFS I need:
Keep a track of one possible cycle (path).
Keep a count of the numbers of visited nodes. If I arrive to a "n" node that has the source as parent, I will need to check if all nodes are already visited.
So, in order to have a Hamiltonian Cycle, I must visit all nodes only once and finish when I arrive to a node that is inside of visited ones and that has "source" as adjacent.
Here's my graph.
https://i.stack.imgur.com/siLDn.png
And here's my code
#include <bits/stdc++.h>
using namespace std;
void addEdge(vector<int> adj[], int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
// return true if there's a cycle on the graph
bool thereIsCycle(vector<int> adj[], int s, int V)
{
// Mark all the vertices as not visited
vector<bool> visited(V, false);
// Set parent vertex for every vertex as -1.
vector<int> parent(V, -1);
// Create a queue for BFS
queue<int> q;
// Mark the current node as
// visited and enqueue it
visited[s] = true;
q.push(s);
while (!q.empty()) {
// Dequeue a vertex from queue and print it
int u = q.front();
q.pop();
// Get all adjacent vertices of the dequeued
// vertex u. If a adjacent has not been visited,
// then mark it visited and enqueue it. We also
// mark parent so that parent is not considered
// for cycle.
for (auto v : adj[u]) {
if (!visited[v]) {
visited[v] = true;
q.push(v);
parent[v] = u;
}
else if (parent[u] != v){
return true;
}
}
}
return false;
}
int main()
{
int V = 4;
vector<int> adj[V];
addEdge(adj, 0, 1);
addEdge(adj, 1, 2);
addEdge(adj, 2, 0);
addEdge(adj, 2, 3);
// check if there is a cycle from node 0
if (thereIsCycle(adj, 0, V)){
cout << "Yes";
}else{
cout << "No";
}
return 0;
}
Any suggests? Thank you all.
It looks like your code is currently looking for simple (non-Hamiltonian) cycles in the graph. If we add to the condition if (parent[u] != v){ return true; } checking that all vertices have been visited (all elements of the visited must be true), then it looks like the code will work correctly.
addEdge is not doing what you think it is.
Adj is intended to be the adjacency matrix of the graph. As implied by matrix this needs to be two dimensional.
2 for (auto v : adj[u]) makes no sense. adj[u] is an int, so it is meaningless to 'iterate' over it.
My suggestion: Take a step back and get the fundamentals right before tackling such an advanced problem. Create an actual graph class based on a correctly implemented adjacency matrix. Test you class with something simple, say listing all reachable nodes using BFS. Once that is working you can begin to move onto bigger challenges.

using C++ priority_queue comparator correctly

This question was asked in an interview recently
public interface PointsOnAPlane {
/**
* Stores a given point in an internal data structure
*/
void addPoint(Point point);
/**
* For given 'center' point returns a subset of 'm' stored points that are
* closer to the center than others.
*
* E.g. Stored: (0, 1) (0, 2) (0, 3) (0, 4) (0, 5)
*
* findNearest(new Point(0, 0), 3) -> (0, 1), (0, 2), (0, 3)
*/
vector<Point> findNearest(vector<Point> points, Point center, int m);
}
This is following approach I used
1) Create a max heap priority_queue to store the closest points
priority_queue<Point,vector<Point>,comp> pq;
2) Iterate the points vector and push a point if priority queue size < m
3) If size == m then compare the queue top with current point and pop if necessary
for(int i=0;i<points.size();i++)
{
if(pq.size() < m)
{
pq.push(points[i]);
}
else
{
if(compareDistance(points[i],pq.top(),center))
{
pq.pop();
pq.push(points[i]);
}
}
}
4) Finally put the contents of priority queue in a vector and return.
How should I write the comp and the compareDistance comparator which will allow me to store m points initially and then compare the current point with the one on top?
I think your approach can be changed so that it uses the priority_queue in a different way. The code becomes a bit complex since there's an if-statement in the for loop, and this if-statement controls when to add to the priority_queue. Why not add all the points to the priority_queue first, and then pop out m points? Let the priority_queue do all the work.
The key to implementing the findNearest function using a priority_queue is to realize that the comparator can be a lambda that captures the center parameter. So you can do something like so:
#include <queue>
#include <vector>
using namespace std;
struct Point { int x, y; };
constexpr int distance(const Point& l, const Point& r)
{
return (l.x - r.x)*(l.x - r.x) + (l.y - r.y)*(l.y - r.y);
}
vector<Point> findNearest(const vector<Point>& points, Point center, int m)
{
auto comparator = [center](const Point& l, const Point& r) {
return distance(l, center) > distance(r, center);
};
priority_queue<Point, vector<Point>, decltype(comparator)> pq(comparator);
for (auto&& p : points) {
pq.emplace(p);
}
vector<Point> result;
for (int i = 0; i < m; ++i) {
result.push_back(pq.top());
pq.pop();
}
return result;
}
In an interview setting it's also good to talk about the flaws in the algorithm.
This implementation runs in O(nlogn). There's going to be a clever algorithm that will beat this run time, especially since you only need the closest m points.
It uses O(n) more space because of the queue, and we should be able to do better. What's really happening in this function is a sort, and sorts can be implemented in-place.
Prone to integer overflow. A good idea would be use a template on the Point struct. You can also use a template to make the points container generic in the findNearest function. The container just has to support iteration.

Iterating over list of list of object

I want to iterate over a list of list of Object,
list<list<Point>> gnuPoints;
this is a static list which accepts list from various classes like circle and polygon all of which classes pushes multiple objects i.e Point(x,y) to the list
while (angle != 360)
{
double x = m_radius*cos(angle);
double y = m_radius*sin(angle);
angle += 30;
circlePoint.push_back(Point(x, y));
}
similarly goes with Polygon and line shapes
polygonPoint.push_back(Point(x,y));
linePoint.Push_back(point(x,y));
then these lists are pushed in gnuPoint(list< list< Point> >).
gnuPoints.push_back(circlePoints);
gnuPoints.push_back(polygonPoints);
gnuPoints.push_back(linePoints);
now i want to write all these x,y values of different shapes in a file,
To iterate over it i cant find any particular solution after this code.
for (list<list<Point>>::iterator it = Point::gnuPoints.begin();
it != Point::gnuPoints.end();
it++)
{
//My assumption is that another For loop would come but could not apply
as I don't know what is available at the first index of gnuPoints list.
}
for (list<list<Point>>::iterator it = Point::gnuPoints.begin();
it != Point::gnuPoints.end();
it++)
{
for (list<Point>::iterator innerIt = it->begin(); innerIt != it->end(); ++innerIt)
}
If you are already on a compiler that supports c++11, this could be simply written as:
for (const auto& container : Point::gnuPoints)
{
for (const auto& item : container)
{
}
}

Find pointer of object in vector C++

I have a class which is called Position:
class Position
{
public:
... //Constructor, Destructor, ...
private:
signed int x_;
signed int y_;
}
Then I have a vector which stores pointers of Positions:
std::vector<Position*> positions
How can I check if a Position is contained in the vector? For example, I have an object of a Position:
Position* p_ = new Position(0, 0);
And I want to check if the vector contains a Position with the same coordinates?
Which operator do I have to overload?
Thanks,
Barbara
auto it = find_if(positions.begin(), positions.end(),
[=](position* p)
{
return p->x() == p_->x() && p->y() == p_->y();
});
if(it != positions.end())
{
//object found
}
However, unless you have a real reason to store pointers in the vector (e.g. you're going to use polymorphism), storing objects directly is much simpler.
vector<position> v;
v.push_back(Position(1, 2));
...
Position p_(1, 4);
auto it = find_if(v.begin(), v.end(),
[=](position p)
{
return p.x() == p_.x() && p.y() == p_.y();
});
if(it != v.end())
{
//position found
}
In the latter case it is possible to further simplify the code by overloading operator == for position.
bool operator == (position p1, position p2)
{
return p1.x == p2.x && p1.y == p2.y; //assuming operator == is declared friend
}
Then you can
auto it = find(v.begin(), v.end(), p_);
And I want to check if the vector contains a Position with the same coordinates? Which operator do I have to overload?
If you had a vector of positions (instead of vector of pointers to positions) the operator you'd have to overload would be:
bool Position::operator==(const Position& p);
With this code, you could write (assuming you are using std::vector<Position> positions;, and not std::vector<Position*> positions;):
using std::find; using std::begin; using std::end;
const Position p{}; // element that is sought after
bool exists = (end(positions) != find(begin(positions), end(positions), p));
[comment:] Yeah I am also quite unsure about this. I asked one of my teammates why he does this [i.e. store by pointers] and he said it would be more efficient and faster and it should not be changed - EVER.
It is probably not more efficient, nor faster than storing by values. If you are not in a position to change the vector though, you will have to add the operator declared above, and also a predicate that compares a Position instance to the values in a Position pointer, and using that with std::find:
const Position p{}; // element that is sought after
auto matches_position = [&p](Position const* const x)
{
return x != nullptr // can positions in the vector be null?
&& p == *x;
};
bool exists = (end(positions) != find(begin(positions), end(positions),
matches_position));
== Coping strategy ==
I would go for the first version (no pointers in the vector), by doing the following:
create a new (minimalistic) project, that fills two separate vectors, with a bunch of randomized positions (fixed number of positions, between 2000 and 10000 instances or so); the vectors should contain positions by pointer and by value respectively, with the same values in each position (a position should be in both vectors, at the same index)
perform the search for the same values in both vectors.
repeat the searches multiple times (to average and minimize timing errors)
take results to your colleague(s).
There are two outcomes from this: either your colleague is right (which seems pretty unlikely, but hey! who knows?) or he is wrong, and his code that "should never be changed" - well ... it should be changed.
Add this to class Position
Public:
bool isSamePosition(position * p){
return p->x == this->x && p->y ==this->y;
}
Then compare with all in the vector
bool unique = true;
for (int i = 0; i < positions.length(); ++i){
if (new_position->isSamePosition(positions[i])
unique = false;
}
if (unique==true)
//do something like push_back vector
;

boost astar_search with edge container

I'm working on a SFML / C++ project and I've some troubles with the boost graph library, in particular with the astar_search. I generated a Voronoi Diagram for a random map and a graph to use the astar method of the Boost Graph Library with the middle of each centers of the polygons
Establishment of the edges :
for (Polygon *u : this->_map->_polygons)
{
if (u->getPolygonType() == u->GROUND)
{
WayPointID wpID = boost::add_vertex(graphe);
graphe[wpID].pos = u->getCenter();
for (std::deque<Edge_ *>::iterator it = u->getEdges().begin() ; it != u->getEdges().end() ; ++it)
{
std::pair<Polygon *, Polygon *> t = (*it)->_polygonsOwn;
WayPointID wpID2 = boost::add_vertex(graphe);
graphe[wpID2].pos = t.second->getCenter();
if (t.first->getPolygonType() == t.first->GROUND)
{
float dx = abs(graphe[wpID].pos.first - graphe[wpID2].pos.first);
float dy = abs(graphe[wpID].pos.second - graphe[wpID2].pos.second);
boost::add_edge(wpID, wpID2, WayPointConnection(sqrt(dx * dx + dy * dy)), graphe);
}
The edges are correctly established, when I want to draw them :
So I need to use the astar search with these edges but my code don't work :(
struct found_goal {};
class astar_goal_visitor : public boost::default_astar_visitor{
private:
typedef boost::adjacency_list<
boost::listS,
boost::vecS,
boost::undirectedS,
WayPoint,
WayPointConnection
> WayPointGraph;
typedef WayPointGraph::vertex_descriptor WayPointID;
typedef WayPointGraph::edge_descriptor WayPointConnectionID;
WayPointGraph graphe;
WayPointID m_goal;
public:
astar_goal_visitor(WayPointID goal) : m_goal(goal) {}
void examine_vertex(WayPointID u, const WayPointGraph &amp){
if(u == m_goal)
throw found_goal();
}
};
And the implementation :
boost::mt19937 gen(time(0));
std::vector<WayPointID> p(boost::num_vertices(graphe));
std::vector<float> d(boost::num_vertices(graphe));
WayPointID start = boost::random_vertex(graphe, gen);
WayPointID goal = boost::random_vertex(graphe, gen);
try {
boost::astar_search
(
graphe,
start,
boost::astar_heuristic<WayPointGraph, float>(),
boost::predecessor_map(&p[0]).distance_map(&d[0]).visitor(astar_goal_visitor(goal)).weight_map(boost::get(&WayPointConnection::dist, graphe))
);
} catch(found_goal fg) {
std::cout << "is ok" << std::endl;
}
The path is never found ... If you can help me about the astar implementation I'd appreciate it :)/
I'm sorry for the length of this post :(, the boost astar needs a lot of code implementation.
Thank you in advance
You insert too many vertices. You should keep, say, an unordred_map<Polygon*,vertex_descriptor>. Before calling add_vertex for a given polygon P you should first check whether P is already in the map. If yes, use the vertex_descriptor corresponding to P, do not call add_vertex. Otherwise, call v= add_vertex and add the pair (P,v) to the map.
Good luck!