Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to contain my class with std::set

Tags:

c++

I'm trying to write a program in C++ language.

Class Edge indicates the connection between u and v.

Edge a which indicates the connection between u and v. Edge a' which indicates the connection between v and u. Edge a and a' indicate same connection. So, I want to contain either a or a'.

I know "set" stores unique elements. So I want to use this. I define operator< below.

When I search bugs, I found some trubles. I store (1,2) -> (1,2) -> (2,1) -> (3,2) -> (2,3) -> (5,2).

But set stores

1 2
5 2
3 2
1 2 <-- Why ????

Could you help me??

#include<iostream>
#include<set>

class Edge {

private:
  int u, v;

public:
  bool operator< (const Edge& e) const {
    bool result = true;
    if( (u == e.u && v == e.v) || (v == e.u && u == e.v) ) {
      result = false;
    }
    return result;
  }

  std::pair<int, int> pair() const {
    return std::pair<int, int>(u, v);
  }

  Edge(int u_, int v_) : u(u_), v(v_) {}
};

int main(void) {
  std::set<Edge> edge;
  std::set<Edge>::iterator eit;

  edge.insert(Edge(1,2)); // <-- (1,2) can be contained.
  edge.insert(Edge(1,2)); // <-- (1,2) doesn't have to be contained.
  edge.insert(Edge(2,1)); // <-- (2,2) doesn't have to be contained.

  edge.insert(Edge(3,2)); // <-- (3,2) can be contained.
  edge.insert(Edge(2,3)); // <-- (2,3) doesn't have to be contained.
  edge.insert(Edge(5,2)); // <-- (5,2) doesn't have to be contained.

  edge.insert(Edge(1,2)); // <-- (1,2) doesn't have to be contained. But edge contains this. Why?

  for(eit = edge.begin(); eit != edge.end(); eit++) {

    std::cout << (*eit).pair().first << " " << (*eit).pair().second << std::endl;
  }

  return 0;
}
like image 658
Akira Noguchi Avatar asked Dec 16 '11 05:12

Akira Noguchi


People also ask

How do you find something in a set in C++?

C++ set find() function is used to find an element with the given value val. If it finds the element then it returns an iterator pointing to the element otherwise, it returns an iterator pointing to the end of the set i.e. set::end().

What is set class in C++?

The C++ Standard Library container class set is used to store and retrieve data from a collection. The values of the elements in the set are unique and serve as the key values according to which the data is automatically ordered.

What Library is set in c++?

Sets are a type of associative container in which each element has to be unique because the value of the element identifies it. The values are stored in a specific sorted order i.e. either ascending or descending.

Is std :: set ordered?

Yes, std::set stores its elements in such a way that iterating over the elements will be done in sorted order (and the call to std::adjacent_find is to show that std::set stores unique items as well).


2 Answers

Your operator< is testing for equality, not less-than. Try:

if (u < e.u)
    result = true;
else if (e.u < u)
    result = false;
else
    result = (v < e.v);

Edit: According to the comment I misunderstood the question - the set is supposed to reject a duplicate in either order. The comparison operator needs to be consistent, so here's one that might work.

if (min(u,v) < min(e.u,e.v))
    result = true;
else if (min(e.u,e.v) < min(u,v))
    result = false;
else
    result = (max(u,v) < max(e.u,e.v));
like image 180
Mark Ransom Avatar answered Oct 30 '22 08:10

Mark Ransom


You operator < implementation is more like an equality implementation. try doing lexical less than implementation:

bool operator< (const Edge& e) const
{
    return (u < e.u) || (u == e.u && v < e.v);
}
like image 29
Dani Avatar answered Oct 30 '22 08:10

Dani