Vous êtes sur la page 1sur 16

Exemples

de questions aux examens



1. Dterminez lordre de croissance du temps dexcution des algorithmes suivants, en fonction
de n, en utilisant la notation asymptotique. Justifiez vos rponses.

for(int i=1; i<= n, ++i)
{

for(int j=1; j <= 5n*n; j++)

{ }
}
-----------

void f(int n)
{

for(int i=0; i<5340*n; i++)


cout << i << endl;
}
-------------

for(int i=1; i<= n, ++i)
{

for(int j=1; j <= i ; j++)

{ }
}

int i = n;
while (i > 0)
{
i = i/2;
}




2. Soit un entier naturel n. Considrez les fonctions de n suivantes.

a) n log2(n)
b) n1/2
c) 22n
d) n ln(n) + 5n
e) 2n

Comparer les ordres de croissance de ces fonctions et les ordonner du plus faible ordre
de croissance au plus grand. Dans votre rponse, crivez O(f(n)) O(g(n)) lorsque

lordre de croissance de f(n) est strictement plus petit que celui de g(n); crivez O(f(n))
= O(g(n)) si les ordres de croissance de g(n) et f(n) sont identiques. Vous devez justifier
votre rponse en utilisant le thorme sur les limites (et, possiblement, la rgle de
lHpital).

3. Dterminez le temps dexcution de la fonction suivante en pire cas et en meilleur cas en
fonction de la taille de x (son nombre dlments). Pour cela, identifiez une opration
baromtre et exprimez votre rponse en utilisant la notation asymptotique. Vous devez
justifier votre rponse.

void tri(std::vector<int> & x)
{
for (unsigned int i = x.size()-1; i > 0; i--)
{
unsigned int pMax = i;
for (unsigned int j = 0; j < i; j++)
{
if (x[j] > x[pMax]) pMax = j;
}
int temp = x[i];
x[i] = x[pMax];
x[pMax] = temp;
}
}


4. Dterminez le temps dexcution de lalgorithme suivant en fonction de n. Exprimez votre
rponse en utilisant la notation asymptotique. Vous devez justifier votre rponse.

void f(int n)
{
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
cout << i << j << endl;
for(int i=0;i<n;i++)
cout << i << endl;
}

5. Dterminez le temps dexcution de lalgorithme suivant en fonction de n. Exprimez votre


rponse en utilisant la notation asymptotique. Vous devez justifier votre rponse.

int i=3;
while(i < n)
{
i *= 5;
}

6. Dterminez le temps dexcution de la fonction suivante, en pire cas et en meilleur cas, en


fonction de la taille du vecteur a (son nombre dlments). Pour cela, identifiez une opration

baromtre et exprimez votre rponse en utilisant la notation asymptotique. Vous devez


justifier votre rponse. On suppose que le vecteur a est tri avant lappel de cette fonction.
int findElement( const std::vector<int> & a, const int & x )
{
int min = 0;
int max = a.size( ) - 1;
while( min <= max )
{
int milieu = ( min + max ) / 2;
if( a[ milieu ] < x ) min = milieu + 1;
else if( x < a[ milieu ] ) max = milieu-1;
else return milieu;
}
return -1;
}

7. Considrez le patron de classe suivant que vous avez tudi en laboratoire (seul le prototype
est visible ici):

template<typename T>
class Vector {
public:
explicit Vector(int = 0);
Vector(const Vector &);
~Vector();
Vector &operator=(const Vector &);
void resize(int, T = T());
void reserve(int);
bool empty() const;
int size() const;
int capacity() const;
T &operator[](const int &);
const T &operator[](const int &) const;
T &at(const int &);
const T &at(const int &) const;
void push_back(const T &);
T pop_back();
const T &back() const;
void clear();
typedef T * iterator;
typedef const T * const_iterator;
iterator insert(iterator, const T &);
iterator begin();

const_iterator begin() const;


iterator end();
const_iterator end() const;
private:
int m_size; /*!<Taille d'un vector*/
int m_capacity; /*!<Capacit d'un vector*/
T *m_objects; /*!<Pointeur pour le dbut d'un tableau dynamique*/
};

a) Quel est lutilit davoir template<typename T> ?


b) Quel est le rle de lattribut m_size? quoi peut-il bien servir?
c) Quel est le rle de lattribut m_capacity? quoi peut-il bien servir? Dites en quoi
m_capacity diffre de m_size

d) quoi sert le type iterator?
e) quoi sert le type const_iterator?
f) Pourquoi avons-nous besoin de deux mthodes operator[] ? Comment le compilateur serat-il quelle version utiliser? Dcrivez une situation o ce sera la version retournant const
T& qui sera utilise et dcrivez une situation o ce sera la version retournant T& qui sera
utilise.


8. Considrez la suite de Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13 Le nime nombre de Fibonacci F(n)
est donn par la rcurrence: F(n) = F(n-1) + F(n-2), avec les conditions initiales: F(0) = 0 et
F(1) =1.

(a) crivez une fonction rcursive en C++ qui permet de calculer F(n) en utilisant sa
dfinition rcursive. Que pouvez-vous dire propos de lefficacit de cette solution ?
(b) crivez une fonction en C++ permettant ce calculer F(n) en un temps en O(n).











9. Considrez limplmentation (partielle) suivante de List. crivez le corps des mthodes


insert() et erase() selon les spcifications mentionnes dans les commentaires.

template<typename Object>
class List
{
private:
struct Node
{
Node(const Object & d = 0, Node* p = 0, Node* n = 0) :
data(d), prev(p), next(n) { }
Object data;
Node* prev;
Node* next;
}; //Node
public:
class iterator
{
public:
iterator() : current(0) { }
Object & operator*()
{
return current->data;
}
iterator & operator++()
{
current = current->next;
return *this;
}
iterator & operator--()
{
current = current->prev;
return *this;
}
private:
Node* current;
iterator(Node* p) : current(p) { }
friend class List<Object>;
};//iterator
public: //List
List() {init();}
~List() { . . . }

// \brief insertion de x prcdant le nud point par itr


// \param[in] lobjet x insrer
// \param[in] litrateur itr pointant sur un nud
// \pre sil y en a ...
// \return iterator pointant sur le nud insr contenant x
iterator insert( const iterator & itr, const Object & x)
{//CODE CRIRE

}
// \brief suppression du nud point par itr
// \param[in] litrateur itr pointant sur le nud supprimer
// \pre sil y en a ...
// \return iterator pointant sur le nud suivant le nud supprim
iterator erase(const iterator & itr)
{//CODE CRIRE

}
private: //List
int theSize;
Node * head;
Node * tail;
void init()//cration des sentinelles
{
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
head->prev = tail->next = 0;
}
}; //List

10. crivez le code du constructeur de copie et des mthodes operator=, empiler et dpiler pour
limplmentation suivante de Pile. Lutilisation des mthodes de <list> est fortement
encourage.

#include <stdexcept>
#include <list>
#include "ContratException.h"
template <typename T>
class Pile
{
public:
Pile() { }
Pile(const Pile& source)
{ //insrez ici le code du constructeur de copie

}
~Pile() { laPile.clear() ; }
const Pile<T>& operator=(const Pile<T>& p)
{ // insrez ici le code de loprateur =

}
void empiler(const T& source);
{ //insertion du code ici

}
T depiler()
{ //insertion du code ici

}
int taille() const { return laPile.size() ; }
private:
std::list<T> laPile;
} ;

1. Vous disposez de la classe suivante


template <typename E>
class Arbre
{
private:
class Noeud
{
public:
E data;
Noeud *gauche;
Noeud *droite;
int hauteur;
Noeud(const E & d): gauche(0),data(d),droite(0),hauteur(0) { }
};
Noeud * racine; //racine de l'arbre
long cpt; // Nombre de noeuds dans l'arbre
std::vector<E> _parcoursEnOrdre(Noeud*, std::vector<E>&) const;
std::vector<E> _parcoursPostOrdre(Noeud*, std::vector<E>&) const;
std::vector<E> _parcoursPreOrdre(Noeud*, std::vector<E>&) const;
public:
std::vector<E> parcoursEnOrdre() const
{
std::vector<E> v; //pour stocker les rsultats du parcours
_parcoursEnOrdre(racine, v);
return v;
}
std::vector<E> parcoursPostOrdre() const
{
std::vector<E> v; //pour stocker les rsultats du parcours
_parcoursPostOrdre(racine, v);
return v;
}
std::vector<E> parcoursPostOrdre() const
{
std::vector<E> v; //pour stocker les rsultats du parcours
_parcoursPreOrdre(racine, v);
return v;
}
};

(a) Les mthodes publiques parcoursEnOrdre(), parcoursPostOdre() et parcoursPreOrdre()


permettent, respectivement, de visiter larbre binaire de recherche selon le parcours en-ordre
(parcours symmtrique), pr-ordre et post-ordre. Pour cela, elles font appel des mthodes
prives de nom similaires. Fournissez limplantation de ces mthodes aux endroits prvues
cette fin ci-dessous.

template <typename E>


void Arbre<E>::_parcoursPreOrdre(Noeud* arb, std::vector<E> & v)
{

}
template <typename E>
void Arbre<E>::_parcoursEnOrdre(Noeud* arb, std::vector<E> & v)
{

}
template <typename E>
void Arbre<E>::_parcoursPostOrdre(Noeud* arb, std::vector<E> & v)
{

(b) Donnez le temps dexcution de ces mthodes laide de la notation asymptotique en


justifiant vos rponses.
(c) Considrant que cette classe met en uvre un arbre binaire de recherche comme
conteneur de donnes, expliquez comment chaque donne se trouvant dans cet arbre est
positionne par rapport aux autres
(c) Sil y a un ordre respect dans ce positionnement, comment est-il dfini en terme du type
gnrique E utilis pour cette classe? Pour ce faire, est-ce quil est souhaitable de
surcharger certains oprateurs pour le type E? Si oui, lesquels?

(d) Quelle est la dfinition de la hauteur dun nud dans un arbre binaire de recherche?
Quelle est la dfinition de la profondeur dun nud? Quelle est la dfinition de la
hauteur dun arbre binaire de recherche? Quelle relation existe-t-il entre la hauteur dun
nud, sa profondeur et la hauteur de larbre binaire de recherche auquel il appartient?
4. Soit la squence suivante : 1, 8, 3, 7, 5, 6, 4, 2. En suivant fidlement lalgorithme
dinsertion avec balancement discut en cours, donnez la reprsentation graphique de
larbre binaire AVL aprs chaque insertion, sachant que les lments seront insrs
dans lordre o ils apparaissent ci-dessus (de gauche droite).


5. Les questions suivantes se rapportent aux conteneurs set, map, multiset, multimap,
unordered_set, unordered_map, unordered_multiset, et unordered_multimap de la STL.

(a) Considrant que chacune de vos donnes est constitue dune paire (cl,valeur) et quil
est impossible davoir deux donnes ayant la mme cl, quel conteneur de la STL
choisiriez-vous si vous dsirez effectuer le plus efficacement possible les opration de
recherche dinsertion et de suppression de donnes? Que pouvez-vous dire au sujet du
temps dexcution de ces oprations?

(b) Considrant que chacune de vos donnes est constitue dun singleton (cl) et quil est
impossible davoir deux donnes ayant la mme cl, quel conteneur de la STL choisiriezvous si vous dsirez effectuer le plus efficacement possible les opration de recherche
dinsertion et de suppression de donnes ainsi que les oprations trouver llment le
plus petit et trouver llment le plus grand ? Que pouvez-vous dire au sujet du temps
dexcution de ces oprations?
(c) Considrant que chacune de vos donnes est constitue dune paire (cl,valeur) et quil
est possible davoir deux (mais au plus dix) donnes ayant la mme cl, quel conteneur
de la STL choisiriez-vous si vous dsirez effectuer le plus efficacement possible les
opration de recherche dinsertion et de suppression de donnes ainsi que dordonner les
donnes selon lordre croissant de leur cl? Que pouvez-vous dire au sujet du temps
dexcution de ces oprations?
(d) Considrant que chacune de vos donnes est constitue dun singleton (cl) et quil est
impossible davoir deux donnes ayant la mme cl, quel conteneur de la STL choisiriezvous si vous dsirez effectuer le plus efficacement possible les opration de recherche
dinsertion et de suppression de donnes? Que pouvez-vous dire au sujet du temps
dexcution de ces oprations?


6.

(8 points) Considrez le tas max dont le tableau contient les lments suivants (stocks dans
lordre de gauche droite, du plus petit index au plus grand) : 22, 16, 17, 13, 11, 11, 9, 9, 8,
10, 7, 7, 6, 8, 5, 3, 2. Quel est le tas obtenu lorsque lon enlve llment 22? Utilisez la

reprsentation arborescente pour illustrer les diffrentes tapes de la reconstruction du tas


aprs avoir enlev llment 22.


7. Dmontrez que la hauteur dun tas de n nuds est en (log n).
-------------------------


8. Dmontrez que la hauteur dun arbre AVL de n nuds est en O(log n).
-------------------------

Considrez larbre AVL suivant.


6


2
9


10
5
1
7



3
8


Dessinez larbre AVL final suite la suppression de la racine.










9. Vous dsirez implmenter larbre binaire de la question prcdente dans un tableau dont les
indices dbutent 0. Pour chaque lment indiquez quelle sera sa position (indice) dans le
tableau.








t
1
x


10

2 3 9
4 6

S

5
7


y
z
2

9. Trouver le plus court chemin entre s et x, ceci en suivant trs fidlement lalgorithme de
Dijkstra discut dans le cours et en considrant la pondration de chaque arc dans le
graphe. Dans le tableau ci-dessous, donnez toutes les tapes de lalgorithme vous
permettant de trouver la solution. Chaque ligne reprsente un sommet destination et la
colonne i reprsente la ime itration de lalgorithme. Ainsi, vous devez indiquer, dans
chaque case, la distance et le prdcesseur pour le chemin trouv par lalgorithme entre le
sommet s et le sommet de la ligne litration reprsente par la colonne.


tapes
sommet initial



Indiquez le plus court chemin entre s et x:
Indiquez la longueur de ce plus court chemin

10. Considrez un graphe orient et valu (pondr) G(S,A,v) o S est un ensemble de n
sommets, A est un ensemble de m arcs et v : A R+ est une fonction valeur non ngative.
Considrez la matrice de valuation W dfini par W[i,j] = 0 lorsque i=j, W[i,j] = lorsque (i,j)
nest pas dans A et W[i,j] = v(i,j) lorsque (i,j) est dans A. Pour k allant de 0 n, soit Dk la
matrice des plus courts chemins passant par les k premiers sommets. Plus spcifiquement,
pour tout sommet i et j et pour tout k, on a que Dk[i,j] est la distance du plus court chemin
allant de i j tel que les sommets intermdiaires sont tous dans {1,.., k}. Notons que D0= W.
(a) crivez la relation de rcurrence permettant dexprimer Dk en fonction de Dk-1.
(b) En vous basant sur cette relation de rcurrence, crivez le pseudo code de
lalgorithme de Floyd permettant de trouver la distance D[i,j] du plus court chemin entre
toutes les paires (i,j) de sommet.


12. Considrez un graphe G(S, A, w) orient et valu tel que S dsigne lensemble de ses
sommets, A dsigne lensemble de ses arcs et w est la fonction de valuation. Considrez
lalgorithme de Bellman-Ford :

Entre: un Graphe orient valu G(S, A, w) et un sommet source s de S.
Sortie: Retourne FAUX sil existe un cycle de poids ngatif. Sinon, retourne VRAI et retourne la
longueur d(v) et le prdcesseur p(v) du plus court chemin allant de s v pour tout sommet v de
S.

POUR tout v dans S FAIRE //initialisation de d et p


d(v) = + ; p(v) = NIL;

d(s) = 0;

RPTER |S|-1 FOIS //boucle principale de lalgorithme


POUR tout (u,v) de A FAIRE



temp = d(u) + w(u, v);



SI temp < d(v) //relchement pour (u.v)




d(v) = temp; p(v) = u;

POUR tout (u,v) de A FAIRE //vrification de lexistence dun cycle de longueur < 0


SI d(v) > d(u) + w(u,v) ALORS retourner FAUX;

retourner VRAI;

Dmontrez que lorsque lalgorithme a termin la boucle principale et quil nexiste pas
dans G des cycles de poids ngatifs, nous avons pour tout plus court chemin allant du
sommet source s un nud v (accessible depuis s) que d(v) est gal la distance du
plus court chemin allant de s v.













11. Considrez lalgorithme de tri suivant :

template <typename Comparable>


void sort( vector<Comparable> & a )
{
vector<Comparable> tmpArray( a.size( ) );
_sort( a, tmpArray, 0, a.size( ) - 1 );
}

template <typename Comparable>


void _sort( vector<Comparable> & a,
vector<Comparable> & tmpArray, int left, int right
)
{
if( left < right )
{
int center = ( left + right ) / 2;
_sort( a, tmpArray, left, center );
_sort( a, tmpArray, center + 1, right );
_tri( a, tmpArray, left, center + 1, right );
}
}
template <typename Comparable>
void _tri( vector<Comparable> & a, vector<Comparable> & tmpArray,
int leftPos, int rightPos, int rightEnd
)
{
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int numElements = rightEnd - leftPos + 1;
while( leftPos <= leftEnd && rightPos <= rightEnd )
if( a[ leftPos ] <= a[ rightPos ] )
tmpArray[ tmpPos++ ] = a[ leftPos++ ];
else
tmpArray[ tmpPos++ ] = a[ rightPos++ ];
while( leftPos <= leftEnd )
tmpArray[ tmpPos++ ] = a[ leftPos++ ];
while( rightPos <= rightEnd )
tmpArray[ tmpPos++ ] = a[ rightPos++ ];
for( int i = 0; i < numElements; i++, rightEnd-- )
a[ rightEnd ] = tmpArray[ rightEnd ];
}

Trouvez le temps dexcution de cet algorithme en pire cas, en cas moyen et en meilleur cas.
Vous devez justifier vos rponses et les exprimer en utilisant la notation asymptotique en
fonction de la taille n du vecteur a.
-------------------------------12. (a) Quelle structure de donnes choisiriez-vous pour la mise en uvre dun conteneur de n
lments vous assurant que les oprations suivantes seffectuent en O(log n) en pire cas : la
recherche dun lment, linsertion dun lment, la suppression dun lment, trouver
llment de valeur maximale et trouver llment de valeur minimale? (b) Quelle structure
de donnes choisiriez-vous pour la mise en uvre dun conteneur de n lments vous assurant
que les oprations suivantes seffectuent en O(1) dans la presque totalit des cas : la recherche
dun lment, linsertion dun lment, la suppression dun lment?

13. Vous disposez dune table de dispersion comportant 10 entres, numrotes de 0 9. Vous
dsirez insrer dans cette table (et dans cet ordre, de gauche droite) les entiers non signs
suivants 23, 22, 42, 64, 53. Pour y arriver, vous utilisez la fonction de hachage h(x) = x mod
10. Indiquez quelle entre de la table sera positionn chaque lment (a) si vous utilisez un
sondage linaire vu en classe, (b) si vous utilisez le sondage quadratique vu en classe, (c) si
vous utilisez un double hachage avec la fonction de hachage auxiliaire h(x) = 7 x mod 7.

14. Vous disposez dune table de dispersion comportant 10 entres, numrotes de 0 9. Vous
dsirez insrer dans cette table (et dans cet ordre, de gauche droite) les entiers non signs
suivants 15, 14, 65, 44, 54, 35. Pour y arriver, vous utilisez la fonction de hachage h(x) = x
mod 10. Indiquez quelle entre de la table sera positionn chaque lment (a) si vous
utilisez un sondage linaire, (b) si vous utilisez le sondage quadratique, (c) si vous utilisez un
double hachage avec la fonction de hachage auxiliaire h(x) = 7 x mod 7.



















1. Ajoutez le code manquant en C++ dans la fonction mergeSortAA() ci-dessous afin que la
fonction mergeSort() puisse effectuer correctement le tri fusion sur le vecteur a. On suppose ici que le
type Comparable surcharge operator= et operator<=. (b) Que pouvez-vous dire au sujet du temps
dexcution du tri fusion ?

template <typename Comparable>
void merge( vector<Comparable> & a, vector<Comparable> & tmpArray,
int leftPos, int rightPos, int rightEnd )
{
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int numElements = rightEnd - leftPos + 1;
while( leftPos <= leftEnd && rightPos <= rightEnd )
if( a[ leftPos ] <= a[ rightPos ] )
tmpArray[ tmpPos++ ] = a[ leftPos++ ];
else
tmpArray[ tmpPos++ ] = a[ rightPos++ ];
while( leftPos <= leftEnd )
tmpArray[ tmpPos++ ] = a[ leftPos++ ];
while( rightPos <= rightEnd )
tmpArray[ tmpPos++ ] = a[ rightPos++ ];
for( int i = 0; i < numElements; i++, rightEnd-- )
a[ rightEnd ] = tmpArray[ rightEnd ];
}
template <typename Comparable>
void mergeSortAA( vector<Comparable> & a, vector<Comparable> & tmpArray, int left, int right )
{
//insrer votre code ici

}
template <typename Comparable>
void mergeSort( vector<Comparable> & a )
{
vector<Comparable> tmpArray( a.size( ) );
mergeSortAA( a, tmpArray, 0, a.size( ) - 1 );
}

Vous aimerez peut-être aussi