CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

41
CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Transcript of CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Page 1: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

CS 261 Fall 2009

Dynamic Array Introduction

(aka Vector, ArrayList)

Page 2: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Arrays, Pro and Con

• Simple Arrays have nice feature that they are randomly accessible - can quickly get to any element

• Dark side - size must be fixed when created.

• Often you don’t know much much space you need until you are done

Page 3: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Dynamic Array (Vector, ArrayList)

• Dynamic Array (Java Vector, ArrayList, same thing, different API) get around this by encapsulating a partially filled array.

• Hide memory management details behind a simple API

• Is still randomly accessible, but now it grows as necessary

Page 4: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Partially Filled Array

Page 5: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Size vs Capacity

• The size is the “logical” size - The number of elements. What the programmer thinks. Managed by an internal data value.

• The capacity is the size of the physical array. Number of elements it can hold.

Page 6: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Adding an element

• Adding an element to end is sometimes easy. Just increase the (logical) size, and put new value at end.

• But what happens when the size reaches the capacity?

• Must reallocate new data array - but this detail is hidden from user.

Page 7: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Reallocation and copy

Page 8: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Adding to Middle

• Adding an element to middle can also force reallocation (if the current size is equal to capacity)

• But will ALWAYS require elements to moved up to make space

• Is therefore O(n) worst case

Page 9: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Picture of Adding to Middle

Must use a loop to make space for new value. Careful! Loop from top down

Page 10: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Removing an Element

• Removing an Element will also require “sliding over” to delete the value

• Therefore is O(n) worst case

Page 11: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Picture of Remove Element

Remove also requires loop. This time should it be from top or bottom?

Page 12: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Element Types

• How to make a general purpose container class?

• We define element type as symbolic preprocessor constant. Default double.

• Requires recompiling source for new element types. Not elegant, but workable.

Page 13: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Interface file#ifndef DyArray_H#define DyArray_H

# ifndef EleType# define EleType double# endif

# ifndef LT# define LT(a, b) (a < b)# endif

# ifndef EQ# define EQ(a, b) (a == b)# endif

Page 14: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Interface, continuedstruct dyArray { EleType * data; int size; int capacity;};

/* prototypes */void dyArrayInit (struct dyArray *da, int initCap);void dyArrayFree (struct dyArray *da);void dyArrayAdd (struct dyArray *da, EleType d);EleType dyArrayGet (struct dyArray *da, int index);EleType dyarraySet (struct dyArray *da, int index, EleType

newValue);int dyArraySize (struct dyArray *da);

Page 15: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

dyArrayInit - initialization

void dyArrayInit (struct dyArray * da, int initCap){ assert (initCap >= 0); da->capacity = initCap; da->size = 0; da->data = (double *) malloc(da->capacity * sizeof(EleType)); assert (da->data != 0);}

Page 16: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

dyArrayFree - clean up

Void dyArrayFree (struct dyArray * da)

{

free (da->data);

da->capacity = 0;

da->size = 0;

}

Page 17: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Size

int dyArraySize (struct dyArray * da)

{ return da->size; }

Even though one line, still a good idea to hide behind function call abstraction

Page 18: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Add a new Element

void dyArrayAdd (struct dyArray * da, EleType newValue)

{ if (da->size >= da->capacity) _dyArrayDoubleCapacity(da);

da->data[da->size] = newValue; da->size += 1; }

Page 19: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

How to Double the Capacity

• Think it through. What are the steps? Need to make a new data buffer array that is twice the size. Need to copy elements from old buffer to new one.

• Next thought - can we REUSE anything we have done already. We have an init function that creates new buffer. What can we wrap around it?

Page 20: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Outline of operations

• Double the capacity, can do this by

• Calling Init the new buffer size

• Copy elements from old buffer

• (opps, need to keep reference to old buffer)

Page 21: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Double the Capacity

void _dyArrayDoubleCapacity (struct dyArray * da) {

EleType * oldbuffer = da->data; int oldsize = da->size; int i; dyArrayInit (da, 2 * da->capacity); for (i = 0; i < oldsize; i++) da->data[i] = oldbuffer[i]; da->size = oldsize; free(oldbuffer);}

Page 22: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Whats with the underscore?

• Underscore is just another character for the C compiler

• Common convention, function names beginning with underscore should not be called directly by user, but are “internal” functions.

Page 23: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Reuse, or not

• Notice how we reused the init function. • Should always look for places where

you can reuse code• But… Should we have reused add

instead of just placing elements into the new buffer

• Judgement call on very simple operations. (arguments pro and con)

Page 24: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

What is O( ) for double

• What is the O( ) of doubleCapacity?

• What is therefore the worst case O( ) of add?

• But do you expect it to be this bad most of the time?

• Subtle issue, will leave for next class

Page 25: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

get and Set, easy operationsEleType dyArrayGet (struct dyArray *da,

int index) {

assert(index >= 0 && index < da->size);

return da->data[index];

}

Set is similar

Page 26: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Adding to middle, a bit harder

Think about the steps

• Make sure index is legal

• Make sure you have enough space

• Slide the remaining elements over

• Move into the new location

• Increase size by 1

Page 27: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Do the easy parts first

Void dyArrayInsert(struct dyArray * da, int index, EleType newValue) {

assert(index >= 0 and index <= da->size); if (da->size >= da->capacity) _dyArrayDoubleCapacity(da); /* slide things over - need to do this */ da->data[index] = newValue; da->size++}

Page 28: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Then do the slide part

• Well, I need to leave SOMETHING for you to do

• Hint. It’s a loop.

Page 29: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

If we have insert, do we really need add?

• How are add and insert similar?

• How are they different?

• What are some arguments for keeping add, for getting rid of it?

• In any design, there are tradeoffs. You should think about the alternatives.

Page 30: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Remove - lots of variations

• There are lots of ways to think about remove.

• Remove last element. Remove first element. Remove element at given index. Remove a given value.

• Think reuse - what is the most general function?

Page 31: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Steps in doing removeAt

• Check that the index is legal

• Remove by sliding values over

• Decrement the size

Page 32: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Implement removeAt

Void dyArray removeAt(struct dyArray *da, int index) {

assert(index >= 0 && index < da->size);

/* remove by sliding things over */

/* you get to do this */

da->size--;

}

Page 33: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Now we have a nice general purpose tool

/* prototypes */void dyArrayInit (struct dyArray *da, int initCap);void dyArrayFree (struct dyArray *da);void dyArrayAdd (struct dyArray *da, EleType d);EleType dyArrayGet (struct dyArray *da, int index);EleType dyArraySet (struct dyArray *da, int index, EleType

newValue);int dyArraySize (struct dyArray *da);Void dyArrayInsert (struct dyArray *da, int index, EleType

newValue);Void dyArrayRemoveAt (struct dyArray *da, int index);

Page 34: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Now lets look at making some ADTS

• How would we make a Bag? (Add, test, remove by value, size)

• How would we make a Stack (add to top, remove from top, test if empty)

• We are building these abstractions on top of the implementations we have done already

Page 35: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Stack API

Void dyArrayPush (struct dyArray * stk, EleType newValue)

{ … /* all one or two liners */ }EleType dyArrayTop (struct dyArray * stk) { assert(! dyArrayIsEmpty(stk)); … }Void dyArrayPop (struct dyArray * stk) { … }Int dyArrayIsEmpty (struct dyArray * stk) { … }

Page 36: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Design Decisions

• This is not the only way to do things - lots of possible design decisions

• Could have used the dyArray API directly, instead of making the stack wrappers

• Could have hidden the dynamic array inside a different structure.

• Think about some of the implications of these choices.

Page 37: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Implementing a Bag

• What about the Bag API?

• Bag operations - add, test, remove, size

• Some of these are already done (which?)

• Some require more than one line

Page 38: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

How to do a test

Int dyArrayContains (struct dyArray *da, EleType testValue)

{

/* loop over all values, checking each */

/* if found, return 1 (true) */

/* if you get to end, return 0 (false) */

} /* you get to write this */

Page 39: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Remove

• This version of remove takes a value, and removes the FIRST instance of something equal to this

• What are some of the alternative versions of remove you could think of

• Can we reduce the problem to the remove we have written already?

Page 40: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Remove

void remove (struct dyArray *da, EleType testValue)

{ int i;

for (i = 0; i < da->size; i++) {

if (EQ(testValue, da->data[i])) {

dyArrayRemoveAt(da, i); return; }

}

}

Page 41: CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)

Your chance

• At home finish implementation of all the operations we have left unspecific. Next move on to remove to complete the Bag. Then do the stack.

• Also your implementation will be used in programming assignment 2.