Skip to content
Snippets Groups Projects
Commit e5aa38d0 authored by Mohamed229-web's avatar Mohamed229-web
Browse files

Revu de la classe TasBinomial et de la méthode union

parent 8b9a5103
Branches tp5_12314926
No related tags found
No related merge requests found
Pipeline #6609 failed
#!/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
class Noeud:
def __init__(self, key):
self.key = key
self.children = []
self.degree = 0
class TasBinomial:
def __init__(self):
self.arbres = []
def union(self, nouveau_tas):
self.arbres.extend(nouveau_tas.arbres)
self.arbres.sort(key=lambda x: x.degree)
i = 0
while i < len(self.arbres) - 1:
if self.arbres[i].degree == self.arbres[i + 1].degree:
if self.arbres[i].key > self.arbres[i + 1].key:
self.arbres[i], self.arbres[i +
1] = self.arbres[i + 1], self.arbres[i]
self.arbres[i].children.append(self.arbres[i + 1])
del self.arbres[i + 1]
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)
i += 1
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 inserer(self, key):
nouveau_tas = TasBinomial()
nouveau_tas.arbres.append(Noeud(key))
self.union(nouveau_tas)
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:
def get_min(self):
if not self.arbres:
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)
min_node = self.arbres[0]
for arbre in self.arbres:
if arbre.key < min_node.key:
min_node = arbre
return min_node.key
def __min(self):
if not self.racine:
def extraire_min(self):
if not self.arbres:
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)
min_node = self.arbres[0]
min_idx = 0
for i, arbre in enumerate(self.arbres):
if arbre.key < min_node.key:
min_node = arbre
min_idx = i
del self.arbres[min_idx]
tas_enfant = TasBinomial()
tas_enfant.arbres = min_node.children
self.union(tas_enfant)
return min_node.key
if __name__ == "__main__":
tokens1 = [10, 12, 11, 1, 5, 22, 99, 20, 70, 60, 65, 23, 6, 4]
# Exemple d'utilisation :
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)
tas = TasBinomial()
tas.inserer(5)
tas.inserer(3)
tas.inserer(10)
tas.inserer(2)
tas.inserer(12)
tas.inserer(20)
print("Min:", tas.get_min())
print("Extract Min:", tas.extraire_min())
print("Min:", tas.get_min())
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment