Top Banner
ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time o add(size(),x), remove(size()-1) [add(0,x), remove(0)] take constant amortized time o Can waste a lot of space 2/3 of the array positions can be empty o Not suitable for real-time applications grow(), shrink(), and balance() take O(size()) time.
64

ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Jan 19, 2016

Download

Documents

Shana Allen
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays

Review

o get(i), set(i,x) take constant time

o add(size(),x), remove(size()-1) [add(0,x), remove(0)] take constant amortized time

o Can waste a lot of space

− 2/3 of the array positions can be emptyo Not suitable for real-time applications

− grow(), shrink(), and balance() take O(size()) time.

Page 2: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• RootishArrayStack: A list implementation with

− get(i) and set(i,x) in constant time

− add(i,x) and remove(i) in O(1 + size()-i) time

− no more than O(size()1/2) wasted space

− Suitable for real-time applications

o in some languages (not Java)

Coming up

• DualRootishArrayDeque

− A 2-ended version

Page 3: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Store the stack as a List of blocks (arrays)

− block k has size (k+1), for k=0,1,2,...,r

− at most 2 blocks not full

RootishArrayStack

a

b c

d fe

g jh i

k l

0

1

2

3

4

blocks public class

RootishArrayStack<T> extends AbstractList<T> { List<T[]> blocks; int n; ...}

Page 4: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• How much space is wasted?

− r blocks have room for r(r+1)/2 elements

− To store n elements we need

− r(r+1)/2 ≥ n

− r ≥ (2n)1/2 blocks are sufficient

− We only waste O(n1/2) space keeping track of the blocks

• The size of the last 2 blocks is at most 2r + 3

− Only waste O(n1/2) space on non-full blocks

− Wasted space is only O(n1/2)

Space analysis

r+1

r

Page 5: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• As usual:

− grow() if necessary

− shift elements i,...,size()-1 right by one position

RootishArrayStack – add(i,x)

public void add(int i, T x) { int r = blocks.size(); if (r*(r+1)/2 < n + 1) grow(); n++; for (int j = n-1; j > i; j--) set(j, get(j-1)); set(i, x);}

Page 6: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Also as usual:

− shift elements i+1,...,size()-1 left by one position

− shrink() if necessary

RootishArrayStack – remove(i)

public T remove(int i) { T x = get(i); for (int j = i; j < n-1; j++) set(j, get(j+1)); n--; shrink(); return x;}

Page 7: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Add another block of size r

− runs in constant time in languages not requiring array initialization

− otherwise, takes O(r) = O(size()1/2) time.

RootishArrayStack – grow()

protected void grow() { blocks.add(f.newArray(blocks.size()+1));}

Page 8: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Remove blocks until there are at most 2 partially empty blocks

RootishArrayStack – shrink()

protected void shrink() { int r = blocks.size(); while (r > 0 && (r-2)*(r-1)/2 >= n) { blocks.remove(blocks.size()-1); r--; }}

Page 9: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Find the block index b that contains element i (function i2b(i) )

• access element i - b(b+1)/2 within that block

RootishArrayStack get(i) and set(i,x)

public T get(int i) { int b = i2b (i); int j = i - b*(b+1)/2; return blocks.get(b)[j];}

public T set(int i, T x) { int b = i2b(i); int j = i - b*(b+1)/2; T y = blocks.get(b)[j]; blocks.get(b)[j] = x; return y;}

Page 10: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Converting the List index i into a block number b

− 0,...,i consists of i+1 elements

− Blocks 0,...,b can store (b+1)(b+2)/2 elements

− We want to find minimum integer b such that

o (b+1)(b+2)/2 ≥ i + 1

− Solve (b+1)(b+2)/2 = i + 1 using the quadratic equation

− quadratic equation gives a non-integer solution b’

o actually two solutions, but only one is positive

− set b = Γb’˥

RootishArrayStack - i2b(i)

Page 11: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Theorem: A RootishArrayStack− can perform get(i) and set(i,x) in constant time− can perform add(i,x) and remove(i) in

O(1+size()-i) time− uses only O(size()1/2) memory in addition to what

is required to store its elements

RootishArrayStack - summary

• Key points:− Real-time

• no amortization− Low-memory overhead

• O(n1/2) versus O(n) for other array-based stacks

Page 12: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Theorem: Any data structure that allows insertions will, at some point during a sequence of n insertions be wasting at least n1/2 space.

Optimality of RootishArrayStack

• Proof: If the data structure uses more than n1/2 blocks− Real-time− n1/2 pointers (references) are being wasted just

keeping track of blocks− Otherwise, the data structure uses k ≤ n1/2 blocks

• some block B has size at least n/k ≥ n1/2

• when B was allocated, it was empty and therefore was a waste of n1/2 space

Page 13: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• The use of many arrays to store data means that we can't do shifting with 1 call to System.arraycopy()– Slower than other implementations when i is

small

Practical Considerations

• The solution to the quadratic formula in i2b(i) requires the square root operation

−This can be slow−This can lead to rounding errors

• can be corrected by checking that • (b+1)/2 < i ≤ (b+1)(b+2)/2

−Lookup tables can speed things• we only want an integer square root

Page 14: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Using a RootishArrayStack for the internal stacks within a DualArrayDeque we obtain:

−Theorem: A DualRootishArrayDeque• can perform get(i), set(i,x) in constant time• can perform add(i,x) remove(i) in O(1 + min{i,size()-i}) amortized time

−uses only O(size()1/2) memory in addition to what is required to store its elements

DualRootishArrayDeque

• A real-time version is possible, see−Brodnik, Carlsson, Demaine, Munro, and

Sedgewick. Resizeable arrays in optimal time and space. Proceedings of WADS 1999

Page 15: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Array-based implementations of Lists, Queues, Stacks, and Deques have many advantages

−Constant-time access by position [get(i), set(i,x)]−Constant-amortized time addition and removal

at the ends−Space-efficient versions use only O(n1/2) extra

space

Review

• Big disadvantage−Additions and removals in the interior are slow

• Running time is at least Ω(min{i, size()-i})

Page 16: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Lists and queues based on (singly and doubly) linked lists– It might use an array of length 2n to store n elements of data –get(i), set(i,x) are slowadd(), remove() with an iterator take constant time

• Space-efficient linked lists

Coming up…

Page 17: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Singly-linked lists

–Efficient stacks and queues

• Doubly-linked lists

–Efficient deques

• Space-efficient doubly-linked lists

–Time/space tradeoff

Coming up…

Page 18: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• A list is a sequence of Node:

• Node contains–a data value x–a pointer next to the next node in the list

Singly-linked lists

a b c d e null

protected class Node { T x; Node next;}

Page 19: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• We keep track of the first node in the list (head)

• We might also keep track of the last node (tail)

Singly-linked lists (cont'd)

public class SLList<T> extends AbstractQueue<T> { Node head; Node tail; int n; ...}

a b y zhead

tail ..

. null

Page 20: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• A singly-linked list can implement a queue

− enqueue at the tail

− dequeue at the head

Queues as singly-linked lists

• Requires special care to manage head and tail correctly

− when adding to empty queue

− when removing last element from queue

a b y zhead

tail ..

. null

front of the linefront of the line back of the lineback of the line

Page 21: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Dequeuing (removing) an element

a b y zhead

tail ..

. null

e

head

tail

null

public T poll() { T x = head.x; head = head.next; if (--n == 0) tail = null; return x;}

Page 22: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

a b

x

head

tail

null

public boolean offer(T x) { Node u = new Node(); u.x = x; if (n == 0) { head = u; tail = u; } else { tail.next = u; tail = u; } n++; return true;}

Enqueuing

x

head

tail

null

Page 23: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Delicateness

public boolean offer(T x) { Node u = new Node(); u.x = x; if (n == 0) { head = u; tail = u; } else { tail = u; tail.next = u; } n++; return true;}

• This code is wrong

−can you see why?

Page 24: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• A singly-linked list can also be used as a stack

−push and pop are done by manipulating head

Stacks as singly-linked lists

a b y zhead

tail ..

. null

top of the stacktop of the stack

bottom of the stackbottom of the stack

Page 25: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Stack - push

a

b ehead

tail

null

e

head

tail

null

public T push(T x) { Node u = new Node(); u.x = x; u.next = head; head = u; if (n == 0) tail = u; n++; return x;}

c d

Page 26: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• In a singly-linked list, we can even do arbitrary insertions/deletions− if we are given a pointer to the preceding

element• Getting a pointer to the ith node takes O(i+1) time

Arbitrary insertion and deletions

protected Node getNode(int i) { Node u = head; for (int j = 0; j < i; j++) u = u.next; return u;}

a b y zhead

tail

..

. null

u

Page 27: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Does not work for first node

−no preceding node u!

Deleting a node

u d e

protected void deleteNext(Node u) { if (u.next == tail) tail = u; u.next = u.next.next;}

Page 28: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Does not work for first node

−no preceding node u!

Adding a node

u

v

e

protected void addAfter(Node u, Node v) { v.next = u.next; u.next = v; if (u == tail) tail = v;}

Page 29: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

29

• Write code for–add(i,x)–remove(i)

• Code should run in O(1+i) time

In-Class Exercise

Page 30: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Singly-linked lists support:−push(x), pop(), enqueue(x), dequeue() in constant time (in the worst case)

−add(i,x), remove(i) in O(1+i) time

Singly-linked list summary

• One Node is created per list item−Memory allocation overhead−Node contains data + 1 pointer/reference (next)

−At least n pointers for a list of size n

Page 31: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Singly-linked lists fall just short of being able to implement a deque

−No way to remove elements from the tail

Doubly-linked lists

a b y zhead

tail ..

. null

can't access this nodeexcept through head

can't access this nodeexcept through head

Page 32: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Doubly-linked lists maintain two pointers (references) per node

−next - points to next node in the list

−prev - points to previous node in the list

Doubly-linked lists

a b y z

head tail

..

. null

protected class Node { Node next, prev; T x;}

null

Page 33: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• This code is incorrect – Why?

Removing a node (incorrect)

u d e

protected void remove(Node p) { p.prev.next = p.next; p.next.prev = p.prev; n--;}

p.prevp.prev

p.nextp.next

pp

Page 34: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Doesn't correctly handle boundary cases

− p == head (so p.prev == null)

− p == tail (so p.prev == tail)

− p == head and p == tail

(sp p.prev == p.tail == null)

Removing a node (incorrect)

d e

protected void remove(Node p) { p.prev.next = p.next; p.next.prev = p.prev; n--;}

head

tail

u d

dhead tail

Page 35: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Versus

protected void remove(Node p) { if (p == head && p == tail) { head = null; tail = null; } else if (p == head) { head = p.next; p.next.prev = null; } else if (p == tail) { tail = p.prev; p.prev.next = null; } else { p.prev.next = p.next; p.next.prev = p.prev; } n--;}

protected void remove(Node p) { p.prev.next = p.next; p.next.prev = p.prev; n--;}

Page 36: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Code for boundary cases is troublesome− hard to write correctly− lots of cases− slow to execute (on some architectures)

• We would like to get rid of boundary cases− need to get rid of head and tail

Code is error prone

protected void remove(Node p) { p.prev.next = p.next; p.next.prev = p.prev; n--;}

Page 37: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Replace head and tail with a dummy Node− dummy.next replaces head− dummy.prev replaces tail− dummy is always present; even in an empty list

The dummy node technique

a b y z...

dummy

public class DLList<T> extends AbstractSequentialList<T> { protected Node dummy; protected int n; ...}

Page 38: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Creating a new (empty) list

public DLList() { dummy = new Node(); dummy.next = dummy; dummy.prev = dummy; n = 0;}

dummy

Page 39: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Now removing a node is easy

Removing a node

u d e

protected void remove(Node p) { p.prev.next = p.next; p.next.prev = p.prev; n--;}

p.prevp.prev

p.nextp.next

pp

Page 40: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Removing a node

p

dummy

protected void remove(Node p) { p.prev.next = p.next; p.next.prev = p.prev; n--;}

pp

• The same code works even when removing the last node

p.prev == p.next == dummy

p.prev == p.next == dummy

Page 41: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Add the new Node u just before Node p

Adding a node

protected Node add(Node u, Node p) { u.next = p; u.prev = p.prev; u.next.prev = u; u.prev.next = u; n++; return u;}

d

u

p

p.prevp.prev

pp

uu

Page 42: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• This code is not correct. Why?

Exercise

protected Node add(Node u, Node p) { u.next = p; u.next.prev = u; u.prev = p.prev; u.prev.next = u; n++; return u;}

d

u

p

p.prevp.prev

pp

uu

Page 43: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• To find the ith node search− from the front if

i < size()/2− from the back

otherwise• O(1+min{i, size()-i})

time• Fast

− when i~0 (head)− when i~size() (tail)

Finding a node

protected Node getNode(int i) { Node p = null; if (i < n/2) { p = dummy.next; for (int j = 0; j < i; j++) p = p.next; } else { p = dummy; for (int j = n; j > i; j--) p = p.prev; } return(p);}

Page 44: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• add(i,x) and remove(i) are now easy−Find the appropriate node p−Add x before p (or remove p)

• Takes O(1 + min{i, size()-i}) time

Removing and Adding

public T remove(int i) { Node p = getNode(i); remove(p); return p.x;}

public void add(int i, T x) { add(getNode(i), x);}

Page 45: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• get(i) and set(i,x) are easy too−and take O(1 + min{i, size()-i}) time

Getting and setting

public T get(int i) { return getNode(i).x;}

public T set(int i, T x) { Node u = getNode(i); T y = u.x; u.x = x; return y;}

Page 46: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Doubly-linked lists support

−add(i,x), remove(i) in O(1 + min{i,size()-i}) time

• deque operations run in constant time per operation

−get(i), set(i,x) in O(1+min{i,size()-i}) time

−insertion/removal of any node in constant time

• given a reference to the node being deleted or

• a reference to the node after the insertion

Doubly-linked lists - summary

Page 47: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Linked lists are great, except

−Each value is stored in its own list node

• Each insertion requires allocating a new node

• Each node stores 2 pointers

−Wasted space is at least

2 × size() × sizeof(pointer)

• If data values are small (e.g., Integer) then wasted space can exceed the space for data

Memory-efficient linked lists

Page 48: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• Idea:−group list elements into blocks (arrays)

−blocks have size b+1−each block stores b-1, b, or b+1 values

• except the last block, which can be more empty

−store the blocks in a linked list

Memory-efficient linked lists

a b c d ge f h i j

last block - partly fulllast block - partly fullb = 3b = 3

Page 49: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• The number of blocks is at most−1 + size()/(b-1)−each block wastes a constant [O(1)] amount of space

−wasted space is O(b+n/(b-1))−By making b larger we can reduce the wasted space

• limit is b ~ n1/2

a b c d ge f h i j

Space analysis

Page 50: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• We represent each block as a BoundedArrayDeque

−ArrayDeque with size of backing array a set fixed

−a.length = b+1

−no grow() or shrink() operations

Block data structure

• Sometimes we will want to

−move the last element in node u to the front u.next

−move the first element in block i to the back of block i-1

−These operations take constant time in a BoundedArrayDeque

Page 51: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• To find the ith element we find the block that contains it

− Takes time O(1 + (min{i, size()-i} /

b))

− faster than a standard linked list

Finding an elementpublic T get(int i) { if (i < n/2) { Node u = first; int b = 0; while (b + u.x.size() < i + 1) { b += u.x.size(); u = u.next; } return u.x.get(i-b); } else { ...

a b c d ge f h i j

b=0b=0

b=3b=3

b=7b=7

b=9b=9

Page 52: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• To insert into block j– check if any of blocks j, j+1, j+2,...,j+b-1 are not full

• if yes, then there is space, so do shifting to make room• requires at most 2b deque operations• requires shifting at most b elements in one of the deques ( O(b) time )

Insertion - easy case O(b) time

a db c e hf g i j k

a db c e hf g i j kx

Insert x hereInsert x here

Page 53: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• If blocks j, j+1, ... j+b-1 are all full– these b blocks contain a total of b(b+1) elements– repartition them into b+1 blocks each containing b elements– then insert into the (now not full) block

Insertion – full case O(b2) time

Insert x hereInsert x herea db c e hf g i lj k

a db c e hf g i lj k

a dx b e hf g i lj kc

O(b2) timeO(b2) time

Page 54: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• To remove an element from block j– if any of blocks j, j+1, j+2,... contain more than b-1

elements• do shifting so that block j contains at least b elements• remove element from block j

Removal- easy case O(b) time

delete thisdelete this

a c d e f gb

a dc e f gcb

a d e f gc

Page 55: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Removal– hard case O(b2) time

delete thisdelete this

O(b2) timeO(b2) time

• If blocks j,...,j+b-1 each contain b-1 elements–we have b blocks each containing b-1 elements– redistribute so that we have b-1 blocks each

containing b elements– delete the element

a c d e fb

a dc e fb

a dc e f

Page 56: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• A CompactDLList has the following properties

–wasted space is O(size()/b)

–get(i) and set(i,x) each take

•O(1 + min{i, size()-i}/b) time

– remove(i) and add(i,x) take time

•O(b + min{i, size()-i}/b) usually

•O(b2 + min{i, size()-i}/b) occasionally

• What do we mean by usually and occasionally?

Space-Efficient Linked List (SElist)

Page 57: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• We use a credit scheme–A block with b+1 elements or b-1 elements has 1 credit–A block with b elements has 0 credits

• Main idea:–When insertion and removal take b2 time, we will take away b spare credits–With every insertion and removal we create at most one new credit

• Conclusion: At most one out of every b insertion/removals takes b2 time

Amortized analysis of CompactDLLists

Page 58: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• A hamburger costs 8 credits – [analogous to: operation that takes O(b2) time]

Weight-watchers analogy

• Every hour of workout gives you one credit– [analagous to: operation that takes O(b) time]

• The maximum number of hamburgers you are allowed to eat is– (# hours spent working out)/8

Page 59: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• At most one credit is created by insertion– (maybe none)

Analysis of insertion (not full case)

a db c e hf g i j k

a db c e hf g i j kx

insert x hereinsert x here

₡₡ ₡₡

₡₡₡₡₡₡

Page 60: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• b credits are freed up and one credit is added

Analysis of insertion (full case)

a db c e hf g i lj k

a db c e hf g i lj k

a dx b e hf g i lj kc

₡₡ ₡₡ ₡₡

₡₡

3 credits freed now3 credits freed now

insert x hereinsert x here

1 credit is added1 credit is added

Page 61: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• At most one new credit is added

Analysis of removal (easy case)

a c d e f gb

delete thisdelete this

a dc e f gcb

a d e f gc

₡₡₡₡

₡₡₡₡

₡₡₡₡₡₡

Page 62: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• b credits are freed and one credit is added.

Analysis of insertion (sparse case)

a c d e fb

delete thisdelete this

a dc e fb

a dc e f

₡₡₡₡₡₡

₡₡

3 credits freed3 credits freed

1 credit is added1 credit is added

Page 63: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

• In a sequence of n add/remove operations–At most n/b takes O(b2) time–Others take O(b) time

Analysis wrap up

• Total time is–O(nb + (n/b)b2) = O(nb)–O(b) amortized time per operation

Page 64: ArrayStack (ArrayList), [ArrayDeque, and DualArrayDeque] implement the List interface using one or two arrays Review o get(i), set(i,x) take constant time.

Compact doubly-linked list (summary)

• Theorem: A CompactDLList is an implementation of the List interface with the following properties:– get(i) and set(i,x) each take•O(1 + min{i, size()-i}/b) time

– remove(i) and add(i,x) take•O(b + min{i, size()-i}/b) amortized time

– The amount of memory used beyond that needed to store the data is O(n/b)– The number of memory allocation/deallocations

during a sequence of n add/remove operations is O(n/b)