Dictionnaire On veut une structure permettant d’insérer, d’enlever et de rechercher des enregistrements. Concepts importants: Clef de recherche: Décrit ce que nous recherchons. Clef de comparaison –Égalité: recherche séquentielle – Ordre total: tri Comparaison d’enregistrements
Exemple (1) Class Dossier{ public: int ID; char* nom; }; class IDCompare { public: bool lt(Dossier& x, Dossier& y) { return x.ID < y.ID; } bool eq(Dossier& x, Dossier& y) { return x.ID == y.ID; } bool gt(Dossier& x, Payroll& y) { return x.ID > y.ID; } };
Exemple (2) class NomCompare { public: bool lt(Dossier& x, Dossier& y) { return strcmp(x.nom, y.nom) < 0; } bool eq(Dossier& x, Dossier& y) { return strcmp(x.nom, y.nom) == 0; } bool gt(Dossier& x, Dossier& y) { return strcmp(x.nom, y.nom) > 0; } };
Exemple (3) class NDCompare { public: bool lt(char* x, Dossier& y) { return strcmp(x, y.nom) < 0; } bool eq(char* x, Dossier& y) { return strcmp(x, y.nom) == 0; } bool gt(char* x, Dossier& y) { return strcmp(x, y.nom) > 0; } };
Dictionnaire: classe abstraite // Classe abstraite pour le dictionnaire. template <class Key, class Elem, class KEComp, class EEComp> class Dictionary { public: virtual void clear() = 0; virtual bool insert(const Elem&) = 0; virtual bool remove(const Key&, Elem&) = 0; virtual bool find(const Key&, Elem&) const = 0; virtual int size() = 0; };
Dictictionnaire: liste non triée template <class Key, class Elem, class KEComp, class EEComp> class UALdict : public Dictionary { private: AList * list; public: UALdict(int size=DefaultListSize) {list = new AList (size); } ~UALdict() { delete list; } void clear() { list->clear(); }
Dictictionnaire: liste non triée bool insert(const Elem& e) { return list->append(e); } bool remove(const Key& K, Elem& e) { for(list->setStart(); list->getValue(e); list->next()) if (KEComp::eq(K, e)) { list->remove(e); return true; } return false; } };
Dictictionnaire: liste non triée bool find(const Key& K, Elem& e) const { for(list->setStart(); list->getValue(e); list->next()) if (KEComp::eq(K, e)) return true; return false; } int size() {return list->leftLength() + list->rightLength(); } };
Coût des opérations Chercher Ajouter Enlever Liste non triée: O(n) O(1) O(1) Liste trié: O(n) O(n) O(1) Tableau non trié: O(n) O(1) O(n) Tableau trié: O(lg n) O(n) O(n)
Arbres binaires de recherche Propriétés des ABR: Soit N, un nœud de valeur K. Tous les éléments stockés dans le sous-arbre de gauche de N ont une valeur < K. Tous les éléments stockés dans le sous-arbre de droite de N ont une valeur K.
ABR: implémentation (1) template <class Key, class Elem, class KEComp, class EEComp> class BST : public Dictionary<Key, Elem, KEComp, EEComp> { private: BinNode * root; // Racine int nodecount; // Nombre de noeuds void clearhelp(BinNode *); BinNode * inserthelp(BinNode *, const Elem&);
ABR: implémentation (2) BinNode * deletemin(BinNode *, BinNode *&); BinNode * removehelp(BinNode *, const Key&, BinNode *&); bool findhelp(BinNode *, const Key&, Elem&) const; void printhelp(BinNode *, int) const;
ABR: implémentation (3) public: BST() { root = NULL; nodecount = 0; } ~BST() { clearhelp(root); } void clear() { clearhelp(root); root = NULL; nodecount = 0; } bool insert(const Elem& e) { root = inserthelp(root, e); nodecount++; return true; }
ABR: implémentation (4) bool remove(const Key& K, Elem& e) { BinNode * t = NULL; root = removehelp(root, K, t); if (t == NULL) return false; e = t->val(); nodecount--; delete t; return true; }
ABR: implémentation (5) bool removeAny(Elem& e) { // Delete min value if (root == NULL) return false; // Empty BinNode * t; root = deletemin(root, t); e = t->val(); delete t; nodecount--; return true; }
ABR: implémentation (6) bool find(const Key& K, Elem& e) const { return findhelp(root, K, e); } int size() { return nodecount; } void print() const { if (root == NULL) cout << ”L’arbre est vide.\n"; else printhelp(root, 0); } };
ABR: rercherche template <class Key, class Elem, class KEComp, class EEComp> bool BST :: findhelp(BinNode * subroot, const Key& K, Elem& e) const { if (subroot == NULL) return false; else if (KEComp::lt(K, subroot->val())) return findhelp(subroot->left(), K, e); else if (KEComp::gt(K, subroot->val())) return findhelp(subroot->right(), K, e); else { e = subroot->val(); return true; }
ABR: insérer (1)
ABR: insérer(2) template <class Key, class Elem, class KEComp, class EEComp> BinNode * BST :: inserthelp(BinNode * subroot, const Elem& val) { if (subroot == NULL) return new BinNodePtr (val,NULL,NULL); if (EEComp::lt(val, subroot->val())) subroot->setLeft(inserthelp(subroot->left(), val)); else subroot->setRight( inserthelp(subroot->right(), val)); return subroot; }
Enlever la plus petite valeur template <class Key, class Elem, class KEComp, class EEComp> BinNode * BST :: deletemin(BinNode * subroot, BinNode *& min) { if (subroot->left() == NULL) { min = subroot; return subroot->right(); } else { subroot->setLeft( deletemin(subroot->left(), min)); return subroot; }
ABR: enlever (1)
ABR: enlever (2) template <class Key, class Elem, class KEComp, class EEComp> BinNode * BST :: removehelp(BinNode * subroot, const Key& K, BinNode *& t) { if (subroot == NULL) return NULL; else if (KEComp::lt(K, subroot->val())) subroot->setLeft( removehelp(subroot->left(), K, t)); else if (KEComp::gt(K, subroot->val())) subroot->setRight( removehelp(subroot->right(), K, t));
ABR: enlever (3) else { // L’élément est trouvé BinNode * temp; t = subroot; if (subroot->left() == NULL) subroot = subroot->right(); else if (subroot->right() == NULL) subroot = subroot->left(); else { // Les deux fils sont non vides subroot->setRight( deletemin(subroot->right(), temp)); Elem te = subroot->val(); subroot->setVal(temp->val()); temp->setVal(te); t = temp; } return subroot; }
Coût des opérations Arbre balancé Arbre non balancé Trouver:O(lg n) O(n) Insérer:O(lg n) O(n) Enlever:O(lg n) O(n)