ch01 - Data Structue and Algorithms - Intro - en
ch01 - Data Structue and Algorithms - Intro - en
Data Structures
and Algorithms
Course Outline
• Chapter 1: Introduction: Structures and
pointers
• Chapter 2: Algorithms complexity
• Chapter 3: Abstract data type: Arrays
• Chapter 4: Linked lists
• Chapter 5: Queues
• Chapter 6: Stacks
• Chapter 7: Trees
• Chapter 8: Heaps
2
Main References
• Principles of Data Structures using C and C++, Vinu V Das, New Age
International Ltd, 2006
• Algorithmes et structures de données génériques, Michel Divay,
DUNOD, 2ed, 2004
• Data Structures and Algorithm Analysis in C/C++ , by Mark Allen
Weiss, Addison Wesley
4
Chapter 1
Introduction: Structures and
Pointers
Data Structures and
Algorithms
5
Outline
• Structures
• Pointers
6
STRUCTURES
7
Introduction
• An array allows
– to designate with one name, a set of values with
the same type
– to access elements, we use indices
• A structure allows
– to designate with one name, a set of values with
different types
– to access elements, we use their names
8
Structure Declaration
• Declaration example:
struct record {
int number ;
int qt ;
float price ;
} ;
• The structure type is called record, and contain 3
fields: 2 of type int and 1 of type float
record item1, item2 ;
• It reserves 2 places in memory of type record:
one for item1 and another for item2
9
Structure fields usage
• The fields are manipulated as any variable.
• We use the operator « dot » (.)
• Examples
item1.number = 15 ;
cout << item1.price ;
cin >> item2.price ;
item1.number++
• The priority of “.” is very high.
10
Global usage of a structure
• The assignment operator “=“ is also used with the
structures
• Examples: item1 = item2 ;
• This gives
item1.number = item2.number ;
item1.qt = item2.qt ;
item1.price = item2.price ;
• The 2 structures should have the same type.
• We don’t use the operator “=“ when the stucture
contains string of characters (…)
11
Structure initialization
• A structure contains initially
– random values if it is local to a function
– zeros if it is global
• Example :
record item1 = {100, 285, 200 } ;
record item2=item1;
const record REF = {1, 10, 1.};
12
Structures nesting
1. Structure including arrays
2. Array of structures
3. Structures including other structures
4. Structure containing pointers (special case…)
13
Structure including arrays
• Structure declaration:
struct person {
char fname[30] ;
char lname [20] ;
float hours [31] ;
} ;
person employee, current ;
• The notation : employee.hours[4]
– Designate the 5th element of hours table of the employee
structure.
• The notation : &employee.hours[4]
– Designate the address of the 5th element of hours table of
the employee structure.
14
Array of structures
• Structure declaration:
struct point {
char name ;
int x ;
int y ;
} ;
point curve[50] ;
• The notations : (1) curve[i].x (2) curve[4]
– (1) designates the value of the field x of the ith element of
array curve.
– (2) represents the structure of type point that corresponds
to the 5th element of array curve
15
Structures including other structures
• Structures declarations :
struct date{ struct person {
int day ; char lname[30] ;
int month ; char fname [20] ;
int year ; float hours [31] ;
} ; date date_recruit ;
date date_post ;
} employee, current ;
• La notation : employe.date_recruit.year
– represent the year of recruitment corresponding to the
structure employee.
• We can write:
current.date_recruit = employee.date_post ;
16
The scope of a structure
17
POINTERS
18
Data types in C++
The C++ manipulates addresses using variables called pointers
pointer reference
enum
19
Pointers variables
• Declaration: DataType* var;
• Multiple declarations: DataType *var1, *var2, …;
• Examples
int * ad ;
int n ;
n = 20 ;
ad = &n ; //assign the address of n to ad
*ad = 30 ;// assign *ad the value 30, n becomes 30
• The variable ad
– is a pointer to integers, pointer of type int*
– Contains the address of an integer
• * is a unary operator that designates the content of an address
• * indicates that a variable is a pointer (in the declaration)
• *ad is an object with address ad, we say that we dereference the pointer
20
Pointers variables
• Representation of pointers
Address Variable
ad n 5000 5008 ad
20
30 5008 30 n
21
Motivation
• Why do we need address types (pointers):
– They can make a program more efficient
• in terms of execution time and memory usage
• e.g., dynamic memory allocation and removal of this
memory during running time
– this can replace static arrays and structures
• e.g., passing arguments to functions by pointer avoid
copying variables and give direct access to original data
– They are used to create more complex data
structure
• e.g., linked list, stacks and queues etc.
22
Some examples
int * ad1, * ad2, *ad ;
int n = 10, p = 20 ;
ad1 = &n ;
ad2 = &p ;
*ad1 = *ad2 + 2 ; //n = p + 2 ;
*ad1 += 3; //n = n + 3
(*ad1)++; //n++
N.B.
• cout<<*ad1++; it will derefence ad1 and display the
value*ad1, then it will increase the address ad1 by 1
• cout<<(*ad1)++; it will dereference ad1 and display it, then it
will increase (*ad1) by 1
23
Some examples (cont.)
• Remarks:
1. ad et *ad are lvalues, but &ad is not
2. int * ad ; reserves a memory place for a pointer
pointing to an integer, but it does not reserve
the integer.
24
Pointer incrementation
int * ad ;
ad++;
• ad contains the address of the next integer
(element) (i.e. the integer that is after *ad)
• In fact, the address is increased by sizeof(int)
bytes.
25
Pointer on a pointer
int
#include<iostream.h> n 44 int *
int main(){
int n=44; pn
cout << " n = " << n << endl; int **
cout << " &n = " << &n << endl; ppn
int* pn=&n; // pn contains the address of n
cout << " pn = " << pn << endl;
cout << " &pn = " << &pn << endl; n = 44
cout << " *pn = " << *pn << endl; &n = 0x22ff44
int** ppn=&pn; // ppn contains the address of pn pn = 0x22ff44
cout << " ppn = " << ppn << endl; &pn = 0x22ff40
cout << " &ppn = " << &ppn << endl; *pn = 44
cout << " *ppn = " << *ppn << endl; ppn = 0x22ff40
cout << "**ppn = " << **ppn << endl; &ppn = 0x22ff3c
return 0; *ppn = 0x22ff44
} **ppn = 44
26
Passing argument to a function
• We have three modes of passing arguments
1. Passing arguments by value
2. Passing arguments by reference
3. Passing argument by address with pointers
27
Passing arguments by value
before call : 10 20
#include <iostream.h> start swap : 10 20
void swap (int , int ) ; end swap : 20 10
after call : 10 20
int main(){
int n=10, p=20 ;
cout << " before call:" <<n<<" "<<p<<"\n" ;
swap (n, p) ;
cout << “after call:"<<n<<" "<<p<<"\n" ;
return 0;
}
void swap (int a, int b){
int tmp ;
cout << " start swap : "<<a<<" "<< b<<"\n" ;
tmp = a ;
a = b ;
b = tmp ;
cout << " end swap : "<<a<<" "<<b<<"\n" ;
} 28
Passing arguments by reference
before call: 10 20
#include <iostream.h> start swap : 10 20
void swap (int &, int &) ; end swap : 20 10
int main(){ after call : 20 10
int n=10, p=20 ;
cout << "before call:"<<n<<" "<<p<< "\n" ;
swap (n, p) ;// attention, ici pas de &n, &p
cout << "after call:"<<n<<" "<< p << "\n" ;
return 0;
}
void swap (int & a, int & b)
{ int tmp ;
cout << “start swap:"<<a<<" "<< b << "\n" ;
tmp = a ; a = b ; b = tmp ;
cout << "end swap :"<<a<<" "<< b << "\n" ;
} 29
Passing argument by address with
pointers
#include <iostream.h>
void swap (int *, int *) ;
int main(){
int a=10, b=20 ;
cout << "before appel : " << a << " " << b << "\n" ;
swap (&a, &b) ;
cout << “after call : " << a << " " << b << "\n" ;
return 0;
}
void swap (int *ad1, int *ad2)
{ int tmp ;
tmp = *ad1 ;
*ad1 = *ad2 ;
*ad2 = tmp ;
}
before call: 10 20
30
after call: 20 10
Remark
• The prototype of the swap function can be
written as follows:
void swap (int * const ad1, int * const ad2)
– * const ad1 is of type int,
– ad1 is then a constant address pointing to an integer,
i.e. a constant pointer.
• i.e. the address or pointer cannot be changed
• If we had:const int * ad1
– int * ad1 is a constant, and then:
– ad1 is a pointer to a constant integer
• i.e. we cannot change the integer value pointed by ad1
31
Passing a structure as argument to a
function
• Passing structure by value
• Passing structure by reference
• Passing the address of a structure and
operator « -> »
32
#include <iostream>
using namespace std ;
Passing structure by value
struct record {// global scope
int a ;
float b ;
} ; before calling fct : 1 12.5
main() in fct : 0 1
{ record x ; returning to main : 1 12.5
void fct (record y) ;
x.a = 1 ; x.b = 12.5 ;
cout << "before calling fct : "<< x.a <<" "<< x.b <<
"\n" ;
fct (x) ;
cout << "returning to main : " << x.a << " " << x.b ;
}
36
Returning a structure value from a
function
record fct (...)
{
record s ; /* local structure to a fct */
.....
return s ; /*the function returns the
value of the structure */
}
37
The name of an array is a constant
pointer
int t[10]
• t is equivalent to &t[0]
• t is a constant pointer to integers
• The following notations are the same
t+1 same as &t[1]
t+i same as &t[i]
t[i] same as *(t+i)
• These are two ways to store the value 1 to each
of 10 elements of the array t
38
The name of an array is a constant
pointer
• These are some examples to store the value 1 to each of 10
elements of the array t
int i ; int i ;
for (i=0;i<10;i++) int *p ://variable pointer
for (p=t, i=0 ; i<10 ; i++, p++)
*(t+i) = 1 ; *p = 1 ;
Remark: we cannot do t++ cout<<p[2]; //correct
39
Null Pointer
• A null pointer
– points on nothing
– has a value 0
– is a constant pointer
• int *ptr; ptr=0; // or ptr=NULL;
– NULL is a predifined constant in files cstdio and
cstddef
• It is very important to insure that the pointer
points somewhere known before using it (or it is
null)
40
Dynamic allocation:
operators new and delete
• We distinguish between static and automatic data:
1. static data exists during the lifetime of the program and lasts
when it ends
2. automatic data exists only during the lifetime of a bloc or a
function
• A new category of data is allocated dynamically
• Dynamic allocation of memory is done in a specific region
in memory called heap (or free store).
• The allocation (i.e. reservation) is done using the operator
new
• The deallocation (i.e. releasing) of this memory is only done
with the operator delete
• Even after leaving a function where the allocation is done,
the allocation persists if we don’t use delete
41
Operator new
ad
• Example 1 ?
int *ad ; ad = new int;//or
int *ad = new int ; 12
*ad = 12;
• Allocate the necessary memory for one element of type int, and
• Assign to ad the corresponding address
adc
• Example 2 ? ? … ?
char *adc ;
adc = new char[100] ;
• Allocate the necessary memory for an array of 100 characters, and
• Put the starting address in adc
42
Syntax and role of new
• Syntax of new:
– new type
– new type[n]
• n can be a variable or a constant
– new type [n] [MAX]; #e.g.: define MAX 4
• A preferred method to declare an array of 2 dimensions (n and m
are two variables)
int **a=new int*[n];
for(int i=0;i<n;i++)
a[i]=new int[m];
• Another method: (n is constant and m is a variable)
const int n = 3;
int *ptr[n];
for(int i=0;i<n;i++)
ptr[i]=new int[m];
43
Operator delete
• Deallocate allocated memory
• Is only applied to pointers with values obtained
from the operator new.
• Does not eliminate the pointer itself but the
value pointed by this pointer
• Example
delete ad ; // ad was a pointer on a variable
delete adc ; // delete [] adc
//adc was a pointer on an array
• Syntax: delete address
44
Remarks
• The main usage of pointers is to manipulate
dynamic allocated variables
• The main reason for dynamic allocation is to
save memory space
– the space is allocated only from the time we
execute the instruction with new
– the space is deallocated when we don’t need it
• it is possible to reach a case where we lack from heap
memory
45
Internal structure of a process
• A process is a running program
stack
• It is constituted with 4 parts in
memory:
– code: the binary code of the
program
– data: contain global variables
– heap: for dynamic allocation using heap
the new operator
– stack: contains temporary data (e.g. data
to manage the usage of functions:
code
local variables, arguments, returning
point address from function)
46
Examples
Example Example reviewed
int* ptr1 = new int; int* ptr1 = new int;
int* ptr2 = new int; int* ptr2 = new int;
*ptr2 = 44; *ptr2 = 44;
*ptr1 = *ptr2; *ptr1 =*ptr2;
ptr1 = ptr2; delete ptr1; //avoid Inaccessible.
object
delete ptr2; ptr1 = ptr2;
delete ptr2;
ptr1 = NULL; //avoid dangling
pointer
ptr2 = NULL;
48
#include <iostream> Uing namespace std;
int BinarySearch(int *ptab, int size, int val){ int mid, left=0,
right=size ;
while(left<right){
mid=(left+right)/2;
if(val==ptab[mid])
return mid;
else if(val < ptab[mid])
right=mid;
else
left=mid+1;
}
return -1; 43
}
int main(){
int n,val; int
ind;
cout<<"Read the nber of elements :"<<endl;
cin>>n;
int *ptr=new int[n];
cout<<"Read the n ele. of
tab:"<<endl;
for(int i=0;i<n;i++) cin>>ptr[i];
cout<<"Read the ele. to search
for"<<endl; cin>>val;
ind=Find(ptr,n,val);
//ind=BinarySearch(ptr,n,val);
if(ind!=-1)
cout<<"The ele. is found at the index "<<ind<<endl;
else
cout<<"The ele is not found!"<<endl;
delete
ptr;
return 0;
}
44
Exercise Structure
Exercise
A student is defined by :
• last name
• first name
• age
• address
• GPA
Write a program that:
1. Reads the data of a student
2. Reads the data of n students (n<=20), in an array of structures
3. Displays the information of a student knowing his last and first name
4. Displays the average of GPA for all students
5. Displays the students with GPA < 3
6. Swap the place of the first and the last students
7. Sort the array in ascending order of GPA
• struct Student{
• char lname[20];
• char fname[20];
• int age;
• char address[40];
• float gpa;
• };
• readNinfo(ast,N);
• stdInfo=searchInfo(ast, N);
• displayInfo(stdInfo);
• cout<<"Aver GPA: "<<averGPA(ast, N)<<endl;
• searchGPA(ast, N);
• cout<<"Swap the first and the last Student..."<<endl;
• swap(ast[0], ast[N-1]);
• displayNinfo(ast,N);
• cout<<"sorting Students by GPA"<<endl;
• sort(ast,N);
• displayNinfo(ast,N);
• return 0; 53
Solution
• void readInfo(Student *st){
• cout<<"Input Student Info"<<endl;
• cout<<"Fname Lname: ";
• cin>>st->fname>>st->lname;
• cout<<"Age: "; cin>>st->age;
• cout<<"Address: "; cin>>st->address;
• cout<<"GPA: "; cin>>st->gpa;
• }
54
Solution
• void displayInfo(Student *st){
• cout<<"Info of Student"<<endl;
• cout<<"Fname Lname: ";
• cout<<st->fname<<" "<<st->lname<<endl;
• cout<<"Age: "; cout<<st->age<<endl;
• cout<<"Address: "; cout<<st->address<<endl;
• cout<<"GPA: "; cout<<st->gpa<<endl;
• }
55
Solution
• Student *searchInfo(Student *ast, int N){
• Student *stdInfo;
• char fname[20],lname[20];
• cout<<"Input Student fname and lname: ";
• cin>>fname>>lname;
• for(int i=0; i<N; i++){
• if(strcmp(fname,ast[i].fname)==0 && strcmp(lname,ast[i].lname)==0){
• stdInfo=&ast[i];
• return stdInfo;
• }
• }
• }
58