Thread: List

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #7
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    A better approach using sentinel nodes (less special conditions):
    Code:
    // Sedgewick method.
    
    #include <stdio.h>
    
    // A "base" node.
    struct node { struct node *next; };
    
    // A list (with sentinel nodes).
    struct list { struct node head, tail; };
    
    // list initializer
    #define LIST_INIT(list__) (struct list){ .head.next = &(list__).tail, .tail.next = &(list__).tail }
    
    _Bool slist_empty( struct list *list )
    { return list->head.next == &list->tail; }
    
    // WARNING: 'node' never can be the tail sentinel node!
    // it can be any other node (including sentinel 'head').
    void slist_insertAfter( struct node *node, struct node *new )
    {
      new->next = node->next;
      node->next = new;
    }
    
    // ANY node, including both sentinels, can be used as 'node'.
    // return NULL if list is empty or the "deleted" node ptr.
    struct node *slist_deleteAfter( struct node *node )
    {
      struct node *next;
    
      next = node->next;
      if ( next == next->next )
        return NULL;
    
      node->next = next->next;
    
      return next;
    }
    
    void slist_clear( struct list *list, void (*dtor)( void * ) )
    {
      while ( 1 )
      {
        struct node *node;
    
        node = slist_deleteAfter( &list->head );
        if ( ! node )
          break;
    
        if ( dtor )
          dtor( node );
      }
    }
    
    // macro for simple list iteration.
    #define for_each(iter__,listptr__) \
      for ( (iter__) = (listptr__)->head.next; (iter__) != (iter__)->next; (iter__) = (iter__)->next )
    
    // macro for list iteration where we can change the list.
    // using an auxiliar 'iterator'.
    #define for_each_safe(iter__,tmp__,listptr__) \
      for ( (iter__) = (listptr__)->head.next, (tmp__) = (iter__)->next; \
            (iter__) != (iter__)->next; \
            (iter__) = (tmp__) )
    
    //--- test ---
    int main( void )
    {
      struct list list = LIST_INIT(list);
      struct node *p;
    
       // Our internal nodes are polymorphic this way.
      struct mynode {
        struct node *next;  // MUST BE the first member.
    
        int value;
      };
    
      static struct mynode node[] = { { .value = 0 }, { .value = 1 }, { .value = 2 } };
    
      // Of course we could do:
      //
      //    struct mynode *q, *r;
      //    q = malloc( siseof *q ); q->value = 2; slist_insertAfter( &list.head, (struct node *)q );
      //    r = malloc( siseof *r ); r->value = 1; slist_insertAfter( (struct node *)q, (struct node *)r ); q = r;
      //    r = malloc( siseof *r ); r->value = 0; slist_insertAfter( (struct node *)q, (struct node *)r );
      //
      // Notice that memory allocation have nothing to do with the list internals.
    
      slist_insertAfter( &list.head, (struct node *)&node[2] );
      slist_insertAfter( (struct node *)&node[2], (struct node *)&node[1] );
      slist_insertAfter( (struct node *)&node[1], (struct node *)&node[0] );
    
      for_each( p, &list )
      {
        struct mynode *q = (struct mynode *)p;
    
        printf( "%d ", q->value );
      }
      
      putchar( '\n' );
    
      // if we had allocated the nodes we could do
      //    slist_clear( &list, free );
      slist_clear( &list, NULL );
    }
    Last edited by flp1969; 01-14-2023 at 04:40 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 03-17-2022, 11:37 AM
  2. Adding element before current node
    By sigur47 in forum C Programming
    Replies: 4
    Last Post: 12-05-2011, 01:50 AM
  3. Quadtree Node -> pointers to the children node
    By yahn in forum C++ Programming
    Replies: 2
    Last Post: 04-13-2009, 06:38 PM
  4. Replies: 0
    Last Post: 09-16-2008, 05:04 AM
  5. Replies: 5
    Last Post: 10-04-2001, 03:42 PM

Tags for this Thread