1 / 23

Lists and Trees in C

Lists and Trees in C. Alan L. Cox alc@cs.rice.edu. Lists, Trees, …. Not built-in However, many libraries e.g., #include <sys/queue.h> Combination of structs, unions, enums, & pointers Adapts ideas from COMP 210/212 Verbose, but straight-forward Some standard shortcuts. List Example.

candra
Download Presentation

Lists and Trees in C

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lists and Trees in C Alan L. Cox alc@cs.rice.edu

  2. Lists, Trees, … • Not built-in • However, many libraries • e.g., #include <sys/queue.h> • Combination of structs, unions, enums, & pointers • Adapts ideas from COMP 210/212 • Verbose, but straight-forward • Some standard shortcuts Lists and Trees

  3. List Example • A list of int is either • Empty or • an int and a list of int • Use a union to allow either case: union { empty ACons }; Lists and Trees

  4. Tag the Union • Differentiate between cases enum ListTag {LIST_EMPTY, LIST_CONS}; struct ListElt { enum ListTag tag; union { empty ACons } elt; }; Must name struct field! Lists and Trees

  5. Empty Case • Use void as a placeholder for the empty case • No value has type void • void represents no information other than its presense enum ListTag {LIST_EMPTY, LIST_CONS}; struct ListElt { enum ListTag tag; union { void empty; ACons } elt; }; Lists and Trees

  6. Cons Case • Use a struct to hold an int and a list of int • First member is the int • Second member is the rest of the list enum ListTag {LIST_EMPTY, LIST_CONS}; struct ListElt { enum ListTag tag; union { void empty; struct { int data; list } cons; } elt; }; Must name union field! Lists and Trees

  7. The Rest of the List • Just another element… enum ListTag {LIST_EMPTY, LIST_CONS}; struct ListElt { enum ListTag tag; union { void empty; struct { int data; struct ListElt *next; } cons; } elt; }; Problem: how big is this? struct ListElt not yet defined! Solution: pointers are all the same size Always use pointers for recursive structures Lists and Trees

  8. Simplify the Type Name enum ListTag {LIST_EMPTY, LIST_CONS}; struct ListElt { enum ListTag tag; union { void empty; struct { int data; struct ListElt *next; } cons; } elt; }; typedef struct ListElt *List; Lists and Trees

  9. List Example: Picturing Lists LIST_CONS LIST_CONS LIST_CONS LIST_EMPTY 1 2 3 Lists and Trees

  10. Reminder: Check return value for NULL List Example: Creating Lists List make_empty(void) { List list = Malloc(sizeof(struct ListElt)); list->tag = LIST_EMPTY; return (list); } List make_cons(int data, List next) { List list = Malloc(sizeof(struct ListElt)); list->tag = LIST_CONS; list->elt.cons.data = data; list->elt.cons.next = next; return (list); } list->eltis equivalent to (*list).elt Lists and Trees

  11. Always check for errors (Compiler might be able to remove checks for efficiency) List Example: Accessing Lists NULL pointer isn’t valid data of this type (Remember this!) Must check, because you can’t dereference a NULL pointer! List list; … if (list == NULL) { fprintf(stderr,“Program error: Invalid list.\n”); exit(1); } switch (list->tag) { case LIST_EMPTY: …; break; case LIST_CONS: … list->elt.cons.data … list->elt.cons.next …; break; default: fprintf(stderr,“Program error: Invalid list tag.\n”); exit(1); } Lists and Trees

  12. Pointers to Data Structures Always refer to complex data via pointers!!! struct ListElt *foo(…) { struct ListElt list; …; return (&list); } • Why? • Correctness: Avoids most common mistakes, such as… • Efficiency: Copying word-sized pointers better than copying large complex data • Familiarity: This is what Java, Scheme, etc., do implicitly typedef struct ListElt *List; Lists and Trees

  13. Simplifying • Previous steps work for any inductive data structure • But, resulting type is very verbose • Often, can simplify… Lists and Trees

  14. Eliminate void Data • Union tag is sufficient information • Remove single-case union enum ListTag {LIST_EMPTY, LIST_CONS}; struct ListElt { enum ListTag tag; union { void empty; struct { int data; struct ListElt *next; } cons; } elt; }; enum ListTag {LIST_EMPTY, LIST_CONS}; struct ListElt { enum ListTag tag; struct { int data; struct ListElt *next; } cons; }; Lists and Trees

  15. Use NULL for void Case • NULL pointer indicates “empty” case • Must always refer to elements with pointers • Eliminates need for ListTag • Collapse nested structures enum ListTag {LIST_EMPTY, LIST_CONS}; struct ListElt { enum ListTag tag; struct { int data; struct ListElt *next; } cons; }; struct ListElt { int data; struct ListElt *next; }; This is the typical C list definition Lists and Trees

  16. 1 2 3 NULL Simplified List Example Lists and Trees

  17. Creating data: List make_empty(void) { return (NULL); } List make_cons(int data, List next) { List list = Malloc(sizeof(struct ListElt)); list->data = data; list->next = next; return (list); } Accessing data: List list = …; if (list == NULL) { … } else { … list->data … list->next … } Simplified List Example:Creating & Accessing Lists and Trees

  18. Binary Tree Example 1 • Use same steps to define these binary trees: • A binary tree of int is either • an int or • a binary tree of int and another binary tree of int Lists and Trees

  19. BTREE_NODE BTREE_LEAF BTREE_LEAF 1 2 Binary Tree Example 1 enum BTreeTag {BTREE_LEAF, BTREE_NODE}; struct BTreeElt { enum BTreeTag tag; union { int leaf; struct { struct BTreeElt *left; struct BTreeElt *right; } node; } elt; }; typedef struct BTreeElt *BTree; Simplification steps aren’t relevant No void case: NULL is not a valid value Lists and Trees

  20. Binary Tree Example 2 • Use same steps to define these binary trees: • A binary tree of int is either • empty or • an int, a binary tree of int, and another binary tree of int Lists and Trees

  21. 1 NULL 2 NULL NULL Binary Tree Example 2 struct BTreeElt { int value; struct BTreeElt *left; struct BTreeElt *right; }; typedef struct BTreeElt *BTree; Simplifications steps are relevant NULL represents empty tree Lists and Trees

  22. Mono- & Polymorphism • C has a monomorphic type system • Our List & BTree definitions only allowed ints • Need separate definitions for types of same structure, but containing different types of elements • There are ways around this, using … • Macros, e.g., #include <sys/queue.h> • void * • Reduces the effectiveness of type-checking • Most modern languages have some form of polymorphism struct ListElt { void *data; struct ListElt *next; }; Lists and Trees

  23. Next Time • Brief Tour of x86-64 Assembly Language Lists and Trees

More Related