Mar 30, 2015
Recap The extensible array-based
implementation of linear list: may be too slow
insert or delete operations involve data movement
may be too space waste only a small portion of the allocated space is
occupied with data
General computer science idea “pay as you go”
Polymorphic Abstract Data Types in C// recall the poly ADT:
#ifndef LIST_H
#define LIST_H
typedef void *poly;
typedef struct listStruct *list;
list newList ();
int length (list l);
poly nth (list l, int n);
void insert (list l, poly x, int i);
poly delete (list l, int i);
void foreach (list l, void (*f)(poly));
#endif
Implementation Using Linked List
Linked list is a self-reference structure:
to simplify operations, we add a unique head node “head”
“head” does not belong to the list may hold meta information of the list
head…
Linked List-based Implementation// Turn the above figure into C, we have:// in file “linkedList.c”#include <stdlib.h>#include “list.h”struct listStruct{ poly data; list next;};
data
next
data
next
data
next
head …
Operation: “newList”// “new” returns an empty list, which consists of// a single head node.list newList (){ list l = (list)malloc (sizeof (*l)); l->data = NULL; // Why this? l->next = NULL; return l;}
/\
/\
l
Operation: “length”int length (list l){ list p = l->next; int n = 0; while (p) { p = p->next; n++; } return n;}
data
next
data
next
data
next
l …p
n==0
Operation: “length”int length (list l){ list p = l->next; int n = 0; while (p) { p = p->next; n++; } return n;}
data
next
data
next
data
next
l …p
n==1
Operation: “length”int length (list l){ list p = l->next; int n = 0; while (p) { p = p->next; n++; } return n;}
data
next
data
next
data
next
l …p
n==2
Operation: “length”int length (list l){ list p = l->next; int n = 0; while (p) { p = p->next; n++; } return n;}
data
next
data
next
data
next
l …p
n==3
Operation: “nth”poly nth (list l, int n){ list p = l->next; int i = 0; if (n<0 || n>=length(l)) error (“invalid index”);
while (i!=n) { p = p->next; i++; } return p;}
Operation: “nth”
data
next
data
next
data
next
l …
n==2
p
i==0
data
next
data
next
data
next
l …
n==2
p
i==1
data
next
data
next
data
next
l …
n==2
p
i==2
Operation: “insert”void insert (list l, poly x, int n){ // 1. change the “next” field of pointer t; // 2. change the “next” field of element (n-1) …;}
data
next
data
next
data
next
l …
n==2
x
nextt
we’d search pointer p
Operation: “insert”void insert (list l, poly x, int n){ list p; if (n<0 || n>length(l)) error (“invalid index”);
// search pointer p points to position n-1 p = n? (nth (l, n-1)) : l;
Operation: “insert” // continued…
// Step #1: cook list node:list temp = (list)malloc (sizeof (*temp));
temp->data = x; // Step #2: temp points to n-th data item temp->next = p->next; // Step #3: link temp onto list p->next = temp; return;}
Operation: “delete”poly delete (list l, int n){ // The key step is to search pointer p // Leave this as exercise.
// See Lab #3. …;}
data
next
data
next
data
next
l …
n==2we’d search pointer p
Operation: “foreach”void foreach (list l, void (*f)(poly)){ list p = l->next; while (p) { f (p->data); p = p->next; }}
data
next
data
next
data
next
l …
Linked List Summary Linked list:
better space usage---no waste good time complexity
insert or delete take linear time but have to search the data sequential, :-(
Can be further generalized: circular linked list doubly linked list doubly circular linked list
Circular Linked List All the pointers forms a circle
Note that the first node has two fields head: points to the head of the list tail: points to the tail of the list
head
tail
data
next
data
next
data
next
l
Circular Linked List---Implementation// in file “clist.c”
struct listStruct
{
struct node *head;
struct node *tail;
};
struct node
{
poly data;
struct node *next;
}
head
tail
data
next
data
next
data
next
l
Linear List Application #1: Polynomials Polynomials:
where ciR and n Nat uniquely determined by a linear list:
For this representation, all the list operations apply
Linear List Application: Polynomials Space waste:
Consider this:
20001 items with 3 non-zeros A refined representation:
ci<>0 for 0<=i<=m Ex:
Polynomial ADT: Interface Abstract data type: polyn
represent the polynomial data type operations:polyn newPolyn (); // an empty polynpolyn add (polyn p1, polyn p2);real value (polyn p, real x0); // p(x0)polyn mult (polyn p1, polyn p2);// add an item c*x^n, which does not appear in pvoid insert (polyn p, real c, int n);
Polynomial ADT in C: Interface// in file “polyn.h”#ifndef POLYN_H#define POLYN_H
typedef struct polynStruct *polyn;
polyn newPolyn (); polyn add (polyn p1, polyn p2);real value (polyn p, real x0); polyn mult (polyn p1, polyn p2);void insert (polyn p, real c, int n);
#endif
Polynomial ADT in C: Implementation// in file “polyn.c”#include “linkedList.h”#include “polyn.h”
struct polynStruct{ linkedList coefExps;};// where “coefExps” is a list of tuples: (c, n)// one way to read “list coefExps” is:// list<tuple<double, nat>> coefExps// However, C does not support this style of// declaration… :-(
Operation: “newPolyn”polyn newPolyn ()
{
polyn p = (polyn)malloc (sizeof (*p));
// use a linked list internally
p->coefExps = newLinkedList ();
return p;
}
Operation: “insert”void insert (polyn p, real c, nat n)
{
// could we use “double” and “int”, instead of
// “real” and “nat”?
tuple t = newTuple (c, n);
linkedListInsertAtTail (p->coefExps, t);
return;
}
// Leave other functions as exercises.
Change to the Head#include <stdlib.h>
#include “linkedList.h”
#include “tuple.h”
#include “polyn.h”
struct polyn
{
linkedList coefExps;
};
Linear List Application#2: Dictionary
Dictionay:
where ki are keys and vi are value all ki are comparable and distinct How can dict’ be represented in compu
ters? many ideas (we’d discuss some in future) for now, we make use of a linear list
Dictionary ADT: Interface
Abstract data type: dict represent the dictionary data type
operations:dict newDict (); // an empty dict
void insert (dict d, poly key, poly value);
poly lookup (dict d, poly key);
poly delete (dict d, poly key);
“dict” ADT in C: Interface// in file “dict.h”#ifndef DICT_H#define DICT_H
typedef struct dictStruct *dict;
dict newDict (); void insert (dict d, poly key, poly value);poly lookup (dict d, poly key);poly delete (dict d, poly key);
#endif
“dict” ADT in C: Implementation// in file “dict.c”
#include “linkedList.h”
#include “dict.h”
struct dictStruct
{
linkedList l;
};
Operations: “new”dict newDict ()
{
dict d = (dict)malloc (sizeof (*d));
d->l = newLinkedList ();
return d;
}
Operations: “insert”void insert (dict d, poly key, poly value)
{
tuple t = newTuple (key, value);
linkedListInsertAtHead (d->l, t);
return;
}
// Leave other functions as programming
// exercises.