[Lemon-commits] deba: r3130 - hugo/trunk/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Thu Jan 11 22:06:48 CET 2007
Author: deba
Date: Thu Jan 11 22:06:47 2007
New Revision: 3130
Modified:
hugo/trunk/lemon/list_graph.h
hugo/trunk/lemon/smart_graph.h
Log:
Changing implementation of undirected graphs
slightly faster, 10% speed-up
Modified: hugo/trunk/lemon/list_graph.h
==============================================================================
--- hugo/trunk/lemon/list_graph.h (original)
+++ hugo/trunk/lemon/list_graph.h Thu Jan 11 22:06:47 2007
@@ -98,16 +98,7 @@
first_free_node(-1), edges(), first_free_edge(-1) {}
- /// Maximum node ID.
-
- /// Maximum node ID.
- ///\sa id(Node)
int maxNodeId() const { return nodes.size()-1; }
-
- /// Maximum edge ID.
-
- /// Maximum edge ID.
- ///\sa id(Edge)
int maxEdgeId() const { return edges.size()-1; }
Node source(Edge e) const { return Node(edges[e.id].source); }
@@ -164,12 +155,6 @@
static Node nodeFromId(int id) { return Node(id);}
static Edge edgeFromId(int id) { return Edge(id);}
- /// Adds a new node to the graph.
-
- /// Adds a new node to the graph.
- ///
- /// \warning It adds the new node to the front of the list.
- /// (i.e. the lastly added node becomes the first.)
Node addNode() {
int n;
@@ -735,10 +720,368 @@
///@}
- /**************** Undirected List Graph ****************/
+ class ListUGraphBase {
+
+ protected:
+
+ struct NodeT {
+ int first_out;
+ int prev, next;
+ };
+
+ struct EdgeT {
+ int target;
+ int prev_out, next_out;
+ };
+
+ std::vector<NodeT> nodes;
+
+ int first_node;
+
+ int first_free_node;
+
+ std::vector<EdgeT> edges;
+
+ int first_free_edge;
+
+ public:
+
+ typedef ListUGraphBase Graph;
+
+ class Node {
+ friend class ListUGraphBase;
+ protected:
+
+ int id;
+ explicit Node(int pid) { id = pid;}
+
+ public:
+ Node() {}
+ Node (Invalid) { id = -1; }
+ bool operator==(const Node& node) const {return id == node.id;}
+ bool operator!=(const Node& node) const {return id != node.id;}
+ bool operator<(const Node& node) const {return id < node.id;}
+ };
+
+ class UEdge {
+ friend class ListUGraphBase;
+ protected:
+
+ int id;
+ explicit UEdge(int pid) { id = pid;}
+
+ public:
+ UEdge() {}
+ UEdge (Invalid) { id = -1; }
+ bool operator==(const UEdge& edge) const {return id == edge.id;}
+ bool operator!=(const UEdge& edge) const {return id != edge.id;}
+ bool operator<(const UEdge& edge) const {return id < edge.id;}
+ };
+
+ class Edge {
+ friend class ListUGraphBase;
+ protected:
+
+ int id;
+ explicit Edge(int pid) { id = pid;}
+
+ public:
+ operator UEdge() const { return UEdge(id / 2); }
+
+ Edge() {}
+ Edge (Invalid) { id = -1; }
+ bool operator==(const Edge& edge) const {return id == edge.id;}
+ bool operator!=(const Edge& edge) const {return id != edge.id;}
+ bool operator<(const Edge& edge) const {return id < edge.id;}
+ };
+
+
+
+ ListUGraphBase()
+ : nodes(), first_node(-1),
+ first_free_node(-1), edges(), first_free_edge(-1) {}
+
+
+ int maxNodeId() const { return nodes.size()-1; }
+ int maxUEdgeId() const { return edges.size() / 2 - 1; }
+ int maxEdgeId() const { return edges.size()-1; }
+
+ Node source(Edge e) const { return Node(edges[e.id ^ 1].target); }
+ Node target(Edge e) const { return Node(edges[e.id].target); }
+
+ Node source(UEdge e) const { return Node(edges[2 * e.id].target); }
+ Node target(UEdge e) const { return Node(edges[2 * e.id + 1].target); }
+
+ static bool direction(Edge e) {
+ return (e.id & 1) == 1;
+ }
+
+ static Edge direct(UEdge e, bool d) {
+ return Edge(e.id * 2 + (d ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node.id = first_node;
+ }
+
+ void next(Node& node) const {
+ node.id = nodes[node.id].next;
+ }
+
+ void first(Edge& e) const {
+ int n = first_node;
+ while (n != -1 && nodes[n].first_out == -1) {
+ n = nodes[n].next;
+ }
+ e.id = (n == -1) ? -1 : nodes[n].first_out;
+ }
+
+ void next(Edge& e) const {
+ if (edges[e.id].next_out != -1) {
+ e.id = edges[e.id].next_out;
+ } else {
+ int n = nodes[edges[e.id ^ 1].target].next;
+ while(n != -1 && nodes[n].first_out == -1) {
+ n = nodes[n].next;
+ }
+ e.id = (n == -1) ? -1 : nodes[n].first_out;
+ }
+ }
+
+ void first(UEdge& e) const {
+ int n = first_node;
+ while (n != -1) {
+ e.id = nodes[n].first_out;
+ while ((e.id & 1) != 1) {
+ e.id = edges[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ }
+ e.id = -1;
+ }
+
+ void next(UEdge& e) const {
+ int n = edges[e.id * 2].target;
+ e.id = edges[(e.id * 2) | 1].next_out;
+ while ((e.id & 1) != 1) {
+ e.id = edges[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ while (n != -1) {
+ e.id = nodes[n].first_out;
+ while ((e.id & 1) != 1) {
+ e.id = edges[e.id].next_out;
+ }
+ if (e.id != -1) {
+ e.id /= 2;
+ return;
+ }
+ n = nodes[n].next;
+ }
+ e.id = -1;
+ }
+
+ void firstOut(Edge &e, const Node& v) const {
+ e.id = nodes[v.id].first_out;
+ }
+ void nextOut(Edge &e) const {
+ e.id = edges[e.id].next_out;
+ }
+
+ void firstIn(Edge &e, const Node& v) const {
+ e.id = ((nodes[v.id].first_out) ^ 1);
+ if (e.id == -2) e.id = -1;
+ }
+ void nextIn(Edge &e) const {
+ e.id = ((edges[e.id ^ 1].next_out) ^ 1);
+ if (e.id == -2) e.id = -1;
+ }
+
+ void firstInc(UEdge &e, bool& d, const Node& v) const {
+ int de = nodes[v.id].first_out;
+ e.id = de / 2;
+ d = ((de & 1) == 1);
+ }
+ void nextInc(UEdge &e, bool& d) const {
+ int de = (edges[(e.id * 2) | (d ? 1 : 0)].next_out);
+ e.id = de / 2;
+ d = ((de & 1) == 1);
+ }
+
+ static int id(Node v) { return v.id; }
+ static int id(Edge e) { return e.id; }
+ static int id(UEdge e) { return e.id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+ static UEdge uEdgeFromId(int id) { return UEdge(id);}
+
+ Node addNode() {
+ int n;
+
+ if(first_free_node==-1) {
+ n = nodes.size();
+ nodes.push_back(NodeT());
+ } else {
+ n = first_free_node;
+ first_free_node = nodes[n].next;
+ }
+
+ nodes[n].next = first_node;
+ if (first_node != -1) nodes[first_node].prev = n;
+ first_node = n;
+ nodes[n].prev = -1;
+
+ nodes[n].first_out = -1;
+
+ return Node(n);
+ }
+
+ UEdge addEdge(Node u, Node v) {
+ int n;
+
+ if (first_free_edge == -1) {
+ n = edges.size();
+ edges.push_back(EdgeT());
+ edges.push_back(EdgeT());
+ } else {
+ n = first_free_edge;
+ first_free_edge = edges[n].next_out;
+ }
+
+ edges[n].target = u.id;
+ edges[n | 1].target = v.id;
+
+ edges[n].next_out = nodes[v.id].first_out;
+ edges[n | 1].next_out = nodes[u.id].first_out;
+ if (nodes[v.id].first_out != -1) {
+ edges[nodes[v.id].first_out].prev_out = n;
+ }
+ if (nodes[u.id].first_out != -1) {
+ edges[nodes[u.id].first_out].prev_out = (n | 1);
+ }
+
+ edges[n].prev_out = edges[n | 1].prev_out = -1;
+
+ nodes[v.id].first_out = n;
+ nodes[u.id].first_out = (n | 1);
+
+ return UEdge(n / 2);
+ }
+
+ void erase(const Node& node) {
+ int n = node.id;
+
+ if(nodes[n].next != -1) {
+ nodes[nodes[n].next].prev = nodes[n].prev;
+ }
+
+ if(nodes[n].prev != -1) {
+ nodes[nodes[n].prev].next = nodes[n].next;
+ } else {
+ first_node = nodes[n].next;
+ }
+
+ nodes[n].next = first_free_node;
+ first_free_node = n;
+
+ }
+
+ void erase(const UEdge& edge) {
+ int n = edge.id * 2;
+
+ if (edges[n].next_out != -1) {
+ edges[edges[n].next_out].prev_out = edges[n].prev_out;
+ }
+
+ if (edges[n].prev_out != -1) {
+ edges[edges[n].prev_out].next_out = edges[n].next_out;
+ } else {
+ nodes[edges[n | 1].target].first_out = edges[n].next_out;
+ }
+
+ if (edges[n | 1].next_out != -1) {
+ edges[edges[n | 1].next_out].prev_out = edges[n | 1].prev_out;
+ }
+
+ if (edges[n | 1].prev_out != -1) {
+ edges[edges[n | 1].prev_out].next_out = edges[n | 1].next_out;
+ } else {
+ nodes[edges[n].target].first_out = edges[n | 1].next_out;
+ }
+
+ edges[n].next_out = first_free_edge;
+ first_free_edge = n;
+
+ }
+
+ void clear() {
+ edges.clear();
+ nodes.clear();
+ first_node = first_free_node = first_free_edge = -1;
+ }
+
+ protected:
+
+ void changeTarget(UEdge e, Node n) {
+ if(edges[2 * e.id].next_out != -1) {
+ edges[edges[2 * e.id].next_out].prev_out = edges[2 * e.id].prev_out;
+ }
+ if(edges[2 * e.id].prev_out != -1) {
+ edges[edges[2 * e.id].prev_out].next_out =
+ edges[2 * e.id].next_out;
+ } else {
+ nodes[edges[(2 * e.id) | 1].target].first_out =
+ edges[2 * e.id].next_out;
+ }
+
+ if (nodes[n.id].first_out != -1) {
+ edges[nodes[n.id].first_out].prev_out = 2 * e.id;
+ }
+ edges[(2 * e.id) | 1].target = n.id;
+ edges[2 * e.id].prev_out = -1;
+ edges[2 * e.id].next_out = nodes[n.id].first_out;
+ nodes[n.id].first_out = 2 * e.id;
+ }
+
+ void changeSource(UEdge e, Node n) {
+ if(edges[(2 * e.id) | 1].next_out != -1) {
+ edges[edges[(2 * e.id) | 1].next_out].prev_out =
+ edges[(2 * e.id) | 1].prev_out;
+ }
+ if(edges[(2 * e.id) | 1].prev_out != -1) {
+ edges[edges[(2 * e.id) | 1].prev_out].next_out =
+ edges[(2 * e.id) | 1].next_out;
+ } else {
+ nodes[edges[2 * e.id].target].first_out =
+ edges[(2 * e.id) | 1].next_out;
+ }
+
+ if (nodes[n.id].first_out != -1) {
+ edges[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);
+ }
+ edges[2 * e.id].target = n.id;
+ edges[(2 * e.id) | 1].prev_out = -1;
+ edges[(2 * e.id) | 1].next_out = nodes[n.id].first_out;
+ nodes[n.id].first_out = ((2 * e.id) | 1);
+ }
+
+ };
+
+// typedef UGraphExtender<UndirGraphExtender<ListGraphBase> >
+// ExtendedListUGraphBase;
+
+ typedef UGraphExtender<ListUGraphBase> ExtendedListUGraphBase;
+
- typedef UGraphExtender<UndirGraphExtender<ListGraphBase> >
- ExtendedListUGraphBase;
/// \addtogroup graphs
/// @{
@@ -776,6 +1119,9 @@
ListUGraph() {}
typedef ExtendedListUGraphBase Parent;
+
+ typedef Parent::OutEdgeIt IncEdgeIt;
+
/// \brief Add a new node to the graph.
///
/// \return the new node.
Modified: hugo/trunk/lemon/smart_graph.h
==============================================================================
--- hugo/trunk/lemon/smart_graph.h (original)
+++ hugo/trunk/lemon/smart_graph.h Thu Jan 11 22:06:47 2007
@@ -366,10 +366,191 @@
};
- /**************** Undirected List Graph ****************/
+ class SmartUGraphBase {
- typedef UGraphExtender<UndirGraphExtender<SmartGraphBase> >
- ExtendedSmartUGraphBase;
+ protected:
+
+ struct NodeT {
+ int first_out;
+ };
+
+ struct EdgeT {
+ int target;
+ int next_out;
+ };
+
+ std::vector<NodeT> nodes;
+ std::vector<EdgeT> edges;
+
+ int first_free_edge;
+
+ public:
+
+ typedef SmartUGraphBase Graph;
+
+ class Node {
+ friend class SmartUGraphBase;
+ protected:
+
+ int id;
+ explicit Node(int pid) { id = pid;}
+
+ public:
+ Node() {}
+ Node (Invalid) { id = -1; }
+ bool operator==(const Node& node) const {return id == node.id;}
+ bool operator!=(const Node& node) const {return id != node.id;}
+ bool operator<(const Node& node) const {return id < node.id;}
+ };
+
+ class UEdge {
+ friend class SmartUGraphBase;
+ protected:
+
+ int id;
+ explicit UEdge(int pid) { id = pid;}
+
+ public:
+ UEdge() {}
+ UEdge (Invalid) { id = -1; }
+ bool operator==(const UEdge& edge) const {return id == edge.id;}
+ bool operator!=(const UEdge& edge) const {return id != edge.id;}
+ bool operator<(const UEdge& edge) const {return id < edge.id;}
+ };
+
+ class Edge {
+ friend class SmartUGraphBase;
+ protected:
+
+ int id;
+ explicit Edge(int pid) { id = pid;}
+
+ public:
+ operator UEdge() const { return UEdge(id / 2); }
+
+ Edge() {}
+ Edge (Invalid) { id = -1; }
+ bool operator==(const Edge& edge) const {return id == edge.id;}
+ bool operator!=(const Edge& edge) const {return id != edge.id;}
+ bool operator<(const Edge& edge) const {return id < edge.id;}
+ };
+
+
+
+ SmartUGraphBase()
+ : nodes(), edges() {}
+
+
+ int maxNodeId() const { return nodes.size()-1; }
+ int maxUEdgeId() const { return edges.size() / 2 - 1; }
+ int maxEdgeId() const { return edges.size()-1; }
+
+ Node source(Edge e) const { return Node(edges[e.id ^ 1].target); }
+ Node target(Edge e) const { return Node(edges[e.id].target); }
+
+ Node source(UEdge e) const { return Node(edges[2 * e.id].target); }
+ Node target(UEdge e) const { return Node(edges[2 * e.id + 1].target); }
+
+ static bool direction(Edge e) {
+ return (e.id & 1) == 1;
+ }
+
+ static Edge direct(UEdge e, bool d) {
+ return Edge(e.id * 2 + (d ? 1 : 0));
+ }
+
+ void first(Node& node) const {
+ node.id = nodes.size() - 1;
+ }
+
+ void next(Node& node) const {
+ --node.id;
+ }
+
+ void first(Edge& edge) const {
+ edge.id = edges.size() - 1;
+ }
+
+ void next(Edge& edge) const {
+ --edge.id;
+ }
+
+ void first(UEdge& edge) const {
+ edge.id = edges.size() / 2 - 1;
+ }
+
+ void next(UEdge& edge) const {
+ --edge.id;
+ }
+
+ void firstOut(Edge &edge, const Node& v) const {
+ edge.id = nodes[v.id].first_out;
+ }
+ void nextOut(Edge &edge) const {
+ edge.id = edges[edge.id].next_out;
+ }
+
+ void firstIn(Edge &edge, const Node& v) const {
+ edge.id = ((nodes[v.id].first_out) ^ 1);
+ if (e.id == -2) e.id = -1;
+ }
+ void nextIn(Edge &edge) const {
+ edge.id = ((edges[edge.id ^ 1].next_out) ^ 1);
+ if (e.id == -2) e.id = -1;
+ }
+
+ void firstInc(UEdge &edge, bool& d, const Node& v) const {
+ int de = nodes[v.id].first_out;
+ edge.id = de / 2;
+ d = ((de & 1) == 1);
+ }
+ void nextInc(UEdge &edge, bool& d) const {
+ int de = (edges[(edge.id * 2) | (d ? 1 : 0)].next_out);
+ edge.id = de / 2;
+ d = ((de & 1) == 1);
+ }
+
+ static int id(Node v) { return v.id; }
+ static int id(Edge e) { return e.id; }
+ static int id(UEdge e) { return e.id; }
+
+ static Node nodeFromId(int id) { return Node(id);}
+ static Edge edgeFromId(int id) { return Edge(id);}
+ static UEdge uEdgeFromId(int id) { return UEdge(id);}
+
+ Node addNode() {
+ int n = nodes.size();
+ nodes.push_back(NodeT());
+ nodes[n].first_out = -1;
+
+ return Node(n);
+ }
+
+ UEdge addEdge(Node u, Node v) {
+ int n = edges.size();
+ edges.push_back(EdgeT());
+ edges.push_back(EdgeT());
+
+ edges[n].target = u.id;
+ edges[n | 1].target = v.id;
+
+ edges[n].next_out = nodes[v.id].first_out;
+ edges[n | 1].next_out = nodes[u.id].first_out;
+
+ nodes[v.id].first_out = n;
+ nodes[u.id].first_out = (n | 1);
+
+ return UEdge(n / 2);
+ }
+
+ void clear() {
+ edges.clear();
+ nodes.clear();
+ }
+
+ };
+
+ typedef UGraphExtender<SmartUGraphBase> ExtendedSmartUGraphBase;
/// \ingroup graphs
///
@@ -407,6 +588,7 @@
public:
typedef ExtendedSmartUGraphBase Parent;
+ typedef Parent::OutEdgeIt IncEdgeIt;
/// Constructor
@@ -443,22 +625,31 @@
protected:
+ void saveSnapshot(Snapshot &s)
+ {
+ s.g = this;
+ s.node_num = nodes.size();
+ s.edge_num = edges.size();
+ }
void restoreSnapshot(const Snapshot &s)
{
while(s.edge_num<edges.size()) {
- UEdge edge = uEdgeFromId(edges.size()-1);
+ int n=edges.size()-1;
+ UEdge edge=uEdgeFromId(n/2);
Parent::getNotifier(UEdge()).erase(edge);
std::vector<Edge> dir;
- dir.push_back(Parent::direct(edge, true));
- dir.push_back(Parent::direct(edge, false));
+ dir.push_back(edgeFromId(n));
+ dir.push_back(edgeFromId(n-1));
Parent::getNotifier(Edge()).erase(dir);
- nodes[edges.back().source].first_out=edges.back().next_out;
- nodes[edges.back().target].first_in=edges.back().next_in;
+ nodes[edges[n].target].first_out=edges[n].next_out;
+ nodes[edges[n-1].target].first_out=edges[n-1].next_out;
+ edges.pop_back();
edges.pop_back();
}
while(s.node_num<nodes.size()) {
- Node node = nodeFromId(nodes.size()-1);
+ int n=nodes.size()-1;
+ Node node = nodeFromId(n);
Parent::getNotifier(Node()).erase(node);
nodes.pop_back();
}
@@ -499,9 +690,8 @@
///This constructor immediately makes a snapshot of the graph.
///\param _g The graph we make a snapshot of.
- Snapshot(SmartUGraph &_g) :g(&_g) {
- node_num=g->nodes.size();
- edge_num=g->edges.size();
+ Snapshot(SmartUGraph &g) {
+ g.saveSnapshot(*this);
}
///Make a snapshot.
@@ -511,11 +701,9 @@
///This function can be called more than once. In case of a repeated
///call, the previous snapshot gets lost.
///\param _g The graph we make the snapshot of.
- void save(SmartUGraph &_g)
+ void save(SmartUGraph &g)
{
- g=&_g;
- node_num=g->nodes.size();
- edge_num=g->edges.size();
+ g.saveSnapshot(*this);
}
///Undo the changes until a snapshot.
@@ -527,7 +715,7 @@
///by restore().
void restore()
{
- g->restoreSnapshot(*this);
+ g->restoreSnapshot(*this);
}
};
};
More information about the Lemon-commits
mailing list