tags:

views:

109

answers:

2
A: 

Two choices:

1) Use a high level library that solves the problem. Boost MultiIndex containers allow shared nodes with multiple ordered/mapped organizations.

2) Instead of two (sorted by rating and name) singly linked lists, use two doubly linked lists. Then deletion of a given node is O(1). To find a node quickly by name, you could use an efficient map (hash table or balanced tree). If you don't mind scanning through one list to find the node, then that list doesn't need to be doubly linked.

As for deletion for linked lists, you're right to suspect that your code can be simplified immensely. Either:

1) use a sentinel (dummy) node for the empty list; that way the "previous node" always exists for actual list items

2) instead of "pointer to previous node" in singly linked list deletion, store "pointer to "next pointer to this node"".

Here's what I mean by 2):

node **pn=&headByRating; // we will update headByRating=n via (*pn)=n if needed
node *c=*pn;  // we will have c == *pn except momentarily
while ( c && strcmp(name, c->item.getName()) {
    pn=&c->nextByRating; // c is now the previous node
    c=*pn; // c is *pn again
}
// now (*pn) points to the node we want to delete, i.e. c
*pn=c->next; // (*pn) skips right over c now.
// delete c; // or else you leak memory; you didn't specify how nodes are allocated
return true;

This should be equivalent to your:

while ( NULL != currByRating && 
      ( strcmp( name, currByRating->item.getName() ) != 0 ) )
{
    prev_node = currByRating;
    currByRating = currByRating->nextByRating;
    prev_node->nextByRating  = currByRating;
}
    if ( currByRating == headByRating ) // was it the head?
    {
     currByRating = currByRating->nextByRating;
     headByRating = currByRating;
     return true;
    }
    else if ( currByRating->nextByRating == NULL ) // could it be the tail?
    {
     currByRating = prev_node;
     currByRating->nextByRating = NULL;
     return true;
    }
    else
    {
     currByRating = prev_node;
     currByRating->nextByRating = currByRating->nextByRating->nextByRating;
     return true;
    }
wrang-wrang
OH! Sorry I need to tag this as homework.
!!R u serious that is equivalent?
If it's homework (can't use Boost), then if you want it to be fast (skipping the second traversal), you need to use a doubly linked list for the second of the two orders. You could also consider using a std::map or hash lookup to find the node by name instead of searching through a list. My suggestion to simplify singly-linked list deletion won't make anything faster; it will just save code.
wrang-wrang
I've allocated nodes through an insertion sort "insort" function: node *current_node = new object( object_t ); where the object_t is being passed in for every node. I allocate each node with current_node.
Yes, it's equivalent (in what it does). You shouldn't have to treat the "tail is NULL" case any differently. And by using "node **pn" you don't have to treat "deleted node is head of list" differently.
wrang-wrang
Since you allocated all the nodes with new, make sure you delete them after the last use (uncomment my "delete c").
wrang-wrang
ok. I thought doing that in the list dtor was the same thing
A: