CSC195, Class 37: Linked Lists (1) Overview: * Review: Perspectives on Lists * What are the basic Scheme-list operations? * Implementing nodes as records * Implementing key list operations Notes: * I've rearranged the schedule so that we can meet at Saints' Rest on Friday. In particular, we'll study Gries on Friday. * How did folks feel about last Friday's class? * Assignment: Think about the other kind of lists (those more like those provided by Java). What procedures should they include? What is a list? * Scheme perspective: Either (1) null or (2) cons of a value and a list. * Java perspective: An easily extensible and iterable collection. + Vectors are indexed collections. + Sets are collections that are neither indexed nor iterable but which support quick "add" and "member?" oeprations. We'll start with the Scheme perspective. Side note: Another dimension of thinking of lists: Homogeneous, Heterogeneous, or Higher-Order * Heterogeneous: May contain different types of values * Homogeneous: Contains only one type of value * Higher-Order: Can build new homogeneous list types Assuming we're using the Scheme perspective, modified for only lists of integers. What operations do you expect to have the class provide? * Create an empty list ilist inull() * Add elements to lists: ilist icons(int i, ilist il) * Get the first element of a list int icar(ilist il) * Get all but the first element of a list ilist icdr(ilist il) * Is the list empty? int nullP(ilist il) Design question: Should we be able to remove elements from the list, or should remove build a new list? * The latter Scheme review: Lists are built from *pairs* Detour: Pointers, structs, and pointers to structs struct node { int val; struct node *next; } node; ... node *tmp; ... /* I want the val component of the thing tmp points to. */ (*tmp).val; /* First syntax. */ tmp->val; /* Alternate syntax. */ WHAT SHOULD WE DO DIFFERENT FOR HETEROGENEOUS LISTS? Make val a pointer rather than an int. Pass pointers (and expect pointers in return) from everything else. ---------------------------------------- Suppose we wanted to provide a richer array of procedures for lists. What are some you'd like? * ndr dr (non-destructive-reverse and destructive-reverse) [Build a new list] vs. destructive * ndd dd (non-destructive-delete and destructive-delete) [Build a new list] vs. destructive * print * length * dmap * free int length(list l) { /* while the current node is not null incremenet count */ int count=0; while (!isEmpty(l)) { ++count; l = cdr(l); } return count; } /* length(list) */ When might this procedure fail? * Give it a circular list: Loop forever. * Give it a too-long list, count can overflow. * Erik might pass in an uninitialized list. We could define the list structure differently typedef struct { int len; node *contents; } *list;