Tas-Min : implémentation

  • Convention : les noeuds sont numérotés à partir de 0 :
  • pere = (i-1)//2 ; fils_gauche = 2*i+1 ; fils_droit = 2*i+2
In [8]:
def echange(tas, i, j):
    tas[i], tas[j] = tas[j], tas[i]

def percolation_up(tas, i):
    pere = (i-1)//2
    if i==0 or tas[i] > tas[pere]:
        return
    echange(tas, i, pere)
    percolation_up(tas, pere)

def percolation_down(tas, i):
    n, fg, fd = len(tas), 2*i+1, 2*i+2
    if fd < n and tas[fd] < tas[i] and tas[fd] < tas[fg]:
        echange(tas, i, fd)
        percolation_down(tas, fd)
    elif fg < n and tas[fg] < tas[i]:
        echange(tas, i, fg)
        percolation_down(tas, fg)

def heappush(tas, x):
    tas.append(x)
    percolation_up(tas, len(tas)-1)

def heappop(tas):
    if len(tas)==0: return
    echange(tas, 0, len(tas)-1)
    mini = tas.pop()
    percolation_down(tas, 0)
    return mini

Affichage (graphviz)

Vraiment pas du tout à connaître hein

In [9]:
def tas_to_dot(M):
    import graphviz
    n, inf = len(M), float('inf')
    s = ["digraph TasMin {", "node[shape=rectangle]"]
    for i in range(n):
        s.append('{} [label="{}"]'.format(i, M[i]))
        if 2*i+1 < n:
            s.append("{}->{}".format(i, 2*i+1))
        if 2*i+2 < n:
            s.append("{}->{}".format(i, 2*i+2))
    s.append("}")
    return graphviz.Source('\n'.join(s), engine='dot')

Exemple : Tas-Min

In [29]:
import random
u = []
In [49]:
# évaluer avec `Ctrl-Entrée` pour rester dans la cellule
heappush(u, (random.randint(0, 99)))
print(u)
tas_to_dot(u)
[3, 4, 8, 17, 35, 51, 42, 78, 28, 51, 79, 61, 60, 87, 51, 94, 94, 79, 53, 56]
Out[49]:
TasMin 0 3 1 4 0->1 2 8 0->2 3 17 1->3 4 35 1->4 5 51 2->5 6 42 2->6 7 78 3->7 8 28 3->8 9 51 4->9 10 79 4->10 11 61 5->11 12 60 5->12 13 87 6->13 14 51 6->14 15 94 7->15 16 94 7->16 17 79 8->17 18 53 8->18 19 56 9->19
In [50]:
print(heappop(u), u)
tas_to_dot(u)
3 [4, 17, 8, 28, 35, 51, 42, 78, 53, 51, 79, 61, 60, 87, 51, 94, 94, 79, 56]
Out[50]:
TasMin 0 4 1 17 0->1 2 8 0->2 3 28 1->3 4 35 1->4 5 51 2->5 6 42 2->6 7 78 3->7 8 53 3->8 9 51 4->9 10 79 4->10 11 61 5->11 12 60 5->12 13 87 6->13 14 51 6->14 15 94 7->15 16 94 7->16 17 79 8->17 18 56 8->18

Exemple : file de priorité

In [51]:
import random
fileprio = []
In [63]:
distance, sommet = (random.randrange(0, 20), random.choice("ABCD"))
heappush(fileprio, (distance, sommet))
print(fileprio)
tas_to_dot(fileprio)
[(0, 'D'), (1, 'D'), (5, 'A'), (3, 'B'), (3, 'D'), (14, 'C'), (14, 'D'), (13, 'A'), (14, 'C'), (5, 'D'), (17, 'A'), (18, 'C')]
Out[63]:
TasMin 0 (0, 'D') 1 (1, 'D') 0->1 2 (5, 'A') 0->2 3 (3, 'B') 1->3 4 (3, 'D') 1->4 5 (14, 'C') 2->5 6 (14, 'D') 2->6 7 (13, 'A') 3->7 8 (14, 'C') 3->8 9 (5, 'D') 4->9 10 (17, 'A') 4->10 11 (18, 'C') 5->11
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]: