How many lines of code do I need, to set up a typical tree structure? What are the pros and cons between a C-style generic tree and an std::map or an std::set ?
We often create a tree of temporary elements, just to see if a particular element has been visited once.
The following piece of code is a typical one in C, where you have a number of shapes, whose edges you wish to store in a tree.
The edge is comprised of two nodes of a shape:
Typically, a generic C-based tree requires copy, free, and compare functions.
All this code, simply to set up a tree of edges.
Reflecting on the code above, we know that
This does the same job, plus it has some advantages:
Compare the C tree layout to the std::set layout:
We often create a tree of temporary elements, just to see if a particular element has been visited once.
The following piece of code is a typical one in C, where you have a number of shapes, whose edges you wish to store in a tree.
The edge is comprised of two nodes of a shape:
struct MyEdgeNodes { Node *n1; Node *n2; };
Typically, a generic C-based tree requires copy, free, and compare functions.
/* the tree */ Tree *edges_tree = NewTree(compareMyEdgeNodes, copyMyEdgeNodes, freeMyEdgeNodes); /* support functions */ void *copyMyEdgeNodes(void *edge) { MyEdgeNodes *tmp_edge_nodes = (MyEdgeNodes *)edge; MyEdgeNodes *new_edge_nodes; new_edge_nodes = malloc(sizeof(struct MyEdgeNodes)); new_edge_nodes->n1 = tmp_edge_nodes->n1; new_edge_nodes->n2 = tmp_edge_nodes->n2; return new_edge_nodes; } int compareMyEdgeNodes(void *edge1, void *edge2) { MyEdgeNodes *edge_nodes1 = (MyEdgeNodes *)edge1; MyEdgeNodes *edge_nodes2 = (MyEdgeNodes *)edge2; if( edge_nodes1->n1 > edge_nodes2->n1 ) return 1; else if( edge_nodes1->n1 < edge_nodes2->n1 ) return -1; else { if( edge_nodes1->n2 > edge_nodes2->n2 ) return 1; else if( edge_nodes1->n2 < edge_nodes2->n2 ) return -1; else return 0; } } void freeMyEdgeNodes(void *edge) { free(edge); }
All this code, simply to set up a tree of edges.
Reflecting on the code above, we know that
- C++ provides implicit copy constructors, so we shouldn't need the copyMyEdgeNodes()
- we know that there is nothing in the struct to be deleted, so there's no need for freeMyEdgeNodes()
- the struct is merely a pair of members, and std::pair already provides an operator<
typedef pair<Node *, Node*> MyEdgeNodes; set< MyEdgeNodes > edges_tree;
This does the same job, plus it has some advantages:
- it requires less calls to malloc and free.
Compare the C tree layout to the std::set layout:
memory layout of a generic tree in C |
memory layout of an std::set |
No comments:
Post a Comment