Data Structure
Department of Computer Science and Software
Engineering
Capital University of Sciences & Technology,
Islamabad Pakistan
1
What is Data structure??
Why do we need data structures?
Lecture 1
Introduction
Course overview, Pointers, Dynamic Memory
allocation Need of Data Structures, Single
dimensional Static and Dynamic arrays,
Multi-Dimensional Static and Dynamic Arrays
3
Outline
Pointers, Dynamic Memory allocation
What is the need of array?
Variable vs array
Fundamental data types
What is the array, types of array
How array can be declared and initialized
How data is to be presented in memory
Memory representation of array
Pointer
Points to an item
Holds the memory address of the item
Has its own memory storage
Occupies space in memory
Hence can itself be accessed too
Allows C/C++ to support dynamic memory allocation
If x contains the address of y, x is said to “point to” y
Pointer variables are declared as
type *var-name;
e.g. int *p; pointer p contains the memory address of an int
variable
float *fl; points to a float variable
Assumptions
characters are one byte in length
integers are four bytes long
floats are four bytes long
doubles are eight bytes long
Pointer Operators
& address of
* value at address
&a address of variable a
*p contents of location pointed to by variable
p
Pointer Operators
• & (address operator)
– a unary operator that returns the memory address of its
operand.
int balance = 350;
int *balptr;
balptr = &balance;
• This address is the location of the variable in memory,
it has nothing to do with the value of balance.
Pointer Operators
• * (indirection operator)
– Is the complement of &.
– It is a unary operator that returns the value of
variable located at address specified by its operand.
int balance = 350;
int *balptr;
balptr = &balance;
int value;
value = *balptr;
// what does value contain?
Pointers
int a=1, b=2, *p;
Picture in memory at this point:
a b p
1 2 ?
p=&a; //p is assigned the address of a
a b p
1 2
b=*p; //b is assigned the value pointed to by p
As p points to a, the statement b=*p is equivalent to b=a
a b p
1 1
Pointer Operators
int main()
{
int balance;
int *balptr;
int value;
balance = 3200;
balptr = &balance;
value = *balptr;
cout << "balance is: " << value << '\n';
cout << "Memory address where balance is stored is: ”
<< balptr << endl;
return 0;
}
Output
balance is: 3200
Memory address where balance is stored is:
0012FF7C
(Note memory address may be different when you
run it on your machine)
Base Type
value = *balptr;
• The compiler transfers the proper number of
bytes according to base type.
int *p;
double f;
// ...
p = &f; // ERROR
Assigning Values Through a Pointer
int *p;
int x = 12;
p=&x;
cout << x << endl;
//Assign a value to the location pointed to by p
*p = 101;
cout << x << endl; //what is value of x?
cout << *p << endl;
cout << p << endl;
cout << &x << endl;
Assigning values through a pointer
12
101
101
0012FF78
0012FF78
Assigning Values Through a Pointer
(*p)++; //increment value to the location pointed to by p
int main()
{
int *p, num;
p = #
*p = 454;
cout << num << ' ';
(*p)++; /* parentheses are necessary because * operator
has lower precedence than ++operator */
cout << num << ' ';
(*p) - -;
cout << num << '\n';
return 0;
} //Output?
Assigning Values Through a Pointer
//Output is 454 455 454
Dynamically Allocated Memory
Pointer variables Stack
& the heap
Pointer Variables
a pointer is a variable which holds the
address of something else
called indirect addressing
.
pointer
what is pointed to
a value of
some type
Some Uses of Pointer Variables
dynamically (run-time) allocated arrays
linked data structures
linked lists
"lifetime" of a variable
is a run-time concept
period of time during which a variable has memory
space associated with it
begins when space is allocated
ends when space is de-allocated
three categories of "lifetime"
static - start to end of program execution
automatic (stack) - start to end of declaring function's
execution
heap - starts with "new"; ends when:
C++: "delete" statement executed
Data memory model
static data space for global variables
run-time stack - activation records
automatic data
added and removed as program runs
(expands and shrinks in an orderly
LIFO manner)
space for variables allocated
heap data at run-time using "new" (allocation
and de-allocation requests occur in
unpredictable order)
Heap Variables
are accessed indirectly via a pointer variable
memory space is explicitly allocated at run-time
(using new)
space is allocated from an area of run-time memory
known as the heap
in C++ space must be explicitly returned (using
delete) to avoid “memory leak”
C++ programmers are responsible for memory
management
Declaring Pointer Variables
syntax
<data type> * <pointer name>;
C++ pointers are typed
some examples
int * intPointer;
intPointer and
float * floatPointer;
floatPointer are
automatic
variables
Assigning a value to a pointer
variable
the value of a pointer variable is a memory address
assign address of an existing variable
int number;
intPointer = &number;
use "new" to allocate space in the heap
intPointer = new int;
address of heap memory space allocated becomes the value
of the pointer variable
heap memory
intPointer
?
Dereferencing
heap variables do not have a name of their own
are anonymous variables
*intPointer refers to the value pointed to by intPointer
intPointer is the finger; *intPointer is the moon
what happens?
intPointer = 36;
*intPointer
*intPointer = 36;
(*intPointer)++; intPointer
cout << *intPointer;
intPointer = null;
Returning Heap Space
done by using the delete statement
syntax
delete <pointer variable>;
example
float * fPointer = new float;
cin >> (*fPointer);
------
delete fPointer;
Pointers - Summary
a pointer variable holds a memory address and can
be used to create and access dynamic variables
dynamic (heap) variables are explicitly created at
run-time (using new)
memory for dynamic variables is allocated in an area
of memory called the heap
space used for dynamic variables needs to be freed
(using delete) to avoid memory leaks
Dynamic Allocation
What is wrong here?
int *xptr = new int;
*xptr = 73;
int *x2ptr;
*x2ptr=65;
Dynamic Allocation
int *xptr = new int;
*xptr = 73;
int *x2ptr;
x2ptr = xptr;
*x2ptr = 65;
Dynamic Allocation
//What is wrong here?
int *xptr = new int;
*xptr = 73;
int *x2ptr = new int;
x2ptr = xptr;
*x2ptr = 65;
//serious issue!!!
Dynamic Allocation
int *myptr = new int(73);
cout << *myptr;
delete myptr;
//declaring and initializing int
Arrays in Data Structure
An array is a collection of more then one data items
or elements of same datatype in contiguous
memory (one after another) e.g. list of names, list of scores
Easier way to compare and use data than having
separate variables for data elements
data_type identifier[size]
int arr[3]
declares a one-dimensional array named arr with space
for 3 integer variables
Variables contiguous in memory; lowest address
has first value, next address has second variable
value, and so on
Arrays
• An array is an indexed data structure
• An array stores a collection of variables
• All variables stored in an array are of the same
data type
• An individual variable within an array is called an
element of the array
• An element of an array is accessed using the array
name and an index
• The name of the array is the address of the first
element. The index is the offset
Declaring an array
data_type array_name[size];
– allocates memory for size variables
– index of first element is 0
– index of last element is size-1
– size must be a constant
Arrays
An individual variable within an array is called an
element of the array
The elements of an array are not named, and
are accessed by the array’s name and their
position in the array (indexing)
Index of first element is zero, index of last
element is size-1 e.g. int arr[3] has variables
arr[0], arr[1] and arr[2]
size has to be a positive constant (not variable)
i.e. can’t do: int x = 3; int arr[x];
but can do: int arr[3 * 2];
Number of bytes reserved with int arr[3]; ?
Declaring an Array
• Example: int list[10];
– allocates memory for 10 integer variables
– index of first element is 0
– index of last element is 9
– C++ does not perform any bounds checking on arrays
list[0]
list[1]
list[9]
Arrays
Arrays offer convenient means of grouping
together several related variables
One- dimensional arrays
type var_name[size]
int sample[10];
double d[30];
char ch[100];
Arrays in Data Structure
Array is can be initialized by two ways;
One when it is declared (Static initialization)
int arr[3] = {15, 25, 3};
Equal or Less not more elements
Run time initialization
Using loop or functions
Initializing Arrays
Arrays can be initialized at the time they are
declared.
Examples:
double taxrate[3] = {0.15, 0.25, 0.3};
char word[] = “hello”;
char list[5] = {‘h’,’e’,’l’,’l’,’o’};
//list of characters, not a string
double vector[100] = {0.0}; //assigns zero to all 100 elements
Initializing Arrays
float f[5]={0.0, 1.0, 2.0, 3.0, 4.0};
// initializes f[0] to 0.0, f[1] to 1.0…f[4] to 4.0
Or
float f[5]; f[0]=0.0; f[1]=1.0; …
int a[10]={2}; //rest initialized to zero
cout << a[0]<< endl << a[5] << endl;
If no size given, allocates as much as the no. of initializers
e.g. int a[] = {5, 2, -9}; // and
int a[3] = {5, 2, -9}; // are equivalent
Can’t do: int hand[2]; hand[2]={5, 9};
Can’t do: short y[2]={1,2,3,4};
Don’t confuse: short b[4] and b[4]
Initializing Arrays
for loops used to initialize arrays
#include <iostream.h>
int main()
{
int t, sample[10]; // this reserves 10 integer
elements
// load the array
for(t=0; t<10; ++t)
sample[t]=t;
// display the array
for(t=0; t<10; ++t)
cout << sample[t] << ' ';
return 0;
}
Initializing Arrays
int a[5];
Now an indexed variable like a[1] can be used anywhere that a variable of
type int can be used
int a[5];
cin >> a[4] >> a[2];
cout << a[2] << “ “ << a[4] << endl;
cin >> a[3] >> a[0];
int max; max = a[3] + a[0]; cout << max << endl;
int next; cin >> next;
a[1]= next; cout << a[1] << endl;
a[3]= 42; cout << a[3] << endl;
int student = 2;
a[student] = 99;
cout << a[student] << “ “ << a[2] << endl;
Also: a[get_index())] = 3; if get_index() returns an int
//Reads in 5 scores, displays max_score and shows
//how much each score differs from max_score
int main()
{
const int SIZE = 5;
int i, score[SIZE], max_score;
cout << “Enter “ << SIZE << “ scores: \n”;
cin >> score[0];
max_score = score[0];
for (i=1; i<SIZE; i++)
{
cin >> score[i];
if (score[i] > max_score)
max_score=score[i];
}
cout << “The highest score is: “ << max_score << endl
<< “Scores & their difference from highest: \n”;
for (i=0; i<SIZE; i++)
{
cout << score[i] << “ off by “
<< (max_score – score[i]) << endl;
}
return 0;
}
Initializing Arrays
Useful to give a constant name to the size of array
/*const type modifier*/
const int NUM_EMPLOYEES = 10;
int salaries[NUM_EMPLOYEES];
for (int i=0; i < NUM_EMPLOYEES; i++)
cin >> salaries[i];
Advantage? Why not use a variable name?
Another way:
# define NUM_EMPLOYEES 10
And yes, sizeof(salaries); gives what?
Arrays
• Total size of an array in bytes?
• Total bytes =
number of bytes in type * number of elements
• e.g. int sample[10];
• Has size in bytes = 10 * sizeof(int)
Initializing Arrays
• What is wrong with the following?
int num=10;
int iarray[num];
int size;
cin >> size;
int myarray[size];
double darray[5]={3.2, 4.5, 6.7, 324.0, 45.8, 23.1, 34.9}
Assigning One Array to Another
int a[10], b[10];
// ...
a = b; // error -- illegal
/*So how do we make the contents of one array
same as the other?*/
Assigning One Array to
Another
int a[5], b[5];
// ...
a = b; // error – illegal
Cannot assign one array to another; each element must
be copied individually
const int ARRAY_SIZE = 5;
int a[] = {10, 11, 12, 13, 14};
int main()
{
int b[ARRAY_SIZE];
for (int i=0; i < ARRAY_SIZE; ++i)
b[i] = a[i];
return 0;
}
Assigning Values to an Array
•Example
int list[10];
int count;
cin >> count;
for(int i=0; i<count; i++)
cin >> list[i];
What if count >9?
Summarize Arrays
• In C++ all arrays are stored in contiguous memory
locations
• An individual element is accessed by use of an index.
• An index describes the position of an element within
an array.
• In C++ all arrays have zero as the index of their first
element.
Arrays: Min Max
int main()
{
const int SIZE = 10;
int i, min_value, max_value;
int list[SIZE];
for(i=0; i<SIZE; i++)
{
list[i] = rand();
cout<<list[i]<<" ";
}
Arrays
// find minimum value
min_value = list[0];
for(i=0; i<SIZE; i++)
{
if (min_value>list[i])
{
min_value = list[i];
}
}
cout << "minimum value: " << min_value << ‘\n’;
Arrays
// find maximum value
max_value = list[0];
for(i=0; i<SIZE; i++)
{
if (max_value<list[i])
{
max_value = list[i];
}
}
cout << "maximum value: " << max_value << '\n';
return 0;
} // end of main function
Arrays - No Bounds Checking
// An incorrect program. Do Not Execute!
int main()
{
int crash[10], i;
for(i=0; i<100; i++)
crash[i]=i;
return 1;
}
Sorting an Array
• Lots of applications require sorting
• Algorithm for sorting
int main(void) Sorting an
{
const int SIZE = 10; Array
double darray[SIZE] = {34, 5.6, 0.9, 345.7, 54.1, 23.5, 2.5, 6.78, 12.4, 13.9};
int i, j;
for (i=0; i<SIZE-1; i++)
{
for (j=i+1; j< SIZE; j++)
{
if (darray[i]>darray[j])
{
double temp;
temp = darray[i];
darray[i] = darray[j];
darray[j] = temp;
}
}
} //inplace sorting ?
return 0;
}
Sorting an Array
// Using the bubble sort to order an array.
int main()
{
const int SIZE = 10;
int nums[SIZE];
int a, b, t;
// give the array some random initial values
for(t=0; t<SIZE; t++)
nums[t] = rand();
Sorting an Array
// This is the bubble sort.
for(a=1; a<SIZE; a++)
{
for(b=SIZE-1; b>=a; b--)
{
if (nums[b-1] > nums[b])
{ // if out of order exchange elements
t = nums[b-1];
nums[b-1] = nums[b];
nums[b] = t;
}
}
} // This is the end of the bubble sort.
} // end of main program
Two Dimensional Arrays
• C++ supports multi-dimensional array
– data_type array_name[ROW_SIZE][COLUMN_SIZE]
– int matrix[3][4];
row[0]
row[1]
row[2]
in memory
row1 row2 row3
Accessing Array Elements
• int matrix[3][4];
– matrix has 12 integer elements
– matrix[0][0] element in first row, first column
– matrix[2][3] element in last row, last column
Two Dimensional Arrays
int main()
{
const int ROWS = 3;
const int COLS = 4;
int i, j, num[ROWS][COLS];
for(i=0; i<ROWS; ++i)
{
for(j=0; j<COLS; ++j)
{
num[i][j] = (i*COLS)+j+1;
cout << num[i][j] << “\t“;
}
cout << “\n”;
}
return 0;
} // output?
Output:
1 2 3 4
5 6 7 8
9 10 11 12
Two Dimensional Arrays
What happens if I change [3][4] to [2][6]?
int main()
{
const int ROWS = 3;
const int COLS = 4;
int i, j, num[ROWS][COLS];
for(i=0; i<ROWS; ++i)
{
for(j=0; j<COLS; ++j)
{
num[i][j] = (i*COLS)+j+1;
cout << num[i][j] << “ “;
}
cout << “\n”;
}
return 0;
} // output?
Output:
1 2 3 4 5 6
7 8 9 10 11 12
Multidimentional Arrays
type name[size1][size2] . . . [sizeN];
int multidim[4][10][3];
when multidimensional arrays are used,
large amounts of memory are consumed.
Multidimensional Array Initialization
int sqrs[10][2] = {
1, 1,
2, 4,
3, 9,
4, 16,
5, 25,
6, 36,
7, 49,
8, 64,
9, 81,
10, 100
};
Multidimensional Arrays
int main(void)
{
const int ALPHABETS = 26;
char code[ALPHABETS][2] =
{
{'a', 'f'}, {'b', 'w'}, {'c', 'x'},
{'d', 'v'}, {'e', 's'}, {'f', 'r'},
{'g', 'q'}, {'h', 'c'}, {'i', 'g'},
{'j', 'h'}, {'k', 'e'}, {'l', 'u'},
{'m', 'b'}, {'n', 'j'}, {'o', 'd'},
{'p', 'k'}, {'q', 't'}, {'r', 'l'},
{'s', 'm'}, {'t', 'n'}, {'u', 'a'},
{'v', 'o'}, {'w', 'p'}, {'x', 'z'},
{'y', 'i'}, {'z', 'y'}
};
Multidimensional Arrays
int i;
char alpha;
cout << "Enter an alphabet: ";
cin >> alpha;
for(i=0; i< ALPHABETS; i++)
{
if(code[i][0]==alpha)
{
cout << "The code of " << alpha
<< " is ";
cout << code[i][1]<<endl;
break;
}
}
return 0;
} // end of main program
C++ automatic array
int entry [31]; value has to be
known at compile time
entry
34 45 15 ---------- 36
0 1 2 ----------- 30
entry[0] = = *entry NO HEAP MEMORY
SPACE IN USE!
C++ dynamic arrays
can use dynamic memory allocation to postpone
decision about array capacity until run-time
array space will be on the heap
pointer to array's beginning is not on the heap
float * dynArray; // declare pointer only
dynArray = new float [max]; // max is a variable
// use of dynamic array the same as use of an automatic array
delete [ ] dynArray; // free heap space
Dynamic Allocation
const int SIZE = 10;
double *ptr = new double[SIZE]; /*10 element array*/
int i;
for (i=0; i<SIZE; i++)
{
ptr[i] = 2.0*i;
}
for (i=0; i<SIZE; i++)
{
cout << ptr[i] << endl;
}
delete []ptr;
Array of Pointers
const int RSIZE = 4;
A two dimensional
const int CSIZE = 6; array of
int * iarray[RSIZE]; RSIZE*CSIZE
for(int k=0; k<RSIZE; k++) 012345
iarray
{ 0
iarray[k] = new int [CSIZE]; 1
if (iarray[k] == NULL) 2
{ 3
cerr << “Memory Allocation Error…\n”;
cerr << “Exiting …\n”;
exit(-1);
}
}
Double and Tripple Pointers
int a = 20;
int *ip = &a; 300 200 100 20
int **ipp = &ip; ippp ipp ip a
int ***ippp = &ipp; 400 300 200 100
cout << a << endl; 20
cout << ip << *ip << endl; 100 20
cout << ipp << *ipp << **ipp << endl; 200 100 20
cout << ippp << *ippp << **ippp << ***ippp << endl;
300 200 100 20
Dynamic Array of Pointers
const int RSIZE = 4;
A two dimensional
const int CSIZE = 6; array of RSIZE*CSIZE
int ** matrix;
matrix = new int * [RSIZE]; matrix 012345
for(int k=0; k<RSIZE; k++) 0
{ 1
matrix[k] = new int [CSIZE]; 2
if (matrix[k] == NULL) 3
{
cerr << “Memory Allocation Error…\n”;
cerr << “Exiting …\n”;
exit(-1);
}
}