320 likes | 328 Views
CSE 326: Data Structures Lists. Lecture 4: Monday, Jan 13, 2003. Today. Finish amortized analysis of stretchy arrays The List ADT Reading assignment for this week: Weiss, Chapter 3. E D C B A. A. F. B C D E F. Amortized Analysis. Stack Stack operations push pop is_empty
E N D
CSE 326: Data Structures Lists Lecture 4: Monday, Jan 13, 2003
Today • Finish amortized analysis of stretchy arrays • The List ADT Reading assignment for this week:Weiss, Chapter 3
E D C B A A F B C D E F Amortized Analysis Stack • Stack operations • push • pop • is_empty • Stack property: if x is on the stack before y is pushed, then x will be popped after y is popped • What is biggest problem with an array implementation?
int[] data; int maxsize; int top; Push(e){ if (top == maxsize){ temp = new int[2*maxsize]; for (i=0;i<maxsize;i++) temp[i]=data[i]; data = temp; maxsize = 2*maxsize; } data[++top] = e; } int pop() { return data[--top]; } Stretchy Stack Implementation Best case Push = O( ) Worst case Push = O( )
Stretchy Stack Amortized Analysis • Consider sequence of npush/pop operations • Amortized time = (T1 + T2 + . . . + Tn) / n • We compute this next push(e1) push(e2) pop() push(e3) push(e4) pop() . . . push(ek) time = T1 n time = Tn
Stretchy Stack Amortized Analysis • The length of the array increases like this: 1, 2, 4, 8, . . . , 2k, . . ., n • For each Ti we have one of the following • Ti = O(1) for pop(), and for some push(ei) • Ti = O(2k) for some push(ei) • Hence
Stretchy Stack Amortized Analysis Let’s compute this sum: And therefore: In an asymptotic sense, there is no overhead in using stretchy arraysrather than regular arrays!
Stretchy Stack Amortized Analysis • Careful ! We must be clever to get good amortized performance ! • Consider “smart pop”: int pop(){ int e = data[--top]; if (top <= maxsize/2){ maxsize = maxsize/2; temp = new int[maxsize]; for (i=0;i<maxsize;i++) temp[i]=data[i]; data = temp;} return e; }
Stretchy Stack Amortized Analysis • Take the sequence of 3n push/pop operations: push(e1) push(e2) ... push(en) pop() push(en) pop() push(en) pop() ... push(en) pop() n Suppose n = 2k+1 Hence amortized time is: T = ((1) + . . . + (1) + (n) + . . .+ (n))/3n = (n (1) + 2n (n))/3n = 2/3 (n) Hence T = (n) !!! 2n
Stretchy Stack Amortized Analysis • A more clever pop: int pop(){ int e = data[--top]; if (top <= maxsize/3){ maxsize = maxsize/2; temp = new int[maxsize]; for (i=0;i<top;i++) temp[i]=data[i]; data = temp;} return e; }
Stretchy Stack Amortized Analysis Some op’s take time=1, some take time > 1.Let’s look at consecutive op’s with time > 1. Four cases: Case 1 op1 op2 . . . opi push() . . . opj . . . push( ) opk . . . op1 op2 . . . opi pop() . . . opj . . . push( ) opk . . . Case 2 time > 1 time > 1 time = 1 at least k/2 push’s (why ?) time = 1 at least k/6 push’s (why ?) time = k > 1 time = k > 1
Stretchy Stack Amortized Analysis Some op’s take time=1, some take time > 1.Let’s look at consecutive op’s with time > 1. Four cases: Case 4 op1 op2 . . . opi push() . . . opj . . . pop( ) opm . . . Case 3 op1 op2 . . . opi pop() . . . opj . . . pop( ) opm . . . time > 1 time > 1 time = 1 at least k/2 pop’s (why ?) time = 1 at least k pop’s (why ?) time = k > 1 time = k > 1
Stretchy Stack Amortized Analysis Now compute the average time: n op1 op2 . . . opi . . . . . . opj . . . . . . opm . . . . . . opn time = 1 at least k1/6 time = 1 time = 1 time = k1 > 1 Total time: T 6nAmortized time:T/n = O(1) time = 1 at least k2/6 time = 1 time = 1 time = k2 > 1 at least k3/6 time = 1 time = 1 time = 1 time = k3 > 1 time = 1 . . . . . . time = 1 . . . . . .
Lists • We will describe them as ADTs = Abstract Data Types
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 ( A1 A2 … An-1 An ) length = n • 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) 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 Hierarchy ListComplexity: 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 Sorted Vector Linked List
Concrete Data Types List b c Linked List What’s an alternative implementation? Linked List using References nodeB.value = “b”;nodeC.value = “c”;list = nodeB;nodeB.next = nodeC
Concrete Data Types List b c Linked List Linked List using References Linked List using Arrays list = 4; nodeB.value = “b”;nodeC.value = “c”;list = nodeB;nodeB.next = nodeC
Linked Lists in C a b c struct node{ Object element; struct node * next; } Everything else is a pointer to a node! typedef stuct node * List; typedef struct node * Position; 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 • Then: public class LinkedListItr {ListNode current; public Object retrieve() { return current.element; } public void advance() { current = current.next; } public boolean pastEnd() { return current == NULL; } 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: • We can create an abstract iterator that works for both linked list and array implements of List public class ArrayListItr { Object [] data; integer current; public Object retrieve() { return data[current]; } public void advance() { current = current+1; }
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 1 7 9 2 3 4 5 6 8 10 Data F O A R N R T Next 3 8 6 4 -1 10 5 First = 2 • How do we implement • Delete(position) ? • Insert(element, position)?
Free Cell Management 1 7 9 2 3 4 5 6 8 10 Data F O A R N R T Next 7 9 0 3 8 6 4 -1 10 5 First = 2 Free = 1 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
Memory Management • Keeping a free cell list is an example of a memory management strategy • How is memory managed in C? • C++? • Java?