CSE 326: Data Structures
Part Two: Lists
Henry Kautz
Autumn Quarter 2002
Today
• Abstract versus Concrete Data Types• List ADT• Iterators• Comparing implementations• Sparse vectors• Nested lists
– Sparse arrays
– Expressions
Abstract vs. Concrete Data Types• Abstract Data Type (ADT)
– Mathematical description of an object and the set of operations on the object
• List, Stack, Tree, Heap, Graph, …
– One ADT may specialize another ADT– One ADT may implement another ADT
• Concrete Data Type– Implementation of an ADT using some set of primitive
data types and operations of known complexity• Primitives: integers, arrays, pointers or references
– Object-oriented programming languages (Java, C++) let you explicitly define new concrete data types that correspond to ADT’s.
List ADT
• Mathematical description: a sequence of items– Ai precedes Ai+1 for 1 i < n
• Operations– First() = position
– Value(position) = item
– Next(position) = position
– Length() = integer
– Insert(item,position)
– Delete(position)
( A1 A2 … An-1 An )length = n
What other operations might be useful?
List ADT
• Mathematical description: a sequence of items– Ai precedes Ai+1 for 1 i < n
• Operations– First() = position
– Value(position) = item
– Next(position) = position
– Length() = integer
– Insert(item,position)
– Delete(position)
( A1 A2 … An-1 An )length = n
What other operations might be useful?
Kth(integer)=item
SetKth(item,integer)
Find(item)=position
Specialization Hierarchy
ListProperty: Sequence
First()=pos Value(pos)=item Kth(integer)=itemNext(pos)=pos Length()=integer SetKth(item,integer)Insert(item,pos) Delete(pos) Find(item)=position
StackProperty: LIFO
Push(item)Pop()=itemIsEmpty()=true/false
QueueProperty: FIFO
Enqueue(item)Dequeue()=itemIsEmpty()=true/false
VectorProperty: random access
Kth(int) = itemSetKth(item,integer)
Implementation HierarchyListComplexity: Unspecified
First()=pos Value(pos)=item Kth(integer)=itemNext(pos)=pos Length()=integer SetKth(item,integer)Insert(item,pos) Delete(pos) Find(item)=position
Linked List(1) for:
(n) for:
Array(1) for:
(n) for:
Specialization and Implementation Hierarchies
List
Stack Queue Vector
Linked List
Sorted Vector
Concrete Data Types
List
Linked List
Linked List using References
What’s an alternative implementation?
nodeB.value = “b”;nodeC.value = “c”;list = nodeB;nodeB.next = nodeC
b c
Concrete Data Types
List
Linked List
Linked List using References
nodeB.value = “b”;nodeC.value = “c”;list = nodeB;nodeB.next = nodeC
b c
Linked List using Arrays
“c” “b”
0 2
list = 4;
1 2 3 4 5
Linked Lists in C
struct node{Object element;struct node * next; }
Everything else is a pointer to a node!
typedef stuct node * List;
typedef struct node * Position;
a b c L
Linked Lists in Java – version 1
• References to objects are implicit pointers
class ListNode{Object element;ListNode next; }
class List{Listnode head;Listnode find(Object item) {
Listnode n = head;while (n != null) {
if (n.element == item)return n; }
return null; }
Data Hiding• Good programming style hides internal details of an object
from the rest of the program– Guarantees that data structure always works as expected – cannot
easily be corrupted
• Here, must make details of ListNode and List public – Type returned by find
– For iterating through a list:
ListNode n;
for (n = mylist.head; n!= null; n = n.next){
v = n.element;
do something on each v
}
Iterators• Introduce a new public class to explicitly represent a position in a list
public class LinkedListItr {ListNode current;public Object retrieve() {
return current.element; }public void advance() {
current = current.next; }
• Then: LinkedListItr i; for (i = mylist.first(); !i.pastEnd(); i.advance){
do something on each v.retrieve() }
Abstract Iterators• Iterators can also be defined for an array
implementation of lists:
public class ArrayListItr {Object [] data;
integer current;
public Object retrieve() {
return data[current]; }
public void advance() {
current = current+1; }
• We can create an abstract iterator that works for both linked list and array implements of List
Abstract Iterator
abstract class ListItr {
abstract Object retrieve();
abstract void advance();
… }
class LinkedListItr extends ListItr { … }
class ArrayListItr extends ListItr { … }
• Why do this?
Array Implementation of Linked Lists
How do we implement
Delete(position) ?
Insert(element, position)?
F O A R N R T
3 8 6 4 -1 10 5
Data
Next
1 7 92 3 4 5 6 8 10
First = 2
Free Cell Management
When an item is removed from the list, must “reclaim” the unused cell for later use
Can use same array to manage a second list of unused cells
F O A R N R T
7 9 03 8 6 4 -1 10 5
Data
Next
1 7 92 3 4 5 6 8 10
First = 2 Free = 1
Memory Management
• Keeping a free cell list is an example of a memory management strategy
• How is memory managed in C?
• C++?
• Java?
Summary: ComplexityLinked list Array Sorted
array
Kth(int)
Find(e)
Insert(e,pos)
Next(pos)
InsertAnywhere(e)
To ADT or NOT to ADT?
• Issue: when to bypass / expand List ADT?
• Using general list (stack) operations: List reverse(List x) {
y = new List;
while (! x.isEmpty())
y.Push( x.Pop() )
return y; }
Disadvantages?
Destructive Method
Reverse() { ListNode x, last, tmp;x = head;
last = null;while (x.next != null){
tmp = x.next; x.next = last; last = x; x = tmp;}
head = x; }
a b c x
a b c x
Faster in practice?
Asymptotically faster?
Slow Reverse
List reverse(List x) {y = new List;
for (i=1; i<=x.length(); i++){
y.Push( x.Kth(i) )
}
return y; }
Polynomial ADT
Possible linked list implementation:
Ai is the coefficient of the xi-1 term:
5 + 2x + 3x2 ( 5 2 3 )7 + 8x ( 7 8 )3 + x2 ( 3 0 2 )
Problem?
List ADT
4 + 3x2001
( 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 )
Sparse Vector Data Structure:4 + 3x2001
40
32001
(<4 0> <2001 3>)
class Term { int coeff, power; }
class PolyNode extends ListNode {Term data; }
class Polynomial extends List {Polynode header;… }
Addition of Two Polynomials?
Complexity?
1050
31200
15+10x50+3x1200
150
p
3050
4100
5+30x50+4x100
50
q
Addition of Two Polynomials• One pass down each list: (n+m)
1050
31200
15+10x50+3x1200
150
p
3050
4100
5+30x50+4x100
50
q
4100
31200
4050
200
r
Sparse Matrices
• How could we represent this compactly?
18 0 33 0 0 00 0 0 0 0 00 0 0 0 0 00 0 0 99 0 00 0 0 0 0 00 0 0 0 0 27
Sparse Matrices
• How could we represent this compactly?( (row (column data) (column data) …) (row ( (column data) (column data) …) … )( (1 (1 18) (2 33)
(4 (4 99))(5 (5 27)) )
18 0 33 0 0 00 0 0 0 0 00 0 0 0 0 00 0 0 99 0 00 0 0 0 0 00 0 0 0 0 27
Nested Polymorphic Lists
• Polymorphic – elements in list may be of different types– Trivial in Java, doable but painful in C++
• Nested – elements of a list is are lists• Nested polymorphic list – elements of list may be
of non-list types (e.g. int) or lists
“Universal” Data Structure
• NPL’s can be used to implement any of the other linked data structures we’ll cover in the course– Trees, heaps, graphs, disjoint sets
• LISP – programming language that uses NPL’s to represent both data and programs– LISP pioneered (in the 1950’s!) many ideas that are the
basis of modern programming languages• Recursion, garbage collection, interactive programming
environments
• JAVA combines the best features of LISP with the best features of C++ (strict type checking, objects and inheritance)
Programs As Lists
(progn
(setq x 10)
(setq y 1)
(while (greater-than x 1)
(progn
(setq y (times y x))
(setq x (minus x 1)))))
-Lisp
• Let’s see how easy it is to build our own programming language interpreter…
(plus (times (minus 6 2) 14) 8)
• Grammar for an expression:expression :: = integer
| “(“ symbol {expression}* “)”
symbol ::= [a-z]+
repeat 0 or more times
repeat 1 or more times
Lists• For these slides: convention that head field of list
points directly to first node of list (no dummy node)
class Node {
Object element;
Node next; }
class List {
Node head;
… }
Read/Eval/Print Loop
• The top level program:
While (not EOF)
Print( Eval( ReadExpression()))
Reading ExpressionsReadExpression() {
t = GetToken();
if (t is numeric)
return new Integer(t);
if (t is “(“))
return ReadList();
if (t is “)”) return null;
else return new Symbol(t);
}
see Weiss for
tokenizer
ReadList
ReadList() {
e = ReadExpression();
if (e == null)
return a new empty List;
else return
Push( e, ReadList() );
}
Why is the recursive call inside the Push?
Evaluating Expressions
Eval( e ){if (e is an Integer)
return its value;if (e is a List)
f = e.head.element;return Apply(f,
EvalList(e.head.next));else error;
}
EvalList
EvalList(Node n){
if (n == null)
return a new empty list;
else return
Push( Eval(n.element),
EvalList(n.next) );
}
Apply
Apply(f, params){
if (f is “plus”)
return sum of params
else if (f is “minus”)
return difference of params
else …
}params is always a list
of ints – it has been fully evaluated!
That’s It!
• 33 lines of pseudo-code• About 100 lines of Java
• What about variables? If statements? Loops?
Adding Variables
• Keep an symbol table list of variable/value pairs
( (a 15) (b 22) (c –2) )• Add to Eval:
– to evaluate a variable, find it in the symbol table and return it’s value – if it is not the table, error.
– to set a variable, check for the special form
(set symbol expression)
Eval with VariablesEval( e ){
if (e is an Integer)
return its value;
if (e is a List)
f = e.head.element;
if (f is “set”){
var = e.head.next.element;
val = e.head.next.next.element;
Put (var,val) in symbol table; }
else return Apply(f,
EvalList(e.head.next))
else return e’s value in symbol table;
}
Control Flow
• Sequence(prog exp1 exp2 …)
– In Apply, return value of last parameter
• Conditionals(if exp1 exp2 exp3)
– In Eval, if exp1 is not 0, evaluate exp2, otherwise exp3
• Loops(loop exp1 exp2)
– In Eval, if exp1 is not 0, evaluate exp2, then repeat
Coming Up
• Sorting– Weiss Chapter 7
• Know how the following work:– Bubble Sort (selection sort)
– Merge Sort
– Quicksort