Visualisez comment les données sont triées à l'aide de Tkinter de Python "Je vois!" C'est un code qui semble l'être. before after
Comme le contenu
--Tri rapide --Tri par fusion --Tri sélectif
Sera réalisée. Voici l exemple de code. Créez des classes. Créez ensuite une fonction.
sortSample.py
# =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
#Avec tkinter et minuteries
#Visualisez le tri
# 2020.06.19 ProOJI
# =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
import tkinter
import time
#Taille de la toile
CANVAS_WIDTH = 600
CANVAS_HEIGHT = 400
#Poids au moment du (des) dessin (s)
WAIT = 0
class Sort():
#Type de tri
SELECTION_SORT = 1
QUICK_SORT = 2
MERGE_SORT = 3
def __init__(self, view):
'Génération d'objets à trier'
self.view = view
def start(self, data, method):
'Commencer le tri'
#Définir une liste de données à trier
self.data = data
#Définir le nombre de données à trier
self.num = len(data)
#Initialisation du comptage de comparaison
self.compare_num = 0
#Effectuer le tri selon la méthode
if method == Sort.SELECTION_SORT:
#Sélectionnez l'exécution du tri
self.selection_sort(0, self.num - 1)
elif method == Sort.QUICK_SORT:
#Exécuter un tri rapide
self.quick_sort(0, self.num - 1)
elif method == Sort.MERGE_SORT:
#Préparer la mémoire de travail pour le tri par fusion
self.work = [0] * self.num
#Exécution du tri de fusion
self.merge_sort(0, self.num - 1)
for num in self.data:
print(num)
#Renvoie le nombre de comparaisons
return self.compare_num
def selection_sort(self, left, right):
'Effectuer un tri sélectif'
if left == right:
#Puisqu'il n'y a qu'une seule donnée, le tri se termine
return
#Déterminez temporairement la valeur minimale
min = self.data[left]
i_min = left
#Rechercher la valeur minimale dans la plage de tri
for i in range(left, right + 1):
if min > self.data[i]:
#Mise à jour de la valeur minimale
min = self.data[i]
i_min = i
#Augmenter le nombre de comparaisons
self.compare_num += 1
#Échangez la valeur minimale et les données les plus à gauche
if i_min != left:
#Remplacez seulement si nécessaire
tmp = self.data[left]
self.data[left] = self.data[i_min]
self.data[i_min] = tmp
#Afficher la séquence de données actuelle
self.view.draw_data(self.data)
#Réduisez la plage et sélectionnez à nouveau
self.selection_sort(left + 1, right)
def quick_sort(self, left, right):
'Effectuer un tri rapide'
if left >= right:
#Le tri se termine car le nombre de données est égal ou inférieur à 1
return
#Détermination du pivot
pivot = self.data[left]
i = left
j = right
#Placez les nombres sous le pivot dans la première moitié du tableau,
#Collectez les nombres au-dessus du pivot dans la seconde moitié du tableau
while True:
#Rechercher des nombres au-dessus du pivot à partir de la gauche
while self.data[i] < pivot:
i += 1
#Augmenter le nombre de comparaisons
self.compare_num += 1
#Recherchez les numéros ci-dessous pivot à partir de la droite
while self.data[j] > pivot:
j -= 1
#Augmenter le nombre de comparaisons
self.compare_num += 1
# i >=Devenir j signifie
#Les nombres ci-dessous pivotent sur le côté gauche du tableau
#Que les nombres au-dessus du pivot sont rassemblés sur le côté droit du tableau
if i >= j:
#Le processus de division de l'ensemble est terminé
break
#Échangez les deux numéros que vous avez recherchés
tmp = self.data[i]
self.data[i] = self.data[j]
self.data[j] = tmp
#La recherche reprend à partir du numéro suivant après l'échange
i += 1
j -= 1
#Afficher la séquence de données actuelle
self.view.draw_data(self.data)
#Trier par une plage de petits nombres
self.quick_sort(left, i - 1)
#Trier par une plage de grands nombres
self.quick_sort(j + 1, right)
def merge_sort(self, left, right):
'Effectuer un tri par fusion'
if left == right:
#Puisqu'il n'y a qu'une seule donnée, le tri se termine
return
#Divisez l'ensemble en deux au centre
mid = (left + right) // 2
#Trier les données de chaque ensemble après division
self.merge_sort(left, mid)
self.merge_sort(mid + 1, right)
#Fusionner chaque ensemble trié
self.merge(left, mid, right)
#Afficher la séquence de données actuelle
self.view.draw_data(self.data)
def merge(self, left, mid, right):
'Fusionner des ensembles'
#Définir le point de départ du premier set
i = left
#Définissez le point de départ du deuxième set
j = mid + 1
#Définir le point de départ de l'ensemble de destinations de fusion
k = 0
#L'un des deux ensembles
#Boucle jusqu'à ce que tous soient fusionnés
while i <= mid and j <= right:
#Augmenter le nombre de comparaisons
self.compare_num += 1
#Des deux ensembles sans les données fusionnées
#Fusionner la plus petite des premières données
if (self.data[i] < self.data[j]):
self.work[k] = self.data[i]
#L'index de l'ensemble fusionné et
#Incrémenter l'index de l'ensemble de destination de fusion
i += 1
k += 1
else:
self.work[k] = self.data[j]
#L'index de l'ensemble fusionné et
#Incrémenter l'index de l'ensemble de destination de fusion
j += 1
k += 1
#Un ensemble de données non fusionnées
#Fusionner dans l'ensemble de destinations de fusion
while i <= mid:
#Augmenter le nombre de comparaisons
self.compare_num += 1
self.work[k] = self.data[i]
i += 1
k += 1
while j <= right:
#Augmenter le nombre de comparaisons
self.compare_num += 1
self.work[k] = self.data[j]
j += 1
k += 1
#Copier l'ensemble de destinations de fusion dans les données
j = 0
for i in range(left, right + 1):
self.data[i] = self.work[j]
j += 1
class View():
def __init__(self, master):
'Génération d'objets liés à l'interface utilisateur'
#divers paramètres
self.drawn_obj = []
#Déterminez la taille de la toile
self.canvas_width = CANVAS_WIDTH
self.canvas_height = CANVAS_HEIGHT
#Créer un cadre pour afficher les informations
self.canvas_frame = tkinter.Frame(
master,
)
self.canvas_frame.grid(column=1, row=1)
#Créer un cadre pour le widget d'opération
self.operation_frame = tkinter.Frame(
master,
)
self.operation_frame.grid(column=2, row=1, padx=10)
#Génération et placement de canevas
self.canvas = tkinter.Canvas(
self.canvas_frame,
width=self.canvas_width,
height=self.canvas_height,
)
self.canvas.pack()
#Génération et placement d'étiquettes
self.text = tkinter.StringVar()
self.text.set("Appuyez sur le bouton de démarrage")
self.label = tkinter.Label(
self.canvas_frame,
textvariable=self.text,
)
self.label.pack()
#Génération et organisation de cadres pour le placement de zone de texte
max_w = CANVAS_WIDTH // 2
max_h = CANVAS_HEIGHT // 2
if max_w < max_h:
max = max_w
else:
max = max_h
self.text_frame = tkinter.LabelFrame(
self.operation_frame,
text="Nombre de données (maximum" + str(max) + ")"
)
self.text_frame.pack(ipadx=10, pady=10)
self.entry = tkinter.Entry(
self.text_frame,
width=4
)
self.entry.pack()
#Génération et placement des cadres pour le placement des boutons radio
self.radio_frame = tkinter.LabelFrame(
self.operation_frame,
text="algorithme"
)
self.radio_frame.pack(ipadx=10, pady=10)
#Génération d'objets pour obtenir le bouton coché
self.sort = tkinter.IntVar()
self.sort.set(Sort.QUICK_SORT)
#Créer et placer 3 boutons radio pour la sélection de l'algorithme
self.selection_button = tkinter.Radiobutton(
self.radio_frame,
variable=self.sort,
text="Tri sélectif",
value=Sort.SELECTION_SORT
)
self.selection_button.pack()
self.quick_button = tkinter.Radiobutton(
self.radio_frame,
variable=self.sort,
text="Tri rapide",
value=Sort.QUICK_SORT
)
self.quick_button.pack()
self.merge_button = tkinter.Radiobutton(
self.radio_frame,
variable=self.sort,
text="Tri par fusion",
value=Sort.MERGE_SORT
)
self.merge_button.pack()
#Génération et placement des boutons de démarrage
self.button = tkinter.Button(
self.operation_frame,
text="début",
)
self.button.pack()
def start(self, n):
'Dessiner l'arrière-plan'
#Définir le nombre de données
self.num = n
#Déterminez la largeur de la ligne représentant une donnée
self.line_width = CANVAS_WIDTH / self.num
#Déterminez la hauteur de ligne de la valeur de données 1
#Lorsque la valeur des données est N, la hauteur de la ligne est auto.line_height *Devenir N
self.line_height = CANVAS_HEIGHT / self.num
#Quand il y a trop de données à dessiner
if self.line_width < 2 or self.line_height < 2:
return False
#Pour le réglage de la position de l'arrière-plan (centré)
self.offset_x = int(
(self.canvas.winfo_width() - self.line_width * self.num) / 2
)
self.offset_y = int(
(self.canvas.winfo_height() - self.line_height * self.num + 1) / 2
)
#Supprimer les données une fois dessinées
for obj in self.drawn_obj:
self.canvas.delete(obj)
#Vider la liste de données dessinée car elle a été supprimée
self.drawn_obj = []
#Supprimer l'objet d'arrière-plan à l'avance
self.canvas.delete("background")
#Dessiner l'arrière-plan
self.canvas.create_rectangle(
self.offset_x,
self.offset_y,
int(self.offset_x + self.line_width * self.num),
int(self.offset_y + self.line_height * self.num),
width=0,
fill="#EEEEFF",
tag="background"
)
#Refléter immédiatement le dessin
self.canvas.update()
return True
def get_algorithm(self):
'Acquisition d'algorithme de tri'
return self.sort.get()
def get_data_num(self):
'Obtenez le nombre de données'
return int(self.entry.get())
def draw_data(self, data):
'Dessinez une séquence de données sous forme de ligne'
#Supprimer les données une fois dessinées
for obj in self.drawn_obj:
self.canvas.delete(obj)
#Vider la liste de données dessinée car elle a été supprimée
self.drawn_obj = []
#Dessinez les nombres de la liste sous forme de rectangle
i = 0
for value in data:
#Déterminez les points de départ et d'arrivée du rectangle
#Déterminez les coordonnées horizontales du rectangle à partir de la position des données
x1 = int(self.offset_x + i * self.line_width)
x2 = int(self.offset_x + (i + 1) * self.line_width)
#Déterminez les coordonnées verticales du rectangle à partir des valeurs de données
y1 = int(self.offset_y + self.line_height * (self.num - value))
y2 = int(self.offset_y + self.line_height * self.num)
#Ajoutez une balise pour pouvoir l'effacer plus tard
tag = "line" + str(i)
self.drawn_obj.append(tag)
#Dessinez un rectangle
self.canvas.create_rectangle(
x1, y1,
x2, y2,
tag=tag,
fill="#FFA588",
width=1
)
i += 1
#Refléter immédiatement le dessin
self.canvas.update()
#Dormez pendant WAIT secondes
time.sleep(WAIT)
def update_message(self, text):
'Mettre à jour le message à afficher sur l'étiquette'
#Définir la chaîne de caractères à dessiner sur l'étiquette
self.text.set(text)
#Refléter immédiatement le dessin
self.label.update()
class Controller():
def __init__(self, view, sort):
'Créer des objets pour contrôler le tri et l'affichage'
#Afficher et trier les paramètres des objets à contrôler
self.view = view
self.sort = sort
#Accepte les événements lorsque le bouton est cliqué
self.view.button["command"] = self.button_click
def button_click(self):
'Traitement lorsqu'un clic est effectué sur un bouton'
num = self.view.get_data_num()
#Vue de départ
if not self.view.start(num):
#Mise à jour du message
self.view.update_message(
"Trop de données"
)
#Ne faites rien si vous échouez
return
#Générer une liste aléatoire du nombre de données NUM avec NUM comme valeur maximale
data = []
for _ in range(num):
import random
data.append(int(random.randint(0, num - 1)))
#Lors de la commande des données initiales par ordre décroissant
#data = []
# for i in range(num):
# data.append(num - i)
#Mise à jour du message
self.view.update_message("Tri")
#Commencer le tri
compare_num = self.sort.start(data, self.view.get_algorithm())
#Mise à jour du message
self.view.update_message(
"Le tri est terminé! (Comparaison:" + str(compare_num) + ")"
)
#Génération d'applications
app = tkinter.Tk()
app.title("Trier")
#Afficher la création d'objets
view = View(app)
#Créer un objet de tri
sort = Sort(view)
#Création d'objet contrôleur
controller = Controller(view, sort)
#En attente de réception de l'événement dans mainloop
app.mainloop()
Il existe différents algorithmes de tri. J'espère que vous pourrez bien l'utiliser.
J'ai résumé l'algorithme de tri
Recommended Posts