Download Stacks and Queues Dynamic memory allocation

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Linked list wikipedia , lookup

Array data structure wikipedia , lookup

Transcript
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




May only use first few spaces. Rest is wasted
OR
E.g. an array of 5 integers


int A[500];
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.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
#include <iostream.h>
int main() {
int * x;
x = new int;
*x =
cout
cout
cout
Create an integer
dynamically
8;
<< “Address of x is “ << &x << endl;
<< “Address stored in x is “ << x << endl;
<< “Value stored at address “ << x << “ is “ << *x << endl;
delete x;
return 0;
delete from memory
}
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 &.
line 9: means address of
Note
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;
ReadData(number);
return 0;
}
void ReadData(int *data) {
cin >> *data;
}
//created dynamically
//pass by reference - pointer method
number contains an address
ReadData needs a parameter that
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
17
operator.
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);
DEMO5
int main() {
myDataType *newrecord;
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 : ";
cin >> rec->name;
cout <<" Enter a grade : ";
cin >> rec->grade;
}
//NOTICE referencing of fields using ->
19
Passing an Array of structs to a function
#include <iostream.h>
#include <stdlib.h>
struct myDataType {
char name[20];
int grade;
};
DEMO 4
void ReadData(myDataType data[], int n);
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 << "
return 0;
" << record[i].grade << endl;
}
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 {
int data;
Node *next;
};
Note reference to a
node within node
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
newNode
NULL
data
10
next
NULL
NULL
29
Insertion to list
front = newNode;
front
newNode
data
0
next
NULL
NULL
30
Insertion to list
newNode = new Node;
newNode->data = 20;
newNode->next = NULL
front
newNode
data
10
next
NULL
data
20
next
NULL
NULL
NULL
31
front->next = newNode;
newNode = NULL
front
newNode
Insertion to list
data
10
next
NULL
data
20
next
NULL
NULL
NULL
32
NodePtr cursor;
cursor = front;
front
Deletion from list (note
requires another pointer)
data
10
next
NULL
cursor
newNode
data
20
next
NULL
NULL
NULL
33
front = front->next;
cursor
front
newNode
//deleting first node
data
10
next
NULL
data
20
next
NULL
NULL
NULL
34
delete cursor;
cursor = NULL;
temp
front
newNode
NULL
data
20
next
NULL
NULL
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