I still think it's much easier to think of this as TWO data structures. Actually it's 4:
- A single point in a list.
- A list of points.
- A single Field in the list
- A list of Fields.
If you think of it like this then you'll have nearly identical methods for manipulating the two lists. As you find bugs in one, you can fix the other, almost in your sleep.
Dealing with linked lists is much MUCH easier if your find() doesn't return a pointer to a node, but rather returns a pointer
to the link that points to the node. In other words, it returns a pointer to head, or a pointer to the previous node's next pointer. If you do this, then adding and deleting become almost trivial because you never have to worry about a special case for adding or deleting at the head of the list
In C++, it's better to return a reference to the link rather than a pointer. So suppose you have
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
class PointID {
public:
PointID(int _id) : id(_id) {}
int id;
PointID *next; // owned by this
};
class PointList {
public:
// Find the PointID node with the give ID and return a reference
// to the pointer to the node (i.e. a ref to head or a PointID::next
// pointer. If the node isn't found then return a ref to the last
// link in the list (again, head or a a PointID::next)
PointID * &findNode(int id);
...
|
The findNode is :
1 2 3 4 5 6 7 8 9 10 11
|
PointID * &PointList::findNode(int id)
{
PointID **headOrNext;
PointID *p;
for (headOrNext = &head; p = *headOrNext; headOrNext = &p->next) {
if (p->id == id) {
break;
}
}
return *headOrNext;
}
|
Now deleting becomes really east:
1 2 3 4 5 6 7 8 9 10 11
|
bool PointList::del(int id)
{
PointID* &link = findNode(id);
if (link) {
PointID *node = link;
link = link->next; // unlink node from the list
delete node;
return true;
}
return false;
}
|