Lecture 6a: Introduction to dynamic containers


I. Intro

If we can remember back to when we were working with arrays in the C/C++ days we remember that arrays don't really change in size. You make them, you like them (hopefully) and you don't change their size. This makes a lot of sense. If you remember back to how you create them:

char stuff[256];

You make it so that there are 256 continguous memory locations for data type of char and if you go out of bound, past 255 in location, you would cause the program to either crash or read junk. The advantages of having an array was also great in that it is fast. For you to access location n, all you need to do is take the memory location of the variable and add it:

stuff[54] = 9;

---becomes---

(stuff + sizeof(char)*54)* = 9;

At this point we aren't really concerned with what the details here really mean but the (*) at the end of the statement on the left side of the = sign means you are directly getting at the memory at that location. Basically stuff is only a pointer to the first spot in the array. The rest are just offsets in actual memory. The sizeof function tells you how large a data type is in memory.

So naturally the problem arises... what do you do if you need more space than what you first allocate? The obvious answer is you have to make a new and bigger array and copy the old into the new one's front. You will have access to the new stuff at the end. So when you make that new array... 1) how much bigger is it? 2) do you need a new array?

II. Solving the size problem

Time Efficiency
Technique
Space Efficiency
small change
big change
Feasibility
Do Nothing
MAX
MAX
MAX
None
Increase size on demand (1:1)
MAX
AVE
MIN
Yes
Increase size by twice (2x)
AVE
AVE
AVE
Yes
Increase size to max (+INF)
MIN
MAX
MAX
Depends
Use Linked List
MAX
MAX
MAX
More management and possible memory leaks, bad access time

Do Nothing

For all you lazy bums out there, this is your choice of approach... you do nothing. This is actually feasible if you have data that expires and don't need the space anymore... but if that were true you won't even think about resizing to begin with. So essentially this approach buys you nothing but is only here to serve as control to the ideal situation.

Increase size on demand (1 size larger for 1 block requested on every request)

This idea is good for small changes expected in the size requirement on small arrays. It basically makes a new array with only size of old + 1 elements and copies the rest and adds the new. This is not really that efficient if you have many new elements to add in that the time it takes to create that new array will far outweigh the gains you get from adding the elements. This, however, is good for such things as keeping an employee record. You are not expecting to add many new things at any fast rate and with the space efficiency, this works out.

Increase size by twice (size = 2x whenever request exceeds size)

This is your most balanced technique. The amount of work done on all levels is about proportionate of the desired operations. This is the best tradeoff before we start going into linked list. It offers no maximums, just average performances across the board.

Increase size to max allowed (size = INF)

This is similar to the Do Nothing technique except it actually solves most problems. It will take up all allowed memory for a variable and use that as the array. This technique will prevent any copying from ever been needed... but at the same time it leaves you no room to make any other variables at all. If you are dealing with a program that only needs a huge array... this is the thing for you.

Linked List

This will be the lecture for next week. This basically maximizes insertion and deletion of an element from the list but will present a big overhead in maintenance, management as well as costly for the access of elements (if random). More on this will be discussed next week.