CS261 Data Structures Dynamic Arrays Part 2: Implementation - - PowerPoint PPT Presentation
CS261 Data Structures Dynamic Arrays Part 2: Implementation - - PowerPoint PPT Presentation
CS261 Data Structures Dynamic Arrays Part 2: Implementation Arrays: Pros and Cons Pro: only core data structure designed to hold a collection of elements Pro: random access: can quickly get to any element O(1) Con: fixed size:
- Pro: only core data structure designed to hold a
collection of elements
- Pro: random access: can quickly get to any
element O(1)
- Con: fixed size:
– Maximum number of elements must be specified when created
Arrays: Pros and Cons
- How to make a general purpose container
class?
- We define TYPE as symbolic preprocessor
constant
- Requires recompiling source for new element
types
– Not elegant, but workable.
Element Types - TYPE
#ifndef __DYNARR_H #define __DYNARR_H # define TYPE int # define LT(a, b) ((a) < (b) # define EQ(a, b) ((a) == (b)) ... /* Rest of dynarr.h (on next slide). */ #endif
Interface File: dynarr.h
struct DynArr { TYPE *data; /* Pointer to data array. */ int size; /* Number of elements in collection. */ int cap; /* Capacity of array. */ }; /* Dynamic Array Functions */ void _initDynArr(struct DynArr *v, int cap); void freeDynArr(struct DynArr *v); int sizeDynArr(struct DynArr *v); void addDynArr(struct DynArr *v, TYPE e) TYPE getDynArr(struct DynArr *v, int pos); void putDynArr(struct DynArr *v, int pos, TYPE val);
Interface (cont.)
Not ideal to have in header file
void _initDynArr(struct DynArr *v, int cap) { v->data = malloc(cap * sizeof(TYPE)); assert(v->data != 0); v->size = 0; v->cap = cap; }
Initialization: initDynArr
struct DynArr { TYPE *data; int size; int cap };
void freeDynArr(struct DynArr *v) { assert(v != 0); assert(v->data != 0); free(v->data); v->data = 0; v->cap = 0; v->size = 0; }
Clean Up: freeDynArr
struct DynArr { TYPE *data; int size; int cap };
struct DynArr d; _initDynArr(&d, 8); addDynArr(&d, 1);
...
freeDynArr(&d);
Concretely, in C…using the dynArray
To use a struct dynArr, the user must declare one in main.c (see previous slide). To declare it, the compiler must know its size when compiling that file (ie. it must be in the header!) If it’s in the header, it is ‘exposed’ to the end user and this can be dangerous and violates ‘encapsulation’ (C can’t declare “private” struct elements) Better Solution: Provide create() and delete() functions for your data
- structure. Create will returns a ‘pointer’ to allocated space
User can always declare pointers and compiler always knows the size of a pointer! Now you can hide your Struct in the .c file or a library
Better Solution
struct DynArr { TYPE *data; /* Pointer to data array. */ int size; /* Number of elements in collection. */ int cap; /* Capacity of array. */ }; struct DynArr; /* developer can still declare pointer to DynArr */ /* Dynamic Array Functions */ void _initDynArr(struct DynArr *v, int cap); void freeDynArr(struct DynArr *v); int sizeDynArr(struct DynArr *v); void addDynArr(struct DynArr *v, TYPE e) TYPE getDynArr(struct DynArr *v, int pos); void putDynArr(struct DynArr *v, int pos, TYPE val); struct DynArr *createDynArr(int cap);
Modified Interface
Moved to .c implementation file
Create Dynamic Array
? size = data = ? cap =
createDynArr must: 1) allocate space for DynArr struct
Usage of createDynArr: struct DynArr *d; d = createDynArr(20); ?
Create Dynamic Array
size = data = 20 cap =
Return pointer createDynArr must: 1) allocate space for DynArr struct 2) initialize dynamic array 3) return pointer to dynamic array
Usage of createDynArr: struct DynArr *d; d = createDynArr(20); . . . .
struct DynArr* createDynArr(int cap) { struct DynArr *r; assert(cap > 0); r = malloc(sizeof( struct DynArr)); assert(r != 0); _initDynArr(r,cap); return r; }
Create Dynamic Array
Allocate space for struct DynArr itself!
struct DynArr { TYPE *data; int size; int cap };
struct DynArr *d; d = createDynArr(20); addDynArr(d, 1);
...
freeDynArr(d);
Using ‘encapsulated’ DynArray
When to use Dynamic Arrays
- Need random access
- Low memory footprint
- Don’t know size of array at compile time
- See Examples in Java and C++ STL
– Vector (C++ STL) – Vector and ArrayList (Java)
- When should/should not use a dynamic array!
– When O(N) resize is NEVER acceptable
Dynamic Array Stack/Bag
- First: Worksheet 14 – Dynamic Array Basics
– _setCapacity – Get, Put – Swap , RemoveAt
- Worksheets 16, 21 (start for next assignment)
– Implement the stack/bag interfaces – keep and reuse functionality from WS#14 where appropriate.
Get the Value at a Given Position
/* Returns data value at index position pos */ TYPE getDynArr (struct DynArr *da, int pos); { assert((sizeDynArr(da) > pos) && (pos >= 0)); return da->data[pos]; }
struct DynArr { TYPE *data; int size; int cap };
Add a New Element
/* Insert new data value val at end of array */ void addDynArr (struct DynArr * da, TYPE val){ if (da->size >= da->cap) _dyArrDoubleCapacity(da); da->data[da->size] = val; da->size++; }
struct DynArr { TYPE *data; int size; int cap };
Double the Capacity
8 size = data = 8 cap = 8 size = data = 16 cap =
Before reallocation: After reallocation:
Must: allocate space copy data free old space
Double the Capacity
void _dyArrDoubleCapacity (struct DynArray * da) { TYPE * oldbuffer = da->data; int oldsize = da->size; int i; _initDynArr (da, 2 * da->cap); for (i = 0; i < oldsize; i++) da->data[i] = oldbuffer[i]; da->size = oldsize; free(oldbuffer); }
struct DynArr { TYPE *data; int size; int cap };