0% found this document useful (0 votes)
0 views38 pages

02 DynamicArrays

The document discusses dynamic arrays, emphasizing their importance as a commonly used data structure in programming. It outlines fundamental operations for lists, implementation details in Java and C++, and the complexities associated with adding and managing elements in dynamic arrays. The document also highlights performance issues and practical examples of using dynamic arrays in programming languages like Java and C++.

Uploaded by

rahubiju
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views38 pages

02 DynamicArrays

The document discusses dynamic arrays, emphasizing their importance as a commonly used data structure in programming. It outlines fundamental operations for lists, implementation details in Java and C++, and the complexities associated with adding and managing elements in dynamic arrays. The document also highlights performance issues and practical examples of using dynamic arrays in programming languages like Java and C++.

Uploaded by

rahubiju
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 38

Dynamic Arrays

Dov Kruger

Department of Electrical and Computer Engineering


Rutgers University

January 23, 2024

1/38
©Dov Kruger 2023
2.1 Introduction

A list is the single most used data structure, and the most
common design pattern in the world

Most computer programs contain thousands or hundreds of


thousands of lists
And the average size? Between 0 and 1.

Yes, that’s right. Most lists are either empty or have one element

A Dynamic array is an object with a single block of memory to


hold a list of values that can grow and shrink

With the right design, it can be very efficient


A common mistake yields disastrously bad performance

2/38
©Dov Kruger 2023
List Operations

What are the principle operations in creating a list?

Adding an element to the list?


Finding an element in a list?
Replace?

It turns out that not all the above operations are fundamental
You have to drill down

3/38
©Dov Kruger 2023
Fundamental Operations for Lists

Create a list
Add a value to the end of the list
Add a value to the start of the list
Add a value at a specific position
Get the size of the list
Remove an element from the end of the list
Remove an element from the start of the list
Remove an element at a specific position
Get the value at a particular position
Set the value at a particular position

4/38
©Dov Kruger 2023
Fundamental Operations in Java

L i s t a = new L i s t ( ) ; // c r e a t e an empty l i s t o b j e c t
a . addEnd ( 5 ) ;
a . addStart (1);
a . i n s e r t A f t e r ( 0 , 3 ) ; // i n s e r t v a l u e 3 a f t e r p o s i t i o n 0
int sz = a . s i z e ( ) ; // number o f e l e m e n t s i n t h e l i s t

a . removeEnd ( ) ;
a . removeStart ( ) ;
a . remove ( i n d e x ) ;

int v = a . get ( index )


a . set ( index , v )

5/38
©Dov Kruger 2023
Fundamental Operations in C++

C++ is similar to Java but objects are declared using different


syntax

DynamicArray a ; // c r e a t e an empty l i s t
a . addEnd ( 5 ) ; // add 5 t o t h e end o f t h e l i s t

Be aware: by default, it’s easy to crash in C++ if you do not


understand copy semantics

6/38
©Dov Kruger 2023
Memory Management in C++ and Copy Semantics

In C++ by default certain constructors are written. Not


understanding how they work can result in crashing. If you write in
C++ make sure you understand!

c l a s s DynamicArray {
public :
D y n a m i c A r r a y ( ) ; // d e f a u l t c o n s t r u c t o r
~ D y n a m i c A r r a y ( ) ; // d e s t r u c t o r
D y n a m i c A r r a y ( c o n s t D y n a m i c A r r a y& o r i g ) ; // c o p y c o n s t r u c t o r
D y n a m i c A r r a y& o p e r a t o r =( c o n s t D y n a m i c A r r a y& o r i g ) ;

// o p t i o n a l : move c o n s t r u c t o r
D y n a m i c A r r a y ( D y n a m i c A r r a y&& o r i g ) ;
};

7/38
©Dov Kruger 2023
Operations: addEnd

What does it mean to add a number to a list?

8/38
©Dov Kruger 2023
Operations: addEnd

9/38
©Dov Kruger 2023
Operations: addEnd

10/38
©Dov Kruger 2023
Operations: addEnd

11/38
©Dov Kruger 2023
Operations: addEnd

12/38
©Dov Kruger 2023
Operations: addEnd

13/38
©Dov Kruger 2023
Is There a Special Case for the First time?

The first time, the existing pointer is null, but the size=0, nothing
is copied

14/38
©Dov Kruger 2023
Implementation in C++

Analyze this code and determine the complexity of addEnd

v o i d addEnd ( i n t v ) { //O( ? )
c o n s t i n t ∗ temp = d a t a ; // k e e p t r a c k o f o l d memory
d a t a = new i n t [ s i z e + 1 ] ; // a l l o c a t e new b l o c k one b i g g e r
f o r ( i n t i = 0 ; i < s i z e ; i ++)
d a t a [ i ] = o l d [ i ] ; // copy o l d d a t a t o new
d a t a [ s i z e ] = v ; // add i n new v a l u e
delete [ ] old ;
s i z e ++; // add one t o s i z e o f l i s t
}

15/38
©Dov Kruger 2023
Operations: addStart(4)

16/38
©Dov Kruger 2023
Operations: addStart(4)

17/38
©Dov Kruger 2023
Operations: addStart(4)

18/38
©Dov Kruger 2023
Operations: addStart(4)

19/38
©Dov Kruger 2023
Operations: addStart(4)

20/38
©Dov Kruger 2023
Operations: addStart(4)

21/38
©Dov Kruger 2023
Complexity of Adding Elements

First time: 1

Second time: allocate new memory, copy the existing (1) and add
1=2

Third time: copy existing (2) and add 1 = 3

1 + 2 + 3 + ... = n(n + 1)/2 = O(n2 )

22/38
©Dov Kruger 2023
Implementation Complexity in C++ and Java
Java

Allocation copies zeros into every byte and is therefore O(n)


Not necessary to explicitly delete the memory
The garbage collector deallocates
It still takes time, which must be accounted for in your algorithm

C++

Allocation writes nothing. Memory is random. Therefore O(1)


Presumably you have to correctly initialize, so O(n) but Java can be
twice as slow
You must manually delete the memory or you leak (task grows until you
crash)
If you want to know how to catch leaks, see videos on valgrind and
-fsanitize

23/38
©Dov Kruger 2023
Operations: insert(2, 7)

24/38
©Dov Kruger 2023
Operations: insert(2, 7). contd.

25/38
©Dov Kruger 2023
Operations: removeEnd

26/38
©Dov Kruger 2023
Operations: removeStart

27/38
©Dov Kruger 2023
Operations: remove()

28/38
©Dov Kruger 2023
Get size of list

Getting the size of the list is O(1)

The size of the DynArray is stored inside

29/38
©Dov Kruger 2023
Get/Set an Element

30/38
©Dov Kruger 2023
Complexity Problems

The DynamicArray as shown is poor because

Growing or shrinking a list by n elements will take O(n2 ) time


Total RAM copied will also be O(n2 ) although it can be
recycled
Very, very slow

Needed: Build a new, better DynamicArray which can grow more


efficiently

Preallocate more space than needed


addEnd is O(1) until space is all full
Growing the list will require O(n) time, where n is the list size
What is the total cost of this?

31/38
©Dov Kruger 2023
Growing an Array

For DynamicArray, cost is


1 + 2 + 3 + ... + n = n(n + 1)/2 = O(n2 )
Suppose instead of growing every time we grow every 2 times?
1 + 2 + 1 + 4 + 1 + 5 + ... n = still O(n2 ) though a lower
constant factor

The way to fundamentally improve: double the size each time

This means grow will happen infrequently:


1 + 2 + 4 + 8 + 16 + ... + n/2 + n
Recall: sum of the powers of 2 = O(2n) = O(n)

Q: How many times will the list grow to reach n=1 million (106 )
elements?

32/38
©Dov Kruger 2023
5.2 Practical Problems Where Knowledge is Crucial

What you have learned about dynamic arrays will help you
understand common performance problems
In Java, String is immutable (cannot be changed)
Therefore the only way to grow a string is to create a new one.
This is exactly like the first BadDynamicArray example we analyzed

p u b l i c c l a s s MyCode {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
String s = "" ;
f i n a l i n t n = 1 0 0 0 0 0 0 ; // what i s wrong w i t h t h i s c o d e ?
f o r ( i n t i = 0 ; i < n ; i ++)
s += i ; // " 1 " , " 1 2 " , " 1 2 3 " , " 1 2 3 4 " , . . .
System . o u t . p r i n t l n ( s ) ;
}

33/38
©Dov Kruger 2023
Java: StringBuilder to the Rescue
The problem with String on the previous slide is that it cannot
grow. Each time
A new String object must be created
The old one must be copied
StringBuilder solves this problem

S t r i n g B u i l d e r b = new S t r i n g B u i l d e r ( ) ;
f i n a l int n = 1000000;
f o r ( i n t i = 0 ; i < n ; i ++)
b . append ( i ) ;

Knowing that the StringBuilder must grow, speed the code further:
S t r i n g B u i l d e r b = new S t r i n g B u i l d e r ( n ∗ 6 ) ;
34/38
©Dov Kruger 2023
Practical Example: MATLAB

MATLAB also can easily have the same problem as Java


This will never complete

a = [];
f o r i =1:1000000
a = [a i ];
end

35/38
©Dov Kruger 2023
Example: Dynamic Arrays Using C++ Library

In the C++ Library, vector

#i n c l u d e <v e c t o r >
i n t main ( ) {
v e c t o r <i n t > a ;
const i n t n = 1 0 2 4 ;
a . r e s e r v e ( n ) ; // p r e a l l o c a t e s p a c e f o r e f f i c i e n c y
f o r ( i n t i = 0 ; i < n ; i ++)
a . push_back ( i ) ;
}

36/38
©Dov Kruger 2023
Example: Dynamic Arrays Using Java Library

import j a v a . u t i l . ∗ ;

public c l a s s TestDynamicArray {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
A r r a y L i s t <I n t e g e r > m y l i s t = new A r r a y L i s t < >();
}
}

37/38
©Dov Kruger 2023
Example: Dynamic Arrays Using C++ Library

#i n c l u d e <v e c t o r >

i n t main ( ) {
v e c t o r <i n t > m y l i s t ;
f o r ( i n t i = 0 ; i < n ; i ++)
m y l i s t . push_back ( i ) ;
}

38/38
©Dov Kruger 2023

You might also like