Download presentation
Presentation is loading. Please wait.
Published byPercival Stevens Modified over 9 years ago
1
CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)
2
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
3
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
4
Partially Filled Array
5
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.
6
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.
7
Reallocation and copy
8
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
9
Picture of Adding to Middle Must use a loop to make space for new value. Careful! Loop from top down
10
Removing an Element Removing an Element will also require “sliding over” to delete the value Therefore is O(n) worst case
11
Picture of Remove Element Remove also requires loop. This time should it be from top or bottom?
12
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.
13
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
14
Interface, continued struct 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);
15
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); }
16
dyArrayFree - clean up Void dyArrayFree (struct dyArray * da) { free (da->data); da->capacity = 0; da->size = 0; }
17
Size int dyArraySize (struct dyArray * da) { return da->size; } Even though one line, still a good idea to hide behind function call abstraction
18
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; }
19
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?
20
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)
21
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); }
22
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.
23
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)
24
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
25
get and Set, easy operations EleType dyArrayGet (struct dyArray *da, int index) { assert(index >= 0 && index size); return da->data[index]; } Set is similar
26
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
27
Do the easy parts first Void dyArrayInsert(struct dyArray * da, int index, EleType newValue) { assert(index >= 0 and index size); if (da->size >= da->capacity) _dyArrayDoubleCapacity(da); /* slide things over - need to do this */ da->data[index] = newValue; da->size++ }
28
Then do the slide part Well, I need to leave SOMETHING for you to do Hint. It’s a loop.
29
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.
30
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?
31
Steps in doing removeAt Check that the index is legal Remove by sliding values over Decrement the size
32
Implement removeAt Void dyArray removeAt(struct dyArray *da, int index) { assert(index >= 0 && index size); /* remove by sliding things over */ /* you get to do this */ da->size--; }
33
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);
34
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
35
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) { … }
36
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.
37
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
38
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 */
39
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?
40
Remove void remove (struct dyArray *da, EleType testValue) { int i; for (i = 0; i size; i++) { if (EQ(testValue, da->data[i])) { dyArrayRemoveAt(da, i); return; } }
41
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.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.