0% found this document useful (0 votes)
45 views

Week 19 Dynamic Data Structure

This document discusses dynamic memory allocation and dynamic data structures in C++. It explains that static allocation assigns fixed memory locations, while dynamic allocation allows memory to be requested and freed as needed at runtime. Pointers are used to reference dynamically allocated memory, and the new and delete operators allocate and free the memory. Arrays and structures can also be dynamically allocated using pointers. Functions can access dynamically allocated variables, arrays, and structures using call-by-reference with pointers.

Uploaded by

Vidhi Kishor
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views

Week 19 Dynamic Data Structure

This document discusses dynamic memory allocation and dynamic data structures in C++. It explains that static allocation assigns fixed memory locations, while dynamic allocation allows memory to be requested and freed as needed at runtime. Pointers are used to reference dynamically allocated memory, and the new and delete operators allocate and free the memory. Arrays and structures can also be dynamically allocated using pointers. Functions can access dynamically allocated variables, arrays, and structures using call-by-reference with pointers.

Uploaded by

Vidhi Kishor
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 37

Dynamic Data Structures

Refer to dynamic memory allocation sections


in your text book.
E.g. Chapter 13 and Chapter 15 of Bronson.
Dynamic Memory Allocation
Static Allocation
 Each variable is assigned storage for a pool of
memory
 The location is fixed for life of variable
Arrays created statically
 Size is fixed once
 E.g. an array of 500 integers
 int A[500];
 May only use first few spaces. Rest is wasted
 OR
 E.g. an array of 5 integers
 int B[5]
 What if we need space for 6 integers?
2
Can we allocate space from our
pool of memory as required?
If we need more memory can we ask for
more?
If we need less can we free up
memory?
Can we do this while the program is
running?

3
Dynamic memory
Allows you to decide at run time how much
space is needed.
Very useful with lists, stacks and queues.
 We do not have to worry about specifying an
upper limit to the size needed.
 We can customise our lists to fit the amount of
information that will be stored.
 We can expand and shrink the lists to respond to
additions and deletions

4
What do you need to do to reserve
memory dynamically?
You need a special sort of variable that holds an address
 A pointer is a variable that holds an address.
You must use a special type of declaration to create a pointer
variable.
 You need to know what sort of object will be created
 You need to use a special notation
E.g to create a pointer that contains an address of an integer
 int * x;
 The asterisk informs the compiler that x holds an address. And that
this will be an address of an integer.
You also need two C++ operators for dynamic memory allocation
 new and delete
5
Memory Pool
Every program is provided with a pool of
memory it can use during execution.
This is called the free store or heap
The size of this heap depends on your
system.
Local variables and function parameters
are stored in another pool called the
stack
6
To create an integer dynamically
1. #include <iostream.h>
2.
3. int main() {
4. int * x;
5. Create an integer
6. x = new int; dynamically
7.
8. *x = 8;
9. cout << “Address of x is “ << &x << endl;
10. cout << “Address stored in x is “ << x << endl;
11. cout << “Value stored at address “ << x << “ is “ << *x << endl;
12.
13. delete x;
14. return 0; delete from memory
15. }

7
Typical output: you will have different addresses!

Address of x is 0x0012FF7C
Address stored in x is 0x00300030
Value stored at address 0x00300030 is 8
Press any key to continue

8
Note
line 6: Allocation of memory
x = new int;
means grab enough memory for one integer from the heap and return its
address and store the address in x
line 13:
delete x;
free up the memory allocated for x for use by this and other programs.

9
Use of &.
Note
line 9: means address of
cout << “Address of x is “ << &x << endl;
means display the address of x
line 10:
cout << “Address stored in x is “ << x << endl;
displays what is stored in x. Since x is a pointer it too will be an address
Use of *.
Line 4: means x is a pointer
int * x;
Line 11: (*x) Dereferences pointer.
“at the address stored in” operator
cout << “Value stored at address “ << x << “ is “ << *x << endl;
Display the value “at the address stored in” x

10
What use is this?
We can grab any amount of memory from the heap
To grab enough memory for 100 integers all we need
is a pointer to hold one address (of an integer).
A request for memory for 100 ints using the new
operator.
new will grab contiguous space for 100 ints and
return the base address to the pointer

int *theData;
theData = new int[100];
This could be an expression. E.g. a variable. Suppose we had a data file
with an unknown number of records. A varaible nItems could be used to
count the number of records in the file. a block of memory could then
be allocated that can contain exaclty the records in the data files.
theData = new int[nItems]; 11
Another example
int *data;
cout << “Enter the number of items to be processed : ”;
cin >> nItems;
data = new int[nItems];

Note the use of square brackets. This looks like an array. Remember an array is a
contiguous block of memory. The array name holds the base address of that block
of memory.
An array name is a special kind of pointer!

The point is that once we allocate a block of memory dynamically we can treat the
pointer like an array.

See Demo 2
12
Dynamic structure Allocation
Suppose we have a declaration for a structure
struct myDataType {
char name[20];
char phoneNo[15];
float balance;
};

We can create a pointer to a structure.


myDataType * myPtr;

we can create a single object dynamically by

myPtr = new myDataType;

or a dynamically created array by

myPtr = new myDataType[100];

13
Accessing parts of a dynamically allocated structure
Normally to access fields of a structure we use the dot notation.
myDataType obj1;

cin >> obj1.name;


cin >> obj1.phoneNo
cin >> obj1.balance;

However if the structure was created dynamically we may be tempted to


access fields of the structure using the following syntax

myDataType *obj2;
obj2 = new myDataType;

cin >> *obj2.balance; // WRONG WILL NOT COMPILE!

to get it to work we would need to do

cin >> (*obj2).balance; //OK BUT YUCKY


14
SPECIAL SYNTAX FOR
Dynamic Structs and Classes
Because of the yucky syntax previously the C/C++ language
provide a more “natural” syntax to dereference dynamic structs and
classes.

cin >> obj2->name;


cin >> obj2->phoneNo;
cin >> obj2->balance;

15
Accessing parts of a dynamically allocated array of
structures
Warning: this is confusing!
However if we have an array of structures created dynamically we have to use
the normal syntax.
myDataType *obj2;

obj2 = new myDataType[5]; //reserve enough space for 5 myDataType objects

//initialise the first two structures


cin >> obj2[0].name;
cin >> obj2[0].phoneNo;
cin >> obj2[0].balance;

cin >> obj2[1].name;


cin >> obj2[1].phoneNo;
cin >> obj2[1].balance;

16
Passing a dynamically allocated atomic variable to a function
#include <iostream.h>

void ReadData(int *data);

int main() {
int *number;

number = new int; //created dynamically


ReadData(number); //pass by reference - pointer method
return 0;
} number contains an address
ReadData needs a parameter that
void ReadData(int *data) {
cin >> *data;
can store an address. data is a pointer
} so it can receive an address.
note to read a value in to the pointed
at address we use the dereference
operator. 17
Passing a dynamically allocated array to a function
This is exactly the same a passing a statically allocated array to a function
Example.

#include <iostream.h>

void ReadData(int data[], int n);

int main() {
int *number;
int nItems;

cout << "How many numbers are there to process? : ";


cin >> nItems;
number = new int[nItems]; //created dynamically

ReadData(number, nItems); //pass and use like a static array


return 0;
}

void ReadData(int data[], int n) {


int i;
for (i=0;i<n;i++)
cin >> data[i];
} 18
Passing a single structure to a function
//Supose we want a function that process a single structure.

#include <iostream.h>

struct myDataType {
char name[20];
int grade;
};

void ReadData(myDataType * rec);

int main() {
myDataType *newrecord;
DEMO5
newrecord = new myDataType; //created dynamically
ReadData(newrecord);

cout << newrecord->name << " " << newrecord->grade << endl;

delete record;
return 0;
}

void ReadData(myDataType *rec) {


cout <<" Enter a name : "; //NOTICE referencing of fields using ->
cin >> rec->name;
cout <<" Enter a grade : ";
cin >> rec->grade;
}

19
Passing an Array of structs to a function
#include <iostream.h>
#include <stdlib.h>

struct myDataType {
char name[20];
int grade;
};

void ReadData(myDataType data[], int n); DEMO 4


int main() {
myDataType *record;
int nItems;
int i;

cout << "How many numbers are there to process? : ";


cin >> nItems;
record = new myDataType[nItems]; //created dynamically
ReadData(record, nItems); //effectively record used like an array

for (i=0;i<nItems;i++)
cout <<record[i].name << " " << record[i].grade << endl;
return 0;
}

void ReadData(myDataType data[], int n) {


int i;
for (i=0;i<n;i++) {
cout << "Enter a name : ";
cin >> data[i].name;
cout << "Enter a grade : ";
cin >> data[i].grade;
}
} 20
Summary: How to use dynamic Arrays

Define a pointer variable of the chosen type: The


pointer variable will point to the dynamic array in
memory and will serve as the name of the dynamic
array
Call new: Creates the dynamic array. The size of the
array is given in the square brackets.
Use like an ordinary array
Call delete: when you have finished your program
before the final return call delete [] to free memory for
future use.

21
A Couple of Ideas to think about

NULL pointers
typedef

22
NULL
You often see NULL used in programs.
It is a special constant pointer value (a zero address) that can be
assigned to any sort of pointer.

int *x = NULL;

Why would you want to assign NULL to a pointer?


 Pointers are dangerous, they allow direct access to memory, any memory.
 It is common practice when creating a pointer to initialise it to NULL. This
can be changed e.g. via a new statement. But whenever you delete
memory it is good practice to reset a pointer back to NULL again.
 Also analogous to strings we can make use of the knowledge that a pointer
is set to NULL. This is especially true for linked lists.

23
typedef
You can define alternative names for existing types
 can aide readability of code
 is important for some dynamic data structures (linked lists)
E.g.
typedef int banana;
banana x; //variable x is a banana
//banana is an int
//same as int x;
OR More commonly to “clean up pointer declarations
typedef float * floatPtr;
floatPtr f1ptr,f2ptr; //f1prt and f2ptr are pointers to floats
24
Practical Application-Linked Lists

A dynamic list data structure created


using pointers
They grow and shrink according to
need.
Adding items to the list is sometimes
called insertion.
We have to specify all the operations
that we have for array based lists.
25
Nodes
We have seen that often useful data items
are structured using structs or arrays.
We can create special structures that contain
pointers to other structures. If the other
structure is the same type as itself.
We have a self referential data structure.
A self referential data structure is often called
a NODE

Yes this is a bit like explaining cricket to an


American! 26
A Node
struct Node { Note reference to a
node within node
int data;
Node *next; Note use of typedef to create an
alias data type pointer to node type.
}; Necessary for function prototypes that use
this sort of self referential structure

typedef struct Node * NodePtr;


NodePtr front = NULL;
NodePtr newNode = NULL;

27
After declaration of pointers

front NULL

newNode NULL

28
Insertion to list

newNode = new Node;


newNode->data = 10;
newNode->next = NULL

front NULL

data 10
newNode
next NULL NULL

29
Insertion to list

front = newNode;

front

data 0
newNode
next NULL NULL

30
Insertion to list

newNode = new Node;


newNode->data = 20;
newNode->next = NULL

data 10
front
next NULL NULL

data 20
newNode
next NULL NULL
31
front->next = newNode; Insertion to list
newNode = NULL

data 10
front
next NULL

data 20
next NULL NULL

newNode NULL
32
NodePtr cursor; Deletion from list (note
cursor = front; requires another pointer)

data 10
front
next NULL

cursor

data 20
next NULL NULL

newNode NULL
33
front = front->next; //deleting first node

data 10
cursor
next NULL

data 20
front
next NULL NULL

newNode NULL
34
delete cursor;
cursor = NULL;

temp
NULL

data 20
front
next NULL NULL

newNode NULL
35
Demo 6 and 7

36
Linked lists

They require very precise programming


and a high level of understanding of
manipulation of data by addresses.
Writing functions that manipulate linked
lists also requires a very clear
understanding of pointers.
More next week.

37

You might also like