当前位置: 首页 > news >正文

python编程实现GUI界面的排序与查找算法动态模拟演示程序

python编程实现GUI界面的排序与查找算法动态模拟演示程序

数据结构比喻常见的排序和查找方法的思想,对于新手来说入门不易,用python编程实现动态直观演示它们的思想,是比较有意义的。在此给出GUI界面的动态演示冒泡排序、选择排序、快速排序、归并排序和顺序查找、二分查找算法思想的演示程序。

附录给出打包可执行程序的地址。

运行截图

操作使用说明

设置数据:调整滑块或点击重置按钮,用户用此可以调整数据。

选择算法:用户可以从列表中选择要演示的算法。

查看说明:算法说明信息框可以显示基于当前数据的算法说明。

开始演示:“开始演示”按钮,用于在当前数据上运行算法演示。

这个程序用到的库或模块简介

tkinter 是 Python 的标准 GUI(图形用户界面)库,用于创建窗口、按钮、文本框等界面元素。它简单易用,适合快速开发小型桌面应用程序。tkinter是Python 标准库,无需额外安装。

random 用于生成随机数,是 Python 标准库中的一个模块,不需要额外安装。

time用于处理时间相关的操作,是 Python 标准库中的一个模块,不需要额外安装。

matplotlib 是 Python 的绘图库,可创建各种静态、动态的图表,如折线图、柱状图、散点图等。它支持多种输出格式,并可与 NumPy、pandas 等数据处理库无缝集成。matplotlib是第三方库,需额外安装。

numpy 是 Python 的数值计算库,提供高效的多维数组对象(ndarray)和各种数学函数。它是科学计算的基础库,许多其他数据科学库都依赖于它。numpy是第三方库,需额外安装。

源码如下:

import tkinter as tk
from tkinter import ttk, messagebox
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import random
import time# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Micro Hei', 'Heiti TC']
plt.rcParams['axes.unicode_minus'] = Falseclass AlgorithmVisualizerGUI:def __init__(self, root, size=15):self.root = rootself.root.title("排序与查找算法动态模拟演示")self.root.geometry("1100x800")self.root.configure(bg="#f0f0f0")# 设置字体self.title_font = ('SimHei', 16, 'bold')self.subtitle_font = ('SimHei', 12, 'bold')self.normal_font = ('SimHei', 10)self.size = sizeself.data = []  # 用户当前的数据self.current_algorithm = Noneself.comparisons = 0self.swaps = 0self.sample_target = 0  # 查找的目标值self.last_size = sizeself.is_running = False  # 标记是否正在运行演示self.setup_ui()self.initialize_data()def setup_ui(self):"""设置用户界面"""# 创建主框架self.main_frame = ttk.Frame(self.root, padding="10")self.main_frame.pack(fill=tk.BOTH, expand=True)# 左侧框架:算法选择和信息展示self.left_frame = ttk.LabelFrame(self.main_frame, text="算法选择与信息", padding="10")self.left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=5, pady=5)self.setup_algorithm_selection()self.setup_info_display()self.setup_demo_button()# 右侧框架:可视化和控制self.right_frame = ttk.LabelFrame(self.main_frame, text="算法演示", padding="10")self.right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)self.setup_visualization()self.setup_control_panel()self.setup_stats_display()self.setup_instructions()def setup_algorithm_selection(self):"""设置算法选择区域"""ttk.Label(self.left_frame, text="选择算法:", font=self.subtitle_font).pack(anchor=tk.W)self.algorithm_listbox = tk.Listbox(self.left_frame, width=30, height=10, font=self.normal_font)self.algorithm_listbox.pack(fill=tk.BOTH, expand=True, pady=5)algorithms = ["冒泡排序", "选择排序", "快速排序", "归并排序", "顺序查找", "二分查找"]for algo in algorithms:self.algorithm_listbox.insert(tk.END, algo)self.algorithm_listbox.bind('<<ListboxSelect>>', self.on_algorithm_select)self.algorithm_listbox.select_set(0)self.current_algorithm = "冒泡排序"def setup_info_display(self):"""设置信息显示区域(添加了滚动条)"""ttk.Label(self.left_frame, text="算法说明:", font=self.subtitle_font).pack(anchor=tk.W, pady=(10, 5))# 创建一个框架来包含文本框和滚动条info_frame = ttk.Frame(self.left_frame)info_frame.pack(fill=tk.BOTH, expand=True, pady=5)# 创建垂直滚动条scrollbar = ttk.Scrollbar(info_frame)scrollbar.pack(side=tk.RIGHT, fill=tk.Y)# 创建文本框并关联滚动条self.info_text = tk.Text(info_frame, width=30, height=15, wrap=tk.WORD, font=self.normal_font, yscrollcommand=scrollbar.set)self.info_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)self.info_text.config(state=tk.DISABLED)# 配置滚动条scrollbar.config(command=self.info_text.yview)def setup_demo_button(self):"""设置演示按钮"""self.start_button = ttk.Button(self.left_frame, text="开始演示", command=self.start_demo)self.start_button.pack(fill=tk.X, pady=10)def setup_visualization(self):"""设置可视化区域"""self.fig, self.ax = plt.subplots(figsize=(7, 5))self.canvas = FigureCanvasTkAgg(self.fig, master=self.right_frame)self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)def setup_control_panel(self):"""设置控制面板"""self.control_frame = ttk.Frame(self.right_frame)self.control_frame.pack(fill=tk.X, pady=10)ttk.Label(self.control_frame, text="数据大小:", font=self.normal_font).pack(side=tk.LEFT, padx=5)self.size_var = tk.IntVar(value=self.size)self.size_scale = ttk.Scale(self.control_frame, from_=5, to=30, orient=tk.HORIZONTAL, variable=self.size_var, length=150)self.size_scale.pack(side=tk.LEFT, padx=5)self.size_label = ttk.Label(self.control_frame, text=str(self.size), width=3)self.size_label.pack(side=tk.LEFT, padx=5)self.size_scale.bind("<Motion>", self.update_size_label)self.size_scale.bind("<ButtonRelease-1>", self.apply_size_change)self.reset_button = ttk.Button(self.control_frame, text="重置数据", command=self.reset_data)self.reset_button.pack(side=tk.RIGHT, padx=5)def setup_stats_display(self):"""设置统计信息显示"""self.stats_frame = ttk.Frame(self.right_frame)self.stats_frame.pack(fill=tk.X, pady=5)self.comparisons_var = tk.StringVar(value="比较次数: 0")self.swaps_var = tk.StringVar(value="交换次数: 0")ttk.Label(self.stats_frame, textvariable=self.comparisons_var, font=self.normal_font).pack(side=tk.LEFT, padx=10)ttk.Label(self.stats_frame, textvariable=self.swaps_var, font=self.normal_font).pack(side=tk.LEFT, padx=10)def setup_instructions(self):"""设置使用说明"""self.instruction_frame = ttk.LabelFrame(self.right_frame, text="使用说明", padding="5")self.instruction_frame.pack(fill=tk.X, pady=5)instruction_text = ("1. 调整'数据大小'滑块或点击'重置数据'按钮设置数据\n""2. 从左侧选择要演示的算法\n""3. 点击'开始演示'在当前数据上运行算法")ttk.Label(self.instruction_frame, text=instruction_text, font=self.normal_font, foreground="blue").pack(anchor=tk.W, padx=5)def initialize_data(self):"""初始化数据"""self.generate_new_data()self.update_info_text()self.update_display()def generate_new_data(self):"""生成新的数据"""self.data = list(range(1, self.size + 1))random.shuffle(self.data)self.sample_target = random.choice(self.data)  # 确保目标值在数组中self.reset_statistics()def reset_statistics(self):"""重置统计信息"""self.comparisons = 0self.swaps = 0self.update_statistics_display()def update_statistics_display(self):"""更新统计信息显示"""self.comparisons_var.set(f"比较次数: {self.comparisons}")self.swaps_var.set(f"交换次数: {self.swaps}")def update_size_label(self, event):"""更新数据大小标签"""value = int(self.size_scale.get())self.size_label.config(text=str(value))self.size = valuedef apply_size_change(self, event):"""应用数据大小改变"""if self.size != self.last_size:self.last_size = self.sizeself.generate_new_data()self.update_info_text()self.update_display()def reset_data(self):"""重置数据 - 响应用户点击重置按钮"""self.generate_new_data()self.update_info_text()self.update_display()def update_display(self):"""根据当前选中的算法更新数据显示"""if self.current_algorithm == "顺序查找":# 顺序查找使用原始乱序数据self.visualize_data(self.data, ["lightblue"] * len(self.data), f"{self.current_algorithm}初始数据(无需排序)- 目标值: {self.sample_target}")elif self.current_algorithm == "二分查找":# 二分查找需要有序数据sorted_data = sorted(self.data)self.visualize_data(sorted_data, ["lightblue"] * len(sorted_data), f"{self.current_algorithm}初始数据(已排序)- 目标值: {self.sample_target}")else:# 其他排序算法显示原始乱序数据self.visualize_data(self.data, ["lightblue"] * len(self.data), "当前数据")def visualize_data(self, data, colors, title=""):"""可视化数据"""self.ax.clear()bars = self.ax.bar(range(len(data)), data, color=colors)self.ax.set_title(title, fontsize=14)self.ax.set_xlabel("索引")self.ax.set_ylabel("值")self.ax.set_xticks(range(len(data)))self.ax.set_xticklabels(range(len(data)))# 添加数值标签(当数据量不太大时)if len(data) <= 20:for i, bar in enumerate(bars):height = bar.get_height()self.ax.text(bar.get_x() + bar.get_width()/2., height + 0.1,f'{int(height)}', ha='center', va='bottom', fontsize=8)self.canvas.draw()self.root.update()def on_algorithm_select(self, event):"""当选择算法时的处理"""if self.is_running:# 如果正在演示,恢复之前的选择self.restore_algorithm_selection()returnselection = self.algorithm_listbox.curselection()if not selection:returnold_algorithm = self.current_algorithmself.current_algorithm = self.algorithm_listbox.get(selection[0])# 如果切换到查找算法,确保目标值有效if old_algorithm != self.current_algorithm and self.current_algorithm in ["二分查找", "顺序查找"]:self.sample_target = random.choice(self.data)self.update_info_text()self.update_display()def restore_algorithm_selection(self):"""恢复算法选择"""if self.current_algorithm:algorithms = ["冒泡排序", "选择排序", "快速排序", "归并排序", "顺序查找", "二分查找"]try:index = algorithms.index(self.current_algorithm)self.algorithm_listbox.select_clear(0, tk.END)self.algorithm_listbox.select_set(index)except ValueError:passdef update_info_text(self):"""更新算法说明文本"""self.info_text.config(state=tk.NORMAL)self.info_text.delete(1.0, tk.END)text = self.get_algorithm_description()self.info_text.insert(tk.END, text)self.info_text.config(state=tk.DISABLED)def get_algorithm_description(self):"""获取算法描述文本"""if self.current_algorithm == "冒泡排序":return (f"冒泡排序 (Bubble Sort)\n\n"f"开始演示冒泡排序!\n\n"f"数据:{self.data}\n\n"f"算法思想:\n"f"1. 比较相邻的元素,如果顺序错误就把它们交换过来\n"f"2. 重复此步骤,直到整个数组排序完成\n\n"f"特点:\n"f"- 简单易懂,但效率较低\n"f"- 时间复杂度:O(n²)\n"f"- 空间复杂度:O(1)\n\n"f"类比:就像水中的泡泡,大的总会浮到上面!")elif self.current_algorithm == "选择排序":return (f"选择排序 (Selection Sort)\n\n"f"开始演示选择排序!\n\n"f"数据:{self.data}\n\n"f"算法思想:\n"f"1. 在未排序序列中找到最小元素,存放到排序序列的起始位置\n"f"2. 再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾\n"f"3. 重复第二步,直到所有元素均排序完毕\n\n"f"特点:\n"f"- 简单直接,不依赖数据分布\n"f"- 时间复杂度:O(n²)\n"f"- 空间复杂度:O(1)\n\n"f"类比:就像选班长,每次找最优秀的!")elif self.current_algorithm == "顺序查找":return (f"顺序查找 (Sequential Search)\n\n"f"开始演示顺序查找!\n\n"f"数据:{self.data}\n"f"数据不需要排序。\n" f"目标值:{self.sample_target}\n\n"f"算法思想:\n"f"从数组的第一个元素开始,逐个与目标值进行比较,直到找到目标值或遍历完整个数组。\n\n"f"特点:\n"f"- 简单直接,适用于任何类型的数组,无论是否有序。\n"f"- 时间复杂度:O(n)\n"f"- 空间复杂度:O(1)\n\n"f"重要提示:顺序查找不需要数据有序!\n\n"f"类比:就像在一排人中挨个找某个人!")elif self.current_algorithm == "二分查找":sorted_data = sorted(self.data)return (f"二分查找 (Binary Search)\n\n"f"开始演示二分查找!\n\n"f"数据:{sorted_data}\n"f"数据需要已排序。\n" f"目标值:{self.sample_target}\n\n"f"算法思想:\n"f"1. 将数组分成两部分,比较中间元素与目标值\n"f"2. 如果中间元素等于目标值,则查找成功\n"f"3. 如果中间元素大于目标值,则在左半部分继续查找\n"f"4. 如果中间元素小于目标值,则在右半部分继续查找\n"f"5. 重复此过程,直到找到目标值或确定目标值不存在\n\n"f"特点:\n"f"- 要求数组必须有序\n"f"- 时间复杂度:O(log n)\n"f"- 空间复杂度:O(1)\n\n"f"重要提示:二分查找必须在有序数据上进行!\n\n"f"类比:就像猜数字游戏!我说大了或小了,你来猜!")elif self.current_algorithm == "快速排序":return (f"快速排序 (Quick Sort)\n\n"f"开始演示快速排序!\n\n"f"数据:{self.data}\n\n"f"算法思想:\n"f"1. 选择一个基准值(pivot)\n"f"2. 将数组分为两部分,小于基准值的元素放在左边,大于基准值的元素放在右边\n"f"3. 对左右两部分分别递归进行快速排序\n\n"f"特点:\n"f"- 高效,平均时间复杂度低\n"f"- 时间复杂度:O(n log n)\n"f"- 空间复杂度:O(log n)\n\n"f"类比:就像整理扑克牌!选一张牌作为基准,小的放左边,大的放右边")elif self.current_algorithm == "归并排序":return (f"归并排序 (Merge Sort)\n\n"f"开始演示归并排序!\n\n"f"数据:{self.data}\n\n"f"算法思想:\n"f"1. 将数组分成两个子数组\n"f"2. 递归地对子数组进行排序\n"f"3. 合并两个已排序的子数组\n\n"f"特点:\n"f"- 稳定排序算法\n"f"- 时间复杂度:O(n log n)\n"f"- 空间复杂度:O(n)\n\n"f"类比:就像合并两个排好队的队伍!先分成小组排序,再合并成大组")else:return ("请选择一个算法进行演示\n\n""可选算法:\n""- 冒泡排序\n""- 选择排序\n""- 快速排序\n""- 归并排序\n""- 顺序查找\n""- 二分查找")def set_running_state(self, running):"""设置运行状态"""self.is_running = runningif running:self.start_button.config(text="正在演示...", state=tk.DISABLED)self.algorithm_listbox.config(state=tk.DISABLED)self.size_scale.config(state=tk.DISABLED)self.reset_button.config(state=tk.DISABLED)else:self.start_button.config(text="开始演示", state=tk.NORMAL)self.algorithm_listbox.config(state=tk.NORMAL)self.size_scale.config(state=tk.NORMAL)self.reset_button.config(state=tk.NORMAL)def start_demo(self):"""开始演示所选算法 - 在用户当前数据上演示"""if not self.current_algorithm:messagebox.showwarning("警告", "请先选择一个算法")returnif self.is_running:return# 重要:只重置统计信息,保持用户数据不变self.reset_statistics()self.set_running_state(True)try:if self.current_algorithm == "冒泡排序":self.bubble_sort_demo()elif self.current_algorithm == "选择排序":self.selection_sort_demo()elif self.current_algorithm == "顺序查找":self.sequential_search_demo()elif self.current_algorithm == "二分查找":self.binary_search_demo()elif self.current_algorithm == "快速排序":self.quick_sort_demo()elif self.current_algorithm == "归并排序":self.merge_sort_demo()finally:self.set_running_state(False)def bubble_sort_demo(self):"""冒泡排序演示"""messagebox.showinfo("冒泡排序", f"开始演示冒泡排序!\n\n数据:{self.data}")# 使用用户数据的副本进行演示data = self.data.copy()n = len(data)for i in range(n):for j in range(0, n-i-1):self.comparisons += 1self.update_statistics_display()# 高亮当前比较的元素colors = ["lightblue"] * ncolors[j] = "red"colors[j+1] = "red"# 已排序部分显示为绿色for k in range(n-i, n):colors[k] = "lightgreen"self.visualize_data(data, colors, f"冒泡排序中 - 比较 {data[j]} 和 {data[j+1]}")time.sleep(0.5)if data[j] > data[j+1]:self.swaps += 1self.update_statistics_display()data[j], data[j+1] = data[j+1], data[j]# 高亮交换后的元素colors[j] = "green"colors[j+1] = "green"for k in range(n-i, n):colors[k] = "lightgreen"self.visualize_data(data, colors, f"冒泡排序中 - 交换 {data[j]} 和 {data[j+1]}")time.sleep(0.5)# 全部排序完成self.visualize_data(data, ["lightgreen"] * n, "冒泡排序完成!")messagebox.showinfo("冒泡排序", f"排序完成!\n比较次数: {self.comparisons}\n交换次数: {self.swaps}")def selection_sort_demo(self):"""选择排序演示"""messagebox.showinfo("选择排序", f"开始演示选择排序!\n\n数据:{self.data}")# 使用用户数据的副本进行演示data = self.data.copy()n = len(data)for i in range(n):min_idx = ifor j in range(i+1, n):self.comparisons += 1self.update_statistics_display()# 高亮当前比较的元素colors = ["lightblue"] * ncolors[min_idx] = "yellow"  # 当前最小值colors[j] = "red"           # 当前比较的元素for k in range(i):colors[k] = "lightgreen"  # 已排序元素self.visualize_data(data, colors, f"选择排序中 - 寻找最小值,当前最小: {data[min_idx]}")time.sleep(0.5)if data[j] < data[min_idx]:min_idx = jif min_idx != i:self.swaps += 1self.update_statistics_display()data[i], data[min_idx] = data[min_idx], data[i]# 高亮交换后的元素colors = ["lightblue"] * ncolors[i] = "green"colors[min_idx] = "green"for k in range(i+1):colors[k] = "lightgreen"self.visualize_data(data, colors, f"选择排序中 - 将最小值 {data[i]} 放到位置 {i}")time.sleep(0.5)# 全部排序完成self.visualize_data(data, ["lightgreen"] * n, "选择排序完成!")messagebox.showinfo("选择排序", f"排序完成!\n比较次数: {self.comparisons}\n交换次数: {self.swaps}")def sequential_search_demo(self):"""顺序查找演示 - 使用原始乱序数据"""data = self.data.copy()  # 使用原始数据,不排序target = self.sample_targetmessagebox.showinfo("顺序查找", f"开始演示顺序查找!\n\n数据:{data}\n目标值:{target}\n\n注意:顺序查找不需要数据有序!")self.visualize_data(data, ["lightblue"] * len(data), f"顺序查找:寻找 {target}")found = Falsefor i, num in enumerate(data):self.comparisons += 1self.update_statistics_display()# 高亮当前比较的元素colors = ["lightblue"] * len(data)colors[i] = "red"self.visualize_data(data, colors, f"顺序查找:比较索引 {i} 的值 {num} 与目标值 {target}")time.sleep(1.0)if num == target:colors[i] = "green"self.visualize_data(data, colors, f"顺序查找:找到 {target} 在位置 {i}")found = Truebreakif not found:self.visualize_data(data, ["lightblue"] * len(data), f"顺序查找:未找到 {target}")messagebox.showinfo("顺序查找", f"未找到 {target}!\n比较次数: {self.comparisons}")else:messagebox.showinfo("顺序查找", f"查找完成!\n{target} 在位置 {i}\n比较次数: {self.comparisons}")def binary_search_demo(self):"""二分查找演示 - 使用排序后的数据"""data = sorted(self.data)  # 必须使用有序数据target = self.sample_targetmessagebox.showinfo("二分查找", f"开始演示二分查找!\n\n数据:{data}\n目标值:{target}\n\n注意:二分查找必须在有序数据上进行!")self.visualize_data(data, ["lightblue"] * len(data), f"二分查找:寻找 {target}")left, right = 0, len(data) - 1found = Falsemid = -1while left <= right:mid = (left + right) // 2self.comparisons += 1self.update_statistics_display()# 高亮当前查找范围和中间元素colors = ["lightgray"] * len(data)for i in range(left, right+1):colors[i] = "lightblue"colors[mid] = "red"self.visualize_data(data, colors, f"二分查找:寻找 {target},当前中间值 {data[mid]}")time.sleep(1.0)if data[mid] == target:colors[mid] = "green"self.visualize_data(data, colors, f"二分查找:找到 {target} 在位置 {mid}")found = Truebreakelif data[mid] < target:left = mid + 1messagebox.showinfo("二分查找", f"{data[mid]} 小于 {target},在右半部分继续查找")else:right = mid - 1messagebox.showinfo("二分查找", f"{data[mid]} 大于 {target},在左半部分继续查找")if not found:self.visualize_data(data, ["lightblue"] * len(data), f"二分查找:未找到 {target}")messagebox.showinfo("二分查找", f"未找到 {target}!\n比较次数: {self.comparisons}")else:messagebox.showinfo("二分查找", f"查找完成!\n{target} 在位置 {mid}\n比较次数: {self.comparisons}")def quick_sort_demo(self):"""快速排序演示"""messagebox.showinfo("快速排序", f"开始演示快速排序!\n\n数据:{self.data}")# 使用用户数据的副本进行演示data = self.data.copy()self.quick_sort(data, 0, len(data) - 1)self.visualize_data(data, ["lightgreen"] * len(data), "快速排序完成!")messagebox.showinfo("快速排序", f"排序完成!\n比较次数: {self.comparisons}\n交换次数: {self.swaps}")def partition(self, data, low, high):"""快速排序分区函数"""pivot = data[high]i = low - 1# 高亮分区范围colors = ["lightgray"] * len(data)for idx in range(low, high+1):colors[idx] = "lightblue"colors[high] = "red"  # 基准值self.visualize_data(data, colors, f"快速排序分区中 - 基准值: {pivot}")time.sleep(0.7)for j in range(low, high):self.comparisons += 1self.update_statistics_display()# 高亮当前比较的元素和基准值colors = ["lightgray"] * len(data)for idx in range(low, high+1):colors[idx] = "lightblue"colors[j] = "yellow"    # 当前比较的元素colors[high] = "red"    # 基准值for k in range(low, i+1):if k < len(colors):colors[k] = "lightgreen"  # 小于基准值的元素self.visualize_data(data, colors, f"快速排序分区中 - 比较 {data[j]} 与基准值 {pivot}")time.sleep(0.5)if data[j] <= pivot:i += 1if i != j:self.swaps += 1self.update_statistics_display()data[i], data[j] = data[j], data[i]# 高亮交换后的元素colors[i] = "green"colors[j] = "green"self.visualize_data(data, colors, f"快速排序分区中 - 交换 {data[i]} 和 {data[j]}")time.sleep(0.5)self.swaps += 1self.update_statistics_display()data[i+1], data[high] = data[high], data[i+1]# 高亮基准值的最终位置colors = ["lightblue"] * len(data)for k in range(low, i+1):if k < len(colors):colors[k] = "lightgreen"if i+1 < len(colors):colors[i+1] = "red"  # 基准值的最终位置for k in range(i+2, high+1):if k < len(colors):colors[k] = "lightcoral"  # 大于基准值的元素self.visualize_data(data, colors, f"快速排序分区完成 - 基准值 {data[i+1]} 已就位")time.sleep(0.7)return i + 1def quick_sort(self, data, low, high):"""快速排序递归函数"""if low < high:pi = self.partition(data, low, high)self.quick_sort(data, low, pi-1)self.quick_sort(data, pi+1, high)def merge_sort_demo(self):"""归并排序演示"""messagebox.showinfo("归并排序", f"开始演示归并排序!\n\n数据:{self.data}")# 使用用户数据的副本进行演示data = self.data.copy()self.merge_sort(data, 0, len(data) - 1)self.visualize_data(data, ["lightgreen"] * len(data), "归并排序完成!")messagebox.showinfo("归并排序", f"排序完成!\n比较次数: {self.comparisons}\n赋值次数: {self.swaps}")def merge(self, data, left, mid, right):"""归并排序合并函数"""n1 = mid - left + 1n2 = right - mid# 创建临时数组L = [0] * n1R = [0] * n2# 复制数据到临时数组 L[] 和 R[]for i in range(n1):L[i] = data[left + i]for j in range(n2):R[j] = data[mid + 1 + j]# 高亮左右子数组colors = ["lightblue"] * len(data)for i in range(left, mid+1):colors[i] = "lightgreen"for j in range(mid+1, right+1):colors[j] = "lightcoral"self.visualize_data(data, colors, f"归并排序:准备合并 [{left}..{mid}] 和 [{mid+1}..{right}]")time.sleep(0.7)# 归并临时数组到 data[left..right]i = j = 0  # 初始化第一个和第二个子数组的索引k = left   # 初始归并子数组的索引while i < n1 and j < n2:self.comparisons += 1self.update_statistics_display()# 高亮当前比较的元素colors = ["lightblue"] * len(data)for idx in range(left, k):colors[idx] = "green"  # 已合并的元素self.visualize_data(data, colors, f"归并排序:比较 {L[i]} 和 {R[j]}")time.sleep(0.5)if L[i] <= R[j]:data[k] = L[i]i += 1else:data[k] = R[j]j += 1k += 1self.swaps += 1  # 统计赋值操作self.update_statistics_display()# 显示合并后的结果colors = ["lightblue"] * len(data)for idx in range(left, k):colors[idx] = "green"self.visualize_data(data, colors, f"归并排序:已合并到位置 {k-1}")time.sleep(0.3)# 复制 L[] 的保留元素while i < n1:data[k] = L[i]i += 1k += 1self.swaps += 1  # 统计赋值操作self.update_statistics_display()# 复制 R[] 的保留元素while j < n2:data[k] = R[j]j += 1k += 1self.swaps += 1  # 统计赋值操作self.update_statistics_display()# 高亮已合并的数组colors = ["lightblue"] * len(data)for idx in range(left, right+1):colors[idx] = "green"self.visualize_data(data, colors, f"归并排序:合并完成 [{left}..{right}]")time.sleep(0.7)def merge_sort(self, data, left, right):"""归并排序递归函数"""if left < right:mid = (left + right) // 2# 分割并排序左半部分self.merge_sort(data, left, mid)# 分割并排序右半部分self.merge_sort(data, mid + 1, right)# 合并已排序的两部分self.merge(data, left, mid, right)if __name__ == "__main__":root = tk.Tk()app = AlgorithmVisualizerGUI(root)root.mainloop()

附录

附录给出打包可执行程序,win10中可用 https://download.csdn.net/download/cnds123/91382304


文章转载自:
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://www.dtcms.com/a/281727.html

相关文章:

  • Sa-Token使用要点
  • mongoDB安装初始化及简单介绍
  • 2025/7/15——java学习总结
  • Pandas 和 NumPy 使用文档整理
  • 大宗现货电子盘交易系统核心功能代码解析
  • QT6 源,六章事件系统(8)QEvent 的孙子类:QEnterEvent 光标进入
  • 无穿戴动捕如何凭借摄像头视觉识别算法,赋能高校专业教学革新?
  • python进阶
  • 145-变分模态分解VMD与平稳小波变换SWT信号降噪算法实现!
  • 4G模块 A7680通过MQTT协议连接到onenet(新版)
  • WebAPIs基本认知,DOM基础介绍
  • 基于Springboot+UniApp+Ai实现模拟面试小工具五:权限校验参数校验及日志功能实现
  • Ubuntu 22.04 安装 mysql-server与 postgreSQL 服务端
  • el-tooltip 快速滚动的时候出现残影如何解决 vue3
  • 30.安卓逆向2-frida hook技术-hook So文件(获取app加载的所有模块、导入函数、导出函数、hook SO函数)
  • 区块链发展史全景长图
  • 强化学习Reinforcement Learning
  • 基于Python的图像文字识别系统
  • Glide双内存缓存加载机制详细介绍
  • K型热电偶电动势以及温度对照表
  • 驱动开发系列61- Vulkan 驱动实现-SPIRV到HW指令的实现过程(2)
  • [Science]论文 视黄素与细胞修复
  • 2025-07-15通过边缘线检测图像里的主体有没有出血
  • IMU 能为无人机提供什么数据?
  • 【论文阅读】A Survey on Knowledge-Oriented Retrieval-Augmented Generation(3)
  • 移动端字体适配
  • 谷歌浏览器控制台如何切换中文
  • StampedLock分析
  • 链表的 哑结点的本质
  • Python 程序设计讲义(1):PyCharm 安装教程