From 8b9a5103e187198190eb08f4f8f1762e3c3c4a06 Mon Sep 17 00:00:00 2001
From: Mohamed229-web <djibrilaibrahim14@gmail.com>
Date: Sun, 15 Oct 2023 22:48:24 +0200
Subject: [PATCH] =?UTF-8?q?Cr=C3=A9ation=20d'un=20code=20python=20pour=20l?=
 =?UTF-8?q?es=20tas=20binomiaux?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 TP5/README.md |   8 ++
 TP5/tas.py    | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 328 insertions(+)
 create mode 100644 TP5/README.md
 create mode 100644 TP5/tas.py

diff --git a/TP5/README.md b/TP5/README.md
new file mode 100644
index 0000000..a6f4e16
--- /dev/null
+++ b/TP5/README.md
@@ -0,0 +1,8 @@
+Pour l'implantation en Python, nous avons créer plusieurs classes:
+- Une classe "RefElement" pour faire un référence à un élément dans le tas (un noeud)
+- Une classe "TasBinomial" pour représenter le tas; il contient en son sein, une classe Noeud pour représenter un de ses noeud et une classe __Ref pour la référence à l'élément courant. Nous avons ensuite implémanter au sein de cette classe les différentes méthodes :
+    - Union, pour la fusion de deux tas,
+    - Insérer, pour l'ajout d'un nouveau élément au tas,
+    - Extraire Min, pour l'extraction de la plus petite clé du tas
+
+Nous avons implémenter aussi des méthodes internes pour gérer les différentes opérations 
\ No newline at end of file
diff --git a/TP5/tas.py b/TP5/tas.py
new file mode 100644
index 0000000..edbb5d4
--- /dev/null
+++ b/TP5/tas.py
@@ -0,0 +1,320 @@
+#!/usr/bin/env python
+
+class RefElement(object):
+    def __init__(self, noeud, get_tas):
+        self.ref = noeud
+        self.get_tas = get_tas
+        self.existe = True
+
+    def __str__(self):
+        if self.existe:
+            return "<Tas Binomial Référant à '%s'>" % str(self.ref.val)
+        else:
+            return "<Référence du tas inexistante>"
+
+    def descendre(self, new_key):
+        # Met à jour la priorité de l'élément.
+        assert self.existe
+        assert self.ref.ref == self
+        self.ref.descendre(new_key)
+
+    def supprimer(self):
+        # Retire l'élément du tas.
+        self.descendre(self)
+        v = self.get_tas().extraireMin()
+        assert not self.existe
+        assert v is self.ref.valeur
+
+    def dans_tas(self, tas):
+        """Retourne True si l'élément appartient au tas entré en paramètre;
+        False sinon.
+        """
+        return self.existe and self.get_tas() == tas
+
+    def __lt__(self, autre):
+        "Agit comme une positive infinie: Toujours True."
+        return True
+
+    def __gt__(self, autre):
+        "Agit comme une négative infinie: Toujours False."
+        return False
+
+
+class TasBinomial(object):
+    class Noeud(object):
+        def __init__(self, get_tas, index, valeur=None):
+            self.niveau = 0
+            self.parent = None
+            self.suivant = None
+            self.fils = None
+            self.index = index
+            self.ref = RefElement(self, get_tas)
+            if valeur == None:
+                valeur = index
+            self.valeur = valeur
+
+        def __str__(self):
+            def k(x): return str(x.index) if x else 'NIL'
+            return '(Valeur:%s, Fils:%s, Suivant:%s)' % (k(self), k(self.fils), k(self.suivant))
+
+        def link(self, other):
+            "Crée un sous arbre."
+            other.parent = self
+            other.suivant = self.fils
+            self.fils = other
+            self.niveau += 1
+
+        def descendre(self, new_key):
+            noeud = self
+            assert new_key < noeud.index
+            noeud.index = new_key
+            cur = noeud
+            parent = cur.parent
+            while parent and cur.index < parent.index:
+                # need to bubble up
+                # swap refs
+                parent.ref.ref, cur.ref.ref = cur, parent
+                parent.ref, cur.ref = cur.ref, parent.ref
+                # now swap keys and payload
+                parent.index, cur.index = cur.index, parent.index
+                parent.valeur, cur.valeur = cur.valeur, parent.valeur
+                # step up
+                cur = parent
+                parent = cur.parent
+
+        @staticmethod
+        def roots_merge(h1, h2):
+            # Union de deux tas, ordonné par degré.
+            # Retourne une nouvelle racine.
+            if not h1:
+                return h2
+            if not h2:
+                return h1
+            if h1.niveau < h2.niveau:
+                h = h1
+                h1 = h.suivant
+            else:
+                h = h2
+                h2 = h2.suivant
+            p = h
+            while h2 and h1:
+                if h1.niveau < h2.niveau:
+                    p.suivant = h1
+                    h1 = h1.suivant
+                else:
+                    p.suivant = h2
+                    h2 = h2.suivant
+                p = p.suivant
+            if h2:
+                p.suivant = h2
+            else:
+                p.suivant = h1
+            return h
+
+        @staticmethod
+        def roots_reverse(h):
+            # Inverse la liste des racine du tas.
+            # Retourn la nouvelle racine. Nettoie aussi la référence des parents.
+            if not h:
+                return None
+            tail = None
+            suivant = h
+            h.parent = None
+            while h.suivant:
+                suivant = h.suivant
+                h.suivant = tail
+                tail = h
+                h = suivant
+                h.parent = None
+            h.suivant = tail
+            return h
+
+    class __Ref(object):
+        def __init__(self, h):
+            self.tas = h
+            self.ref = None
+
+        def get_ref_tas(self):
+            if not self.ref:
+                return self
+            else:
+                # compact
+                self.ref = self.ref.get_ref_tas()
+                return self.ref
+
+        def get_tas(self):
+            return self.get_ref_tas().get_tas
+
+    def __init__(self, list=[]):
+        # Populate a new heap with the (key, value) pairs in 'lst'.
+        # If the elements of lst are not subscriptable, then they are treated as
+        # opaque elements and inserted into the heap themselves.
+        self.racine = None
+        self.taille = 0
+        self.ref = TasBinomial.__Ref(self)
+        for x in list:
+            try:
+                self.inserer(x[0], x[1])
+            except TypeError:
+                self.inserer(x)
+
+    def inserer(self, key, value=None):
+        # Insert 'value' in to the heap with priority 'key'. If 'value' is omitted,
+        # then 'key' is used as the value.
+        # Returns a reference (of type ItemRef) to the internal node in the tree.
+        # Use this reference to delete the key or to change its priority.
+        n = TasBinomial.Noeud(self.ref.get_tas, key, value)
+        self.__union(n)
+        self.taille += 1
+        return n.ref
+
+    def union(self, other):
+        # Merge 'other' into 'self'. Returns None.
+        # Note: This is a destructive operation; 'other' is an empty heap afterwards.
+        self.taille = self.taille + other.taille
+        h2 = other.racine
+        self.__union(h2)
+        other.ref.ref = self.ref
+        other.__init__()
+
+    def min(self):
+        # Returns the value with the minimum key (= highest priority) in the heap
+        # without removing it, or None if the heap is empty.
+        pos = self.__min()
+        return pos[0].valeur if pos else None
+
+    def extraire_min(self):
+        # Returns the value with the minimum key (= highest priority) in the heap
+        # AND removes it from the heap, or None if the heap is empty.
+        #
+        # find mininum
+        pos = self.__min()
+        if not pos:
+            return None
+        else:
+            (x, prev) = pos
+            # remove from list
+            if prev:
+                prev.suivant = x.suivant
+            else:
+                self.racine = x.suivant
+            fils = TasBinomial.Noeud.roots_reverse(x.fils)
+            self.__union(fils)
+            x.ref.existe = False
+            self.taille -= 1
+            return x.valeur
+
+    def __nonzero__(self):
+        # True si le tas n'est pas vide; False sinon.
+        return self.tas != None
+
+    def __len__(self):
+        # Retourne le nombre d'élément dans le tas.
+        return self.taille
+
+    def __setitem__(self, key, value):
+        # Insertion.
+        # H[key] = value  équivaut à  H.insert(key, value)
+        self.inserer(key, value)
+
+    def __iadd__(self, other):
+        # Merge.
+        # a += b  équivaut à  a.union(b).
+        self.union(other)
+        return self
+
+    def suivant(self):
+        # Returns the value with the minimum key (= highest priority) in the hseap
+        # AND removes it from the heap; raises StopIteration if the heap is empty.
+        if self.racine:
+            return self.extraire_min()
+        else:
+            raise StopIteration
+
+    def __contains__(self, ref):
+        # Test whether a given reference 'ref' (of RefElement) is in this heap.
+        if type(ref) != RefElement:
+            raise TypeError
+        else:
+            return ref.dans_tas(self)
+
+    def __min(self):
+        if not self.racine:
+            return None
+        min = self.racine
+        min_prev = None
+        prev = min
+        cur = min.suivant
+        while cur:
+            if cur.index < min.index:
+                min = cur
+                min_prev = prev
+            prev = cur
+            cur = cur.suivant
+        return (min, min_prev)
+
+    def __union(self, h2):
+        if not h2:
+            # nothing to do
+            return
+
+        h1 = self.racine
+
+        if not h1:
+            self.racine = h2
+            return
+
+        h1 = TasBinomial.Noeud.roots_merge(h1, h2)
+        prev = None
+        x = h1
+        next = x.suivant
+        while next:
+            if x.niveau != next.niveau or \
+                    (next.suivant and next.suivant.niveau == x.niveau):
+                prev = x
+                x = next
+            elif x.index <= next.index:
+                # x becomes the root of next
+                x.suivant = next.suivant
+                x.link(next)
+            else:
+                # next becomes the root of x
+                if not prev:
+                    # update the "master" head
+                    h1 = next
+                else:
+                    # just update previous link
+                    prev.suivant = next
+                next.link(x)
+                # x is not toplevel anymore, update ref by advancing
+                x = next
+            next = x.suivant
+        self.racine = h1
+
+
+def créerTas(list=[]):
+    # Création d'un nouveau tas en utilisant *list* qui est une séquence de (clé, valeur)
+    # Avec la clé
+    return TasBinomial(list)
+
+
+if __name__ == "__main__":
+    tokens1 = [10, 12, 11, 1, 5, 22, 99, 20, 70, 60, 65, 23, 6, 4]
+    tokens2 = [80, 19, 51, 30, 82, 65, 45, 55, 75, 88, 28, 27, 3, 6, 7, 2]
+
+    tas1 = créerTas(tokens1)
+    tas2 = créerTas(tokens2)
+    h3 = créerTas()
+    # print(tas1.racine)
+    # print(tas2.racine)
+    # tas1.union(tas2)
+    # print(tas1.taille)
+    h3.inserer(50)
+    h3.inserer(3)
+    print(h3.racine)
+    print(h3.taille)
+    h3.inserer(5)
+    h3.inserer(2)
+    h3.inserer(24)
+    print(h3.racine)
+    print(h3.taille)
-- 
GitLab