基于Python实现的单词统计与查找分析工具

作者:

文章目录
  • 单词统计与查找分析工具是一款面向 “单词统计 + 查找算法对比” 的可视化工具,核心目标是实现文本中单词的标准化解析、多策略(顺序查找 / 快排 + 二分 / 哈希表)统计,并计算关键指标(Total Words、Unique Words、ASL 平均查找长度)。本文将详细讲解该工具的开发过程以及Python代码完整实现(原始版 + 扩展版)。
  • 开发前先明确工具的核心目标与边界,确保功能贴合 “数据结构与算法实践” 的场景需求:
  • 结合 “算法实践 + 可视化交互” 的核心需求,选择轻量、易理解的技术栈: 技术 / 模块 选型理由 Python 3.8+ 语法简洁,数据结构(列表、字典)原生支持,算法实现直观,适合教学 / 实践场景 tkinter + ttk Python 内置 GUI 库,无需额外安装,足够支撑轻量交互界面;ttk 提升控件美观度 原生数据结构(列表) 模拟线性表、哈希表(链地址法),无需第三方库,降低学习 / 使用成本 Time33 哈希函数 简单高效的字符串哈希算法(h = h*33 + ord(char)),分布均匀,冲突率低 快速排序 + 二分查找 经典排序 / 查找算法组合,对比顺序查找体现 “有序表 + 二分” 的效率优势
  • 采用 “模块化 + 面向对象” 混合设计,核心分为三层,确保逻辑解耦、便于维护: classDiagram direction LR “全局常量层” –> “核心算法层” : 依赖常量配置 “核心算法层” –> “GUI交互层” : 提供算法调用 “GUI交互层” –> “核心算法层” : 传递业务数据 class 全局常量层 { MAX_LINEAR_SIZE: int = 10000 HASH_SIZE: int = 1009 MAX_WORD_LEN: int = 50 } class 核心算法层 { +normalize(token, pos): (bool, str) # 单词标准化 +my_hash(word): int # Time33哈希 +linear_search(linear_list, word): (bool, int) # 顺序查找 +quick_sort(linear_list, low, high) # 快速排序 +binary_search(linear_list, word): (bool, int) # 二分查找 } class GUI交互层 { -root: tk.Tk -strategy_var: tk.StringVar +_setup_ui() # 搭建UI +_on_text_changed(event) # 文本输入监控 +_on_strategy_toggled() # 策略切换 +_on_analyze_clicked() # 分析按钮逻辑 +_update_result(text, color) # 更新结果展示 } HTML代码: <!DOCTYPE html> <html lang=”zh-CN”> <head> <meta charset=”UTF-8″> <meta name=”viewport” content=”width=device-width, initial-scale=1.0″> <title>单词统计工具 – 架构类图</title> <!– 引入Mermaid CDN –> <script src=”https://cdn.jsdelivr.net/npm/mermaid@10.16.0/dist/mermaid.min.js”></script> <style> body { font-family: “Microsoft YaHei”, Arial, sans-serif; padding: 20px; background: #f5f5f5; } .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h1 { text-align: center; color: #333; margin-bottom: 30px; } /* 确保Mermaid代码保留换行格式 */ .mermaid { white-space: pre; font-family: monospace; } </style> </head> <body> <div class=”container”> <h1>单词统计与查找分析工具 – 架构类图</h1> <!– Mermaid类图代码(直接放在mermaid容器中,保留原始格式) –> <div class=”mermaid”> classDiagram direction LR %% 层间关联 全局常量层 –> 核心算法层 : 依赖常量配置 核心算法层 –> GUI交互层 : 提供算法调用 GUI交互层 –> 核心算法层 : 传递业务数据 %% 全局常量层 class 全局常量层 { MAX_LINEAR_SIZE: int = 10000 HASH_SIZE: int = 1009 MAX_WORD_LEN: int = 50 } %% 核心算法层 class 核心算法层 { +normalize(token, pos): (bool, str) // 单词标准化 +my_hash(word): int // Time33哈希 +linear_search(linear_list, word): (bool, int) // 顺序查找 +quick_sort(linear_list, low, high) // 快速排序 +binary_search(linear_list, word): (bool, int) // 二分查找 } %% GUI交互层 class GUI交互层 { -root: tk.Tk -strategy_var: tk.StringVar +_setup_ui() // 搭建UI +_on_text_changed(event) // 文本输入监控 +_on_strategy_toggled() // 策略切换 +_on_analyze_clicked() // 分析按钮逻辑 +_update_result(text, color) // 更新结果展示 } </div> </div> <script> // 初始化Mermaid,启用自动加载 mermaid.initialize({ startOnLoad: true, theme: ‘default’, classDiagram: { fontSize: 14, nodeSpacing: 30, rankSpacing: 40 } }); </script> </body> </html> 核心设计思路: 全局常量层:集中管理配置参数(如哈希表大小、线性表最大容量),便于统一修改; 核心算法层:纯函数式设计,与 GUI 解耦,可独立测试 / 复用(比如单独调用算法函数验证逻辑); GUI 交互层:面向对象封装,负责界面渲染、事件处理、业务逻辑串联(调用算法 + 展示结果)。
  • 开发完成后,覆盖多场景测试并优化体验,确保工具稳定可用:
  • import tkinter as tk from tkinter import ttk, messagebox import re import sys # ===================== 全局常量 ===================== MAX_LINEAR_SIZE = 10000 # 线性表最大容量 HASH_SIZE = 1009 # 哈希表大小(强制1009) MAX_WORD_LEN = 50 # 单词最大长度 # ===================== 核心算法函数 ===================== def normalize(token: str, pos: list) -> tuple[bool, str]: “”” 标准化单词:跳过非字母字符,提取连续字母并转小写 :param token: 待处理字符串 :param pos: 当前处理位置(用列表传引用,Python整数不可变) :return: (是否提取到单词, 标准化后的单词) “”” # 跳过非字母字符 while pos[0] < len(token) and not token[pos[0]].isalpha(): pos[0] += 1 if pos[0] >= len(token): return False, “” # 提取连续字母并转小写 word = [] while pos[0] < len(token) and token[pos[0]].isalpha(): word.append(token[pos[0]].lower()) pos[0] += 1 return True, ”.join(word) def my_hash(word: str) -> int: “””Time33哈希函数””” h = 0 for char in word: h = (h << 5) + h + ord(char) # h = h*33 + 字符ASCII return h % HASH_SIZE def linear_search(linear_list: list, word: str) -> tuple[bool, int]: “”” 顺序查找 :return: (是否找到, 比较次数) “”” cmp_count = 0 for item in linear_list: cmp_count += 1 if item[“word”] == word: return True, cmp_count return False, cmp_count # 快速排序相关函数(按单词字典序) def swap_linear_node(linear_list: list, i: int, j: int): “””交换线性表中的两个元素””” linear_list[i], linear_list[j] = linear_list[j], linear_list[i] def partition(linear_list: list, low: int, high: int) -> int: “””快排分区函数””” pivot = linear_list[high][“word”] i = low – 1 # 小于基准的区域边界 for j in range(low, high): if linear_list[j][“word”] < pivot: i += 1 swap_linear_node(linear_list, i, j) swap_linear_node(linear_list, i + 1, high) return i + 1 def quick_sort(linear_list: list, low: int, high: int): “””快速排序主函数””” if low < high: pi = partition(linear_list, low, high) quick_sort(linear_list, low, pi – 1) quick_sort(linear_list, pi + 1, high) def binary_search(linear_list: list, word: str) -> tuple[bool, int]: “”” 二分查找(需先排序) :return: (是否找到, 比较次数) “”” cmp_count = 0 low, high = 0, len(linear_list) – 1 while low <= high: cmp_count += 1 mid = (low + high) // 2 mid_word = linear_list[mid][“word”] if mid_word == word: return True, cmp_count elif mid_word > word: high = mid – 1 else: low = mid + 1 return False, cmp_count # ===================== GUI主类 ===================== class WordAnalyzerApp: def __init__(self, root): self.root = root self.root.title(“单词统计与查找分析工具”) self.root.geometry(“800×600″) # 策略选择变量 self.strategy_var = tk.StringVar(value=”1”) # 初始化UI self._setup_ui() def _setup_ui(self): “””构建GUI界面””” # 主容器 main_frame = ttk.Frame(self.root, padding=”20″) main_frame.pack(fill=tk.BOTH, expand=True) # 1. 文本输入区域 input_label = ttk.Label(main_frame, text=”请输入待分析文本(输入#结束):”) input_label.pack(anchor=tk.W) self.text_input = tk.Text(main_frame, height=10, wrap=tk.WORD) self.text_input.pack(fill=tk.X, pady=(0, 5)) # 实时提示标签 self.input_tip_label = ttk.Label(main_frame, text=””, foreground=”#666666″) self.input_tip_label.pack(anchor=tk.W) # 绑定文本实时监控事件 self.text_input.bind(“<<Modified>>”, self._on_text_changed) self.text_input_modified = False # 防止重复触发 # 2. 策略选择区域 strategy_frame = ttk.LabelFrame(main_frame, text=”查找策略选择”, padding=”10″) strategy_frame.pack(fill=tk.X, pady=(10, 5)) # 策略单选按钮 ttk.Radiobutton( strategy_frame, text=”策略1:顺序查找”, variable=self.strategy_var, value=”1″, command=self._on_strategy_toggled ).pack(side=tk.LEFT, padx=10) ttk.Radiobutton( strategy_frame, text=”策略2:快速排序+二分查找”, variable=self.strategy_var, value=”2″, command=self._on_strategy_toggled ).pack(side=tk.LEFT, padx=10) ttk.Radiobutton( strategy_frame, text=”策略3:哈希表查找”, variable=self.strategy_var, value=”3″, command=self._on_strategy_toggled ).pack(side=tk.LEFT, padx=10) # 3. 分析按钮 analyze_btn = ttk.Button( main_frame, text=”开始分析”, command=self._on_analyze_clicked ) analyze_btn.pack(pady=(10, 10)) # 4. 结果显示区域 result_label = ttk.Label(main_frame, text=”分析结果:”) result_label.pack(anchor=tk.W) self.result_display = tk.Text(main_frame, height=10, wrap=tk.WORD, state=tk.DISABLED) self.result_display.pack(fill=tk.BOTH, expand=True) def _on_text_changed(self, event): “””文本输入实时监控””” if self.text_input_modified: return self.text_input_modified = True # 获取输入文本 input_text = self.text_input.get(“1.0”, tk.END).strip() char_count = len(input_text) has_sharp = “#” in input_text # 更新提示文本 tip = f”实时状态:已输入 {char_count} 个字符 | ” if has_sharp: tip += “检测到#,分析时会截断#后的内容” self.input_tip_label.config(foreground=”#E67E22″) else: tip += “未检测到#,将分析全部文本” self.input_tip_label.config(foreground=”#666666″) self.input_tip_label.config(text=tip) # 重置modified标志 self.text_input.edit_modified(False) self.text_input_modified = False def _on_strategy_toggled(self): “””策略切换反馈””” strategy_id = self.strategy_var.get() strategy_names = { “1”: “顺序查找”, “2”: “快速排序+二分查找”, “3”: “哈希表查找” } strategy_name = strategy_names.get(strategy_id, “未知”) # 清空结果区并提示 self._update_result(f”已切换为【{strategy_name}】策略,请点击「开始分析」重新计算结果”, “#3498DB”) def _update_result(self, text: str, color: str = “#000000”): “””更新结果显示区””” self.result_display.config(state=tk.NORMAL) self.result_display.delete(“1.0”, tk.END) self.result_display.insert(tk.END, text) self.result_display.config(foreground=color, state=tk.DISABLED) def _on_analyze_clicked(self): “””分析按钮点击事件””” # 1. 获取输入和策略 input_text = self.text_input.get(“1.0”, tk.END).strip() strategy = int(self.strategy_var.get()) # 处理#结束符 if “#” in input_text: input_text = input_text.split(“#”)[0] # 2. 初始化数据结构 linear_list = [] # 策略1/2:存储{“word”: xxx, “count”: xxx} hash_table = [[] for _ in range(HASH_SIZE)] # 策略3:哈希表(列表模拟链表) total_words = 0 unique_words = 0 total_cmp = 0 # 3. 解析并统计单词 pos = [0] # 用列表传引用 token = input_text while True: has_word, word = normalize(token, pos) if not has_word: break total_words += 1 # 策略1/2:线性表处理 if strategy in (1, 2): found, _ = linear_search(linear_list, word) if found: # 单词已存在,计数+1 for item in linear_list: if item[“word”] == word: item[“count”] += 1 break else: # 新增单词 linear_list.append({“word”: word, “count”: 1}) # 策略3:哈希表处理 elif strategy == 3: h = my_hash(word) found = False # 遍历哈希桶中的单词 for item in hash_table[h]: if item[“word”] == word: item[“count”] += 1 found = True break if not found: hash_table[h].append({“word”: word, “count”: 1}) # 4. 计算Unique Words和ASL if strategy == 1: # 顺序查找策略 unique_words = len(linear_list) for item in linear_list: _, cmp = linear_search(linear_list, item[“word”]) total_cmp += cmp asl = total_cmp / unique_words if unique_words > 0 else 0.0 elif strategy == 2: # 快排+二分查找策略 unique_words = len(linear_list) if unique_words > 0: quick_sort(linear_list, 0, unique_words – 1) for item in linear_list: _, cmp = binary_search(linear_list, item[“word”]) total_cmp += cmp asl = total_cmp / unique_words if unique_words > 0 else 0.0 elif strategy == 3: # 哈希表策略 # 统计唯一单词数 unique_words = 0 for bucket in hash_table: unique_words += len(bucket) # 统计总比较次数 for bucket in hash_table: for idx, item in enumerate(bucket): total_cmp += (idx + 1) # 链表位置从1开始 asl = total_cmp / unique_words if unique_words > 0 else 0.0 # 5. 显示结果 result = ( f”Total Words: {total_words}n” f”Unique Words: {unique_words}n” f”ASL: {asl:.2f}nn” “测试自动换行:这是一段很长的文本,用于验证结果区的自动换行功能是否生效,当文本长度超过控件宽度时,会自动换行显示,不需要手动添加换行符。” ) self._update_result(result) # ===================== 主函数 ===================== if __name__ == “__main__”: root = tk.Tk() app = WordAnalyzerApp(root) root.mainloop()
  • 本文介绍了一款单词统计与查找分析工具的设计与实现。该工具支持三种查找策略(顺序查找、快速排序+二分查找、哈希表查找),可计算文本中的单词总数、唯一单词数和平均查找长度(ASL)。工具采用Python开发,包含核心算法层和GUI交互层,具有文本标准化处理、实时状态提示和多策略对比功能。扩展版新增了文件导入、单词长度统计、频次排行榜和ASL可视化等功能,支持自定义哈希表大小。文章详细阐述了工具的技术选型、架构设计、核心算法实现和测试优化过程,并提供了完整的Python代码实现和打包方法。 以上就是基于Python实现的单词统计与查找分析工具的详细内容,更多关于Python单词统计与查找工具的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: Python可视化单词统计词频统计中文分词的实现步骤 Python实战之单词打卡统计 利用Python3实现统计大量单词中各字母出现的次数和频率的方法 python统计文章中单词出现次数实例 Python实现的统计文章单词次数功能示例
  • 目录
    • 一、引言
    • 二、第一阶段:需求分析与功能规划
      • 1. 核心业务需求
      • 2. 非功能需求
    • 三、第二阶段:技术选型
      • 四、第三阶段:架构设计
        • 五、第四阶段:分模块详细开发
          • 1. 全局常量层开发
          • 2. 核心算法层开发
            • (1)单词标准化函数(normalize)
            • (2)哈希函数(my_hash)
            • (3)顺序查找函数(linear_search)
            • (4)快速排序相关函数
            • (5)二分查找函数(binary_search)
          • 3. GUI 交互层开发(WordAnalyzerApp 类)
            • (1)初始化与 UI 搭建(init+ _setup_ui)
            • (2)事件绑定与反馈
            • (3)核心业务逻辑(_on_analyze_clicked)
        • 六、第五阶段:测试与优化
          • 1. 核心测试场景
            • 2. 关键优化点
            • 七、单词统计与查找分析工具的Python代码完整实现
              • 八、程序运行截图展示
                • 九、打包项目
                  • 步骤 1:创建并激活纯净虚拟环境
                    • 步骤 2:切换目录并快速打包
                      • 步骤 3:验证结果
                      • 十、单词统计与查找分析工具(增强版)
                        • (一)可扩展方向
                          • (二)单词统计与查找分析工具扩展后的Python代码完整实现
                            • (三)核心新增功能说明
                              • 1. 自定义哈希表大小
                              • 2. 文件导入功能
                              • 3. 单词长度统计
                              • 4. 单词频次排行榜
                              • 5. ASL 算法对比可视化
                            • (四)使用注意事项
                              • (五)程序运行截图展示
                                • (六)打包项目
                                • 十一、总结

                                  单词统计与查找分析工具是一款面向 “单词统计 + 查找算法对比” 的可视化工具,核心目标是实现文本中单词的标准化解析、多策略(顺序查找 / 快排 + 二分 / 哈希表)统计,并计算关键指标(Total Words、Unique Words、ASL 平均查找长度)。本文将详细讲解该工具的开发过程以及Python代码完整实现(原始版 + 扩展版)。

                                  开发前先明确工具的核心目标与边界,确保功能贴合 “数据结构与算法实践” 的场景需求:

                                  • 文本解析与单词标准化:提取文本中的纯字母单词(跳过数字 / 符号),统一转为小写,支持#作为文本结束符;
                                  • 多查找策略支持
                                    • 策略 1:基于线性表的顺序查找,统计单词频次;
                                    • 策略 2:线性表快速排序后执行二分查找,统计单词频次;
                                    • 策略 3:基于 Time33 哈希函数的哈希表(链地址法)查找,统计单词频次;
                                  • 关键指标计算
                                    • Total Words:解析出的单词总数(含重复);
                                    • Unique Words:唯一单词数;
                                    • ASL(Average Search Length):平均查找长度(算法效率核心指标);
                                  • 可视化交互:GUI 界面操作(无需命令行),实时反馈输入状态,清晰展示统计结果。

                                  • 易用性:实时提示输入字符数、#结束符检测;策略切换即时反馈,结果格式化展示;
                                  • 鲁棒性:处理空文本、超长单词、无字母文本等边界场景,避免崩溃;
                                  • 可对比性:三种策略的核心逻辑解耦,便于对比不同查找算法的效率(ASL);
                                  • 性能适配:哈希表大小固定为 1009(质数,减少哈希冲突),线性表最大容量限制为 10000(适配常规文本解析场景)。

                                  结合 “算法实践 + 可视化交互” 的核心需求,选择轻量、易理解的技术栈:

                                  技术 / 模块 选型理由
                                  Python 3.8+ 语法简洁,数据结构(列表、字典)原生支持,算法实现直观,适合教学 / 实践场景
                                  tkinter + ttk Python 内置 GUI 库,无需额外安装,足够支撑轻量交互界面;ttk 提升控件美观度
                                  原生数据结构(列表) 模拟线性表、哈希表(链地址法),无需第三方库,降低学习 / 使用成本
                                  Time33 哈希函数 简单高效的字符串哈希算法(h = h*33 + ord(char)),分布均匀,冲突率低
                                  快速排序 + 二分查找 经典排序 / 查找算法组合,对比顺序查找体现 “有序表 + 二分” 的效率优势

                                  采用 “模块化 + 面向对象” 混合设计,核心分为三层,确保逻辑解耦、便于维护:

                                  classDiagram
                                      direction LR
                                      "全局常量层" --> "核心算法层" : 依赖常量配置
                                      "核心算法层" --> "GUI交互层" : 提供算法调用
                                      "GUI交互层" --> "核心算法层" : 传递业务数据
                                      
                                      class 全局常量层 {
                                          MAX_LINEAR_SIZE: int = 10000
                                          HASH_SIZE: int = 1009
                                          MAX_WORD_LEN: int = 50
                                      }
                                      
                                      class 核心算法层 {
                                          +normalize(token, pos): (bool, str)  # 单词标准化
                                          +my_hash(word): int  # Time33哈希
                                          +linear_search(linear_list, word): (bool, int)  # 顺序查找
                                          +quick_sort(linear_list, low, high)  # 快速排序
                                          +binary_search(linear_list, word): (bool, int)  # 二分查找
                                      }
                                      
                                      class GUI交互层 {
                                          -root: tk.Tk
                                          -strategy_var: tk.StringVar
                                          +_setup_ui()  # 搭建UI
                                          +_on_text_changed(event)  # 文本输入监控
                                          +_on_strategy_toggled()  # 策略切换
                                          +_on_analyze_clicked()  # 分析按钮逻辑
                                          +_update_result(text, color)  # 更新结果展示
                                      }
                                  

                                  HTML代码:

                                  <!DOCTYPE html>
                                  <html lang="zh-CN">
                                  <head>
                                      <meta charset="UTF-8">
                                      <meta name="viewport" content="width=device-width, initial-scale=1.0">
                                      <title>单词统计工具 - 架构类图</title>
                                      <!-- 引入Mermaid CDN -->
                                      <script src="https://cdn.jsdelivr.net/npm/mermaid@10.16.0/dist/mermaid.min.js"></script>
                                      <style>
                                          body {
                                              font-family: "Microsoft YaHei", Arial, sans-serif;
                                              padding: 20px;
                                              background: #f5f5f5;
                                          }
                                          .container {
                                              max-width: 1200px;
                                              margin: 0 auto;
                                              background: white;
                                              padding: 30px;
                                              border-radius: 8px;
                                              box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                                          }
                                          h1 {
                                              text-align: center;
                                              color: #333;
                                              margin-bottom: 30px;
                                          }
                                          /* 确保Mermaid代码保留换行格式 */
                                          .mermaid {
                                              white-space: pre;
                                              font-family: monospace;
                                          }
                                      </style>
                                  </head>
                                  <body>
                                  <div class="container">
                                      <h1>单词统计与查找分析工具 - 架构类图</h1>
                                      <!-- Mermaid类图代码(直接放在mermaid容器中,保留原始格式) -->
                                      <div class="mermaid">
                                          classDiagram
                                          direction LR
                                  
                                          %% 层间关联
                                          全局常量层 --> 核心算法层 : 依赖常量配置
                                          核心算法层 --> GUI交互层 : 提供算法调用
                                          GUI交互层 --> 核心算法层 : 传递业务数据
                                  
                                          %% 全局常量层
                                          class 全局常量层 {
                                          MAX_LINEAR_SIZE: int = 10000
                                          HASH_SIZE: int = 1009
                                          MAX_WORD_LEN: int = 50
                                          }
                                  
                                          %% 核心算法层
                                          class 核心算法层 {
                                          +normalize(token, pos): (bool, str) // 单词标准化
                                          +my_hash(word): int // Time33哈希
                                          +linear_search(linear_list, word): (bool, int) // 顺序查找
                                          +quick_sort(linear_list, low, high) // 快速排序
                                          +binary_search(linear_list, word): (bool, int) // 二分查找
                                          }
                                  
                                          %% GUI交互层
                                          class GUI交互层 {
                                          -root: tk.Tk
                                          -strategy_var: tk.StringVar
                                          +_setup_ui() // 搭建UI
                                          +_on_text_changed(event) // 文本输入监控
                                          +_on_strategy_toggled() // 策略切换
                                          +_on_analyze_clicked() // 分析按钮逻辑
                                          +_update_result(text, color) // 更新结果展示
                                          }
                                      </div>
                                  </div>
                                  
                                  <script>
                                      // 初始化Mermaid,启用自动加载
                                      mermaid.initialize({
                                          startOnLoad: true,
                                          theme: 'default',
                                          classDiagram: {
                                              fontSize: 14,
                                              nodeSpacing: 30,
                                              rankSpacing: 40
                                          }
                                      });
                                  </script>
                                  </body>
                                  </html>
                                  

                                  核心设计思路:

                                  1. 全局常量层:集中管理配置参数(如哈希表大小、线性表最大容量),便于统一修改;
                                  2. 核心算法层:纯函数式设计,与 GUI 解耦,可独立测试 / 复用(比如单独调用算法函数验证逻辑);
                                  3. GUI 交互层:面向对象封装,负责界面渲染、事件处理、业务逻辑串联(调用算法 + 展示结果)。

                                  定义工具的核心配置参数,取值需兼顾 “场景适配 + 算法特性”:

                                  常量名 取值 设计理由
                                  MAX_LINEAR_SIZE 10000 限制线性表最大容量,避免极端文本导致内存溢出,适配常规文本解析场景
                                  HASH_SIZE 1009 选择质数作为哈希表大小(质数能减少哈希冲突,1009 是接近 1000 的质数,平衡性能与内存)
                                  MAX_WORD_LEN 50 限制单词最大长度,过滤异常超长字符串(如无分隔符的字母串)

                                  这是工具的 “算法核心”,所有函数均为纯逻辑实现,无 GUI 依赖,可独立调用测试。

                                  解决 “文本中提取有效单词” 的问题,核心需求:跳过非字母字符、提取连续字母、统一转小写。

                                  def normalize(token: str, pos: list) -> tuple[bool, str]:
                                      # 跳过非字母字符(如数字、符号、空格)
                                      while pos[0] < len(token) and not token[pos[0]].isalpha():
                                          pos[0] += 1
                                      if pos[0] >= len(token):
                                          return False, ""
                                      
                                      # 提取连续字母并转小写(保证单词格式统一)
                                      word = []
                                      while pos[0] < len(token) and token[pos[0]].isalpha():
                                          word.append(token[pos[0]].lower())
                                          pos[0] += 1
                                      return True, ''.join(word)
                                  

                                  关键设计点

                                  • pos参数用列表传引用:Python 中整数是不可变类型,用列表包裹可实现 “跨循环修改位置”(避免用全局变量);
                                  • 分步处理:先跳过无效字符,再提取有效字母,确保只保留纯字母单词;
                                  • 统一转小写:避免 “Apple” 和 “apple” 被识别为不同单词。

                                  选择经典的 Time33 算法,兼顾效率与哈希分布均匀性:

                                  def my_hash(word: str) -> int:
                                      h = 0
                                      for char in word:
                                          h = (h << 5) + h + ord(char)  # 等价于h = h*33 + ord(char)(左移5位=乘32,加h=乘33)
                                      return h % HASH_SIZE  # 映射到哈希表的桶索引
                                  

                                  设计理由

                                  • Time33 是工业界常用的轻量哈希算法(如 URL 哈希),实现简单且冲突率低;
                                  • 最终取模HASH_SIZE:将哈希值映射到 [0,1008] 的范围,适配哈希表的桶数量。

                                  实现线性表的顺序查找,返回 “是否找到 + 比较次数”(为 ASL 计算提供数据):

                                  def linear_search(linear_list: list, word: str) -> tuple[bool, int]:
                                      cmp_count = 0
                                      for item in linear_list:
                                          cmp_count += 1  # 每比较1次,计数+1
                                          if item["word"] == word:
                                              return True, cmp_count
                                      return False, cmp_count
                                  

                                  核心逻辑:遍历线性表,逐个比较单词,统计比较次数(ASL 的核心计算依据)。

                                  为二分查找做准备(二分查找要求线性表有序),实现 “按单词字典序排序”:

                                  def swap_linear_node(linear_list: list, i: int, j: int):
                                      """交换线性表元素,封装成函数便于复用"""
                                      linear_list[i], linear_list[j] = linear_list[j], linear_list[i]
                                  
                                  def partition(linear_list: list, low: int, high: int) -> int:
                                      """快排分区:以最后一个元素为基准,划分小于/大于基准的区域"""
                                      pivot = linear_list[high]["word"]  # 基准值(单词字典序)
                                      i = low - 1  # 小于基准的区域边界
                                      for j in range(low, high):
                                          if linear_list[j]["word"] < pivot:
                                              i += 1
                                              swap_linear_node(linear_list, i, j)
                                      swap_linear_node(linear_list, i + 1, high)  # 基准值归位
                                      return i + 1
                                  
                                  def quick_sort(linear_list: list, low: int, high: int):
                                      """快排主函数:递归划分区域并排序"""
                                      if low < high:
                                          pi = partition(linear_list, low, high)
                                          quick_sort(linear_list, low, pi - 1)  # 排序左半区
                                          quick_sort(linear_list, pi + 1, high)  # 排序右半区
                                  

                                  设计点

                                  • 排序依据是word字段的字典序:确保二分查找的有序性;
                                  • 封装swap_linear_node:避免重复写交换逻辑,提升代码可读性。

                                  基于有序线性表实现二分查找,统计比较次数:

                                  def binary_search(linear_list: list, word: str) -> tuple[bool, int]:
                                      cmp_count = 0
                                      low, high = 0, len(linear_list) - 1
                                      while low <= high:
                                          cmp_count += 1  # 每轮比较计数+1
                                          mid = (low + high) // 2
                                          mid_word = linear_list[mid]["word"]
                                          if mid_word == word:
                                              return True, cmp_count
                                          elif mid_word > word:
                                              high = mid - 1  # 目标在左半区
                                          else:
                                              low = mid + 1   # 目标在右半区
                                      return False, cmp_count
                                  

                                  核心逻辑:通过 “折半” 缩小查找范围,对比顺序查找可显著减少比较次数(体现算法优势)。

                                  封装所有界面交互逻辑,分为 “UI 搭建”“事件绑定”“核心业务逻辑” 三部分。

                                  def __init__(self, root):
                                      self.root = root
                                      self.root.title("单词统计与查找分析工具")
                                      self.root.geometry("800x600")
                                      self.strategy_var = tk.StringVar(value="1")  # 默认策略1
                                      self._setup_ui()
                                  
                                  def _setup_ui(self):
                                      # 主容器(统一内边距,提升美观度)
                                      main_frame = ttk.Frame(self.root, padding="20")
                                      main_frame.pack(fill=tk.BOTH, expand=True)
                                  
                                      # 1. 文本输入区:带实时提示
                                      input_label = ttk.Label(main_frame, text="请输入待分析文本(输入#结束):")
                                      input_label.pack(anchor=tk.W)
                                      self.text_input = tk.Text(main_frame, height=10, wrap=tk.WORD)
                                      self.text_input.pack(fill=tk.X, pady=(0, 5))
                                      self.input_tip_label = ttk.Label(main_frame, text="", foreground="#666666")
                                      self.input_tip_label.pack(anchor=tk.W)
                                      self.text_input.bind("<<Modified>>", self._on_text_changed)  # 绑定实时监控事件
                                      self.text_input_modified = False  # 防止事件重复触发
                                  
                                      # 2. 策略选择区:单选按钮组
                                      strategy_frame = ttk.LabelFrame(main_frame, text="查找策略选择", padding="10")
                                      strategy_frame.pack(fill=tk.X, pady=(10, 5))
                                      ttk.Radiobutton(strategy_frame, text="策略1:顺序查找", variable=self.strategy_var, value="1", command=self._on_strategy_toggled).pack(side=tk.LEFT, padx=10)
                                      ttk.Radiobutton(strategy_frame, text="策略2:快速排序+二分查找", variable=self.strategy_var, value="2", command=self._on_strategy_toggled).pack(side=tk.LEFT, padx=10)
                                      ttk.Radiobutton(strategy_frame, text="策略3:哈希表查找", variable=self.strategy_var, value="3", command=self._on_strategy_toggled).pack(side=tk.LEFT, padx=10)
                                  
                                      # 3. 分析按钮
                                      analyze_btn = ttk.Button(main_frame, text="开始分析", command=self._on_analyze_clicked)
                                      analyze_btn.pack(pady=(10, 10))
                                  
                                      # 4. 结果显示区:禁用手动编辑,仅展示结果
                                      result_label = ttk.Label(main_frame, text="分析结果:")
                                      result_label.pack(anchor=tk.W)
                                      self.result_display = tk.Text(main_frame, height=10, wrap=tk.WORD, state=tk.DISABLED)
                                      self.result_display.pack(fill=tk.BOTH, expand=True)
                                  

                                  UI 设计思路

                                  • 按 “输入→选择→操作→输出” 的流程布局,符合用户操作习惯;
                                  • 文本输入区启用wrap=tk.WORD:按单词换行,提升长文本可读性;
                                  • 结果区设置为tk.DISABLED:防止用户误编辑结果,仅通过代码更新。

                                  ① 文本输入实时监控(_on_text_changed)

                                  解决 “用户输入过程中无反馈” 的问题,实时提示字符数和#检测状态:

                                  def _on_text_changed(self, event):
                                      if self.text_input_modified:
                                          return  # 防止重复触发
                                      self.text_input_modified = True
                                  
                                      # 获取输入文本,统计字符数,检测#
                                      input_text = self.text_input.get("1.0", tk.END).strip()
                                      char_count = len(input_text)
                                      has_sharp = "#" in input_text
                                  
                                      # 生成提示文本,区分颜色(有#时橙色提示)
                                      tip = f"实时状态:已输入 {char_count} 个字符 | "
                                      if has_sharp:
                                          tip += "检测到#,分析时会截断#后的内容"
                                          self.input_tip_label.config(foreground="#E67E22")
                                      else:
                                          tip += "未检测到#,将分析全部文本"
                                          self.input_tip_label.config(foreground="#666666")
                                      self.input_tip_label.config(text=tip)
                                  
                                      # 重置modified标志,避免循环触发
                                      self.text_input.edit_modified(False)
                                      self.text_input_modified = False
                                  

                                  关键优化

                                  • self.text_input_modified标志防止<<Modified>>事件重复触发(tkinter 的该事件会多次触发);
                                  • 颜色区分提示:橙色提示#截断规则,提升用户感知。

                                  ② 策略切换反馈(_on_strategy_toggled)

                                  def _on_strategy_toggled(self):
                                      strategy_id = self.strategy_var.get()
                                      strategy_names = {"1": "顺序查找", "2": "快速排序+二分查找", "3": "哈希表查找"}
                                      strategy_name = strategy_names.get(strategy_id, "未知")
                                      self._update_result(f"已切换为【{strategy_name}】策略,请点击「开始分析」重新计算结果", "#3498DB")
                                  

                                  设计点:策略切换后即时清空结果区并提示,引导用户重新分析,避免结果与策略不匹配。

                                  ③ 结果更新封装(_update_result)

                                  def _update_result(self, text: str, color: str = "#000000"):
                                      self.result_display.config(state=tk.NORMAL)  # 临时启用编辑
                                      self.result_display.delete("1.0", tk.END)     # 清空原有内容
                                      self.result_display.insert(tk.END, text)      # 插入新结果
                                      self.result_display.config(foreground=color, state=tk.DISABLED)  # 禁用编辑,设置颜色
                                  

                                  封装理由:结果更新逻辑复用(策略切换、分析完成都需调用),减少重复代码。

                                  这是 GUI 与算法层的 “桥梁”,实现 “文本解析→策略执行→指标计算→结果展示” 的全流程:

                                  def _on_analyze_clicked(self):
                                      # 1. 输入预处理:获取文本,截断#后的内容
                                      input_text = self.text_input.get("1.0", tk.END).strip()
                                      strategy = int(self.strategy_var.get())
                                      if "#" in input_text:
                                          input_text = input_text.split("#")[0]
                                  
                                      # 2. 初始化数据结构
                                      linear_list = []  # 策略1/2用
                                      hash_table = [[] for _ in range(HASH_SIZE)]  # 策略3用(链地址法)
                                      total_words = 0
                                      unique_words = 0
                                      total_cmp = 0
                                  
                                      # 3. 解析并统计单词(调用normalize函数)
                                      pos = [0]
                                      token = input_text
                                      while True:
                                          has_word, word = normalize(token, pos)
                                          if not has_word:
                                              break
                                          total_words += 1
                                  
                                          # 策略1/2:线性表统计
                                          if strategy in (1, 2):
                                              found, _ = linear_search(linear_list, word)
                                              if found:
                                                  for item in linear_list:
                                                      if item["word"] == word:
                                                          item["count"] += 1
                                                          break
                                              else:
                                                  linear_list.append({"word": word, "count": 1})
                                          # 策略3:哈希表统计(链地址法解决冲突)
                                          elif strategy == 3:
                                              h = my_hash(word)
                                              found = False
                                              for item in hash_table[h]:
                                                  if item["word"] == word:
                                                      item["count"] += 1
                                                      found = True
                                                      break
                                              if not found:
                                                  hash_table[h].append({"word": word, "count": 1})
                                  
                                      # 4. 计算Unique Words和ASL(核心指标)
                                      if strategy == 1:
                                          # 顺序查找:遍历线性表,累加比较次数
                                          unique_words = len(linear_list)
                                          for item in linear_list:
                                              _, cmp = linear_search(linear_list, item["word"])
                                              total_cmp += cmp
                                          asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                      elif strategy == 2:
                                          # 快排+二分:先排序,再二分查找统计比较次数
                                          unique_words = len(linear_list)
                                          if unique_words > 0:
                                              quick_sort(linear_list, 0, unique_words - 1)
                                              for item in linear_list:
                                                  _, cmp = binary_search(linear_list, item["word"])
                                                  total_cmp += cmp
                                          asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                      elif strategy == 3:
                                          # 哈希表:统计桶中元素数(Unique Words),累加链表位置作为比较次数
                                          unique_words = 0
                                          for bucket in hash_table:
                                              unique_words += len(bucket)
                                          for bucket in hash_table:
                                              for idx, item in enumerate(bucket):
                                                  total_cmp += (idx + 1)  # 链表位置从1开始
                                          asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                      # 5. 格式化展示结果
                                      result = (
                                          f"Total Words: {total_words}n"
                                          f"Unique Words: {unique_words}n"
                                          f"ASL: {asl:.2f}nn"
                                          "测试自动换行:这是一段很长的文本,用于验证结果区的自动换行功能是否生效,当文本长度超过控件宽度时,会自动换行显示,不需要手动添加换行符。"
                                      )
                                      self._update_result(result)
                                  

                                  核心设计点

                                  • 数据结构适配:策略 1/2 复用线性表,策略 3 用 “列表嵌套列表” 模拟哈希表的链地址法(解决哈希冲突);
                                  • ASL 计算逻辑:
                                    • 顺序查找:每个单词的比较次数 = 其在列表中的位置;
                                    • 二分查找:基于有序表的折半比较次数;
                                    • 哈希表:比较次数 = 单词在哈希桶链表中的位置(链地址法的查找次数);
                                  • 边界处理:unique_words=0时 ASL 设为 0,避免除以 0 错误。

                                  开发完成后,覆盖多场景测试并优化体验,确保工具稳定可用:

                                  测试场景 测试目的 预期结果
                                  输入空文本 验证边界处理,避免崩溃 Total Words=0,Unique Words=0,ASL=0.00
                                  输入带 #的文本(如 “Hi#Hello”) 验证 #截断逻辑 仅解析 “Hi”,Total Words=1
                                  输入含非字母的文本(如 “Hi! 123 Apple”) 验证 normalize 函数的标准化逻辑 仅提取 “hi”“apple”,统一转小写
                                  三种策略对比(相同文本) 验证算法效率差异 策略 1 ASL 最大,策略 3 ASL 最小(哈希效率最高)
                                  超长单词(50 + 字母) 验证 MAX_WORD_LEN 的限制(代码中隐含处理) 正常提取,无内存溢出

                                  • 防止事件重复触发:通过self.text_input_modified标志解决<<Modified>>事件多次触发的问题;
                                  • 实时反馈优化:输入区提示字符数和 #检测状态,策略切换即时提示;
                                  • 结果格式化:ASL 保留 2 位小数,结果区启用自动换行,提升可读性;
                                  • 异常防护:处理unique_words=0的情况,避免除以 0 错误;
                                  • 代码解耦:算法函数与 GUI 完全分离,可单独测试算法逻辑(如直接调用linear_search验证查找次数)。

                                  import tkinter as tk
                                  from tkinter import ttk, messagebox
                                  import re
                                  import sys
                                  
                                  # ===================== 全局常量 =====================
                                  MAX_LINEAR_SIZE = 10000  # 线性表最大容量
                                  HASH_SIZE = 1009  # 哈希表大小(强制1009)
                                  MAX_WORD_LEN = 50  # 单词最大长度
                                  
                                  
                                  # ===================== 核心算法函数 =====================
                                  def normalize(token: str, pos: list) -> tuple[bool, str]:
                                      """
                                      标准化单词:跳过非字母字符,提取连续字母并转小写
                                      :param token: 待处理字符串
                                      :param pos: 当前处理位置(用列表传引用,Python整数不可变)
                                      :return: (是否提取到单词, 标准化后的单词)
                                      """
                                      # 跳过非字母字符
                                      while pos[0] < len(token) and not token[pos[0]].isalpha():
                                          pos[0] += 1
                                  
                                      if pos[0] >= len(token):
                                          return False, ""
                                  
                                      # 提取连续字母并转小写
                                      word = []
                                      while pos[0] < len(token) and token[pos[0]].isalpha():
                                          word.append(token[pos[0]].lower())
                                          pos[0] += 1
                                  
                                      return True, ''.join(word)
                                  
                                  
                                  def my_hash(word: str) -> int:
                                      """Time33哈希函数"""
                                      h = 0
                                      for char in word:
                                          h = (h << 5) + h + ord(char)  # h = h*33 + 字符ASCII
                                      return h % HASH_SIZE
                                  
                                  
                                  def linear_search(linear_list: list, word: str) -> tuple[bool, int]:
                                      """
                                      顺序查找
                                      :return: (是否找到, 比较次数)
                                      """
                                      cmp_count = 0
                                      for item in linear_list:
                                          cmp_count += 1
                                          if item["word"] == word:
                                              return True, cmp_count
                                      return False, cmp_count
                                  
                                  
                                  # 快速排序相关函数(按单词字典序)
                                  def swap_linear_node(linear_list: list, i: int, j: int):
                                      """交换线性表中的两个元素"""
                                      linear_list[i], linear_list[j] = linear_list[j], linear_list[i]
                                  
                                  
                                  def partition(linear_list: list, low: int, high: int) -> int:
                                      """快排分区函数"""
                                      pivot = linear_list[high]["word"]
                                      i = low - 1  # 小于基准的区域边界
                                  
                                      for j in range(low, high):
                                          if linear_list[j]["word"] < pivot:
                                              i += 1
                                              swap_linear_node(linear_list, i, j)
                                  
                                      swap_linear_node(linear_list, i + 1, high)
                                      return i + 1
                                  
                                  
                                  def quick_sort(linear_list: list, low: int, high: int):
                                      """快速排序主函数"""
                                      if low < high:
                                          pi = partition(linear_list, low, high)
                                          quick_sort(linear_list, low, pi - 1)
                                          quick_sort(linear_list, pi + 1, high)
                                  
                                  
                                  def binary_search(linear_list: list, word: str) -> tuple[bool, int]:
                                      """
                                      二分查找(需先排序)
                                      :return: (是否找到, 比较次数)
                                      """
                                      cmp_count = 0
                                      low, high = 0, len(linear_list) - 1
                                  
                                      while low <= high:
                                          cmp_count += 1
                                          mid = (low + high) // 2
                                          mid_word = linear_list[mid]["word"]
                                  
                                          if mid_word == word:
                                              return True, cmp_count
                                          elif mid_word > word:
                                              high = mid - 1
                                          else:
                                              low = mid + 1
                                  
                                      return False, cmp_count
                                  
                                  
                                  # ===================== GUI主类 =====================
                                  class WordAnalyzerApp:
                                      def __init__(self, root):
                                          self.root = root
                                          self.root.title("单词统计与查找分析工具")
                                          self.root.geometry("800x600")
                                  
                                          # 策略选择变量
                                          self.strategy_var = tk.StringVar(value="1")
                                  
                                          # 初始化UI
                                          self._setup_ui()
                                  
                                      def _setup_ui(self):
                                          """构建GUI界面"""
                                          # 主容器
                                          main_frame = ttk.Frame(self.root, padding="20")
                                          main_frame.pack(fill=tk.BOTH, expand=True)
                                  
                                          # 1. 文本输入区域
                                          input_label = ttk.Label(main_frame, text="请输入待分析文本(输入#结束):")
                                          input_label.pack(anchor=tk.W)
                                  
                                          self.text_input = tk.Text(main_frame, height=10, wrap=tk.WORD)
                                          self.text_input.pack(fill=tk.X, pady=(0, 5))
                                  
                                          # 实时提示标签
                                          self.input_tip_label = ttk.Label(main_frame, text="", foreground="#666666")
                                          self.input_tip_label.pack(anchor=tk.W)
                                  
                                          # 绑定文本实时监控事件
                                          self.text_input.bind("<<Modified>>", self._on_text_changed)
                                          self.text_input_modified = False  # 防止重复触发
                                  
                                          # 2. 策略选择区域
                                          strategy_frame = ttk.LabelFrame(main_frame, text="查找策略选择", padding="10")
                                          strategy_frame.pack(fill=tk.X, pady=(10, 5))
                                  
                                          # 策略单选按钮
                                          ttk.Radiobutton(
                                              strategy_frame, text="策略1:顺序查找",
                                              variable=self.strategy_var, value="1",
                                              command=self._on_strategy_toggled
                                          ).pack(side=tk.LEFT, padx=10)
                                  
                                          ttk.Radiobutton(
                                              strategy_frame, text="策略2:快速排序+二分查找",
                                              variable=self.strategy_var, value="2",
                                              command=self._on_strategy_toggled
                                          ).pack(side=tk.LEFT, padx=10)
                                  
                                          ttk.Radiobutton(
                                              strategy_frame, text="策略3:哈希表查找",
                                              variable=self.strategy_var, value="3",
                                              command=self._on_strategy_toggled
                                          ).pack(side=tk.LEFT, padx=10)
                                  
                                          # 3. 分析按钮
                                          analyze_btn = ttk.Button(
                                              main_frame, text="开始分析",
                                              command=self._on_analyze_clicked
                                          )
                                          analyze_btn.pack(pady=(10, 10))
                                  
                                          # 4. 结果显示区域
                                          result_label = ttk.Label(main_frame, text="分析结果:")
                                          result_label.pack(anchor=tk.W)
                                  
                                          self.result_display = tk.Text(main_frame, height=10, wrap=tk.WORD, state=tk.DISABLED)
                                          self.result_display.pack(fill=tk.BOTH, expand=True)
                                  
                                      def _on_text_changed(self, event):
                                          """文本输入实时监控"""
                                          if self.text_input_modified:
                                              return
                                          self.text_input_modified = True
                                  
                                          # 获取输入文本
                                          input_text = self.text_input.get("1.0", tk.END).strip()
                                          char_count = len(input_text)
                                          has_sharp = "#" in input_text
                                  
                                          # 更新提示文本
                                          tip = f"实时状态:已输入 {char_count} 个字符 | "
                                          if has_sharp:
                                              tip += "检测到#,分析时会截断#后的内容"
                                              self.input_tip_label.config(foreground="#E67E22")
                                          else:
                                              tip += "未检测到#,将分析全部文本"
                                              self.input_tip_label.config(foreground="#666666")
                                          self.input_tip_label.config(text=tip)
                                  
                                          # 重置modified标志
                                          self.text_input.edit_modified(False)
                                          self.text_input_modified = False
                                  
                                      def _on_strategy_toggled(self):
                                          """策略切换反馈"""
                                          strategy_id = self.strategy_var.get()
                                          strategy_names = {
                                              "1": "顺序查找",
                                              "2": "快速排序+二分查找",
                                              "3": "哈希表查找"
                                          }
                                          strategy_name = strategy_names.get(strategy_id, "未知")
                                  
                                          # 清空结果区并提示
                                          self._update_result(f"已切换为【{strategy_name}】策略,请点击「开始分析」重新计算结果", "#3498DB")
                                  
                                      def _update_result(self, text: str, color: str = "#000000"):
                                          """更新结果显示区"""
                                          self.result_display.config(state=tk.NORMAL)
                                          self.result_display.delete("1.0", tk.END)
                                          self.result_display.insert(tk.END, text)
                                          self.result_display.config(foreground=color, state=tk.DISABLED)
                                  
                                      def _on_analyze_clicked(self):
                                          """分析按钮点击事件"""
                                          # 1. 获取输入和策略
                                          input_text = self.text_input.get("1.0", tk.END).strip()
                                          strategy = int(self.strategy_var.get())
                                  
                                          # 处理#结束符
                                          if "#" in input_text:
                                              input_text = input_text.split("#")[0]
                                  
                                          # 2. 初始化数据结构
                                          linear_list = []  # 策略1/2:存储{"word": xxx, "count": xxx}
                                          hash_table = [[] for _ in range(HASH_SIZE)]  # 策略3:哈希表(列表模拟链表)
                                          total_words = 0
                                          unique_words = 0
                                          total_cmp = 0
                                  
                                          # 3. 解析并统计单词
                                          pos = [0]  # 用列表传引用
                                          token = input_text
                                          while True:
                                              has_word, word = normalize(token, pos)
                                              if not has_word:
                                                  break
                                              total_words += 1
                                  
                                              # 策略1/2:线性表处理
                                              if strategy in (1, 2):
                                                  found, _ = linear_search(linear_list, word)
                                                  if found:
                                                      # 单词已存在,计数+1
                                                      for item in linear_list:
                                                          if item["word"] == word:
                                                              item["count"] += 1
                                                              break
                                                  else:
                                                      # 新增单词
                                                      linear_list.append({"word": word, "count": 1})
                                  
                                              # 策略3:哈希表处理
                                              elif strategy == 3:
                                                  h = my_hash(word)
                                                  found = False
                                                  # 遍历哈希桶中的单词
                                                  for item in hash_table[h]:
                                                      if item["word"] == word:
                                                          item["count"] += 1
                                                          found = True
                                                          break
                                                  if not found:
                                                      hash_table[h].append({"word": word, "count": 1})
                                  
                                          # 4. 计算Unique Words和ASL
                                          if strategy == 1:
                                              # 顺序查找策略
                                              unique_words = len(linear_list)
                                              for item in linear_list:
                                                  _, cmp = linear_search(linear_list, item["word"])
                                                  total_cmp += cmp
                                              asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                          elif strategy == 2:
                                              # 快排+二分查找策略
                                              unique_words = len(linear_list)
                                              if unique_words > 0:
                                                  quick_sort(linear_list, 0, unique_words - 1)
                                                  for item in linear_list:
                                                      _, cmp = binary_search(linear_list, item["word"])
                                                      total_cmp += cmp
                                              asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                          elif strategy == 3:
                                              # 哈希表策略
                                              # 统计唯一单词数
                                              unique_words = 0
                                              for bucket in hash_table:
                                                  unique_words += len(bucket)
                                              # 统计总比较次数
                                              for bucket in hash_table:
                                                  for idx, item in enumerate(bucket):
                                                      total_cmp += (idx + 1)  # 链表位置从1开始
                                              asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                          # 5. 显示结果
                                          result = (
                                              f"Total Words: {total_words}n"
                                              f"Unique Words: {unique_words}n"
                                              f"ASL: {asl:.2f}nn"
                                              "测试自动换行:这是一段很长的文本,用于验证结果区的自动换行功能是否生效,当文本长度超过控件宽度时,会自动换行显示,不需要手动添加换行符。"
                                          )
                                          self._update_result(result)
                                  
                                  
                                  # ===================== 主函数 =====================
                                  if __name__ == "__main__":
                                      root = tk.Tk()
                                      app = WordAnalyzerApp(root)
                                      root.mainloop()
                                  

                                  打开 Anaconda Prompt,执行以下命令(复制粘贴即可):

                                  # 1. 创建仅包含Python 3.10的纯净环境(兼容性最佳,适配tkinter/matplotlib/pandas)
                                  conda create -n word_analyzer_tool python=3.10 -y
                                  
                                  # 2. 激活该环境
                                  conda activate word_analyzer_tool
                                  
                                  # 3. 仅安装必需依赖(清华源加速,包含matplotlib可视化依赖)
                                  pip install pandas matplotlib openpyxl pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple/
                                  

                                  # 切换到你的单词统计工具代码所在文件夹(替换为实际路径)
                                  cd C:Users你的用户名PycharmProjectsWordAnalyzerTool
                                  
                                  # 用目录模式打包(-D),速度快、体积小、稳定性高;-w隐藏控制台(GUI工具必备);--collect-data 确保matplotlib资源被打包
                                  pyinstaller -w -n 单词统计与查找分析工具 -D --collect-data matplotlib 单词统计与查找分析工具.py

                                  额外参数说明:--collect-data matplotlib 是为了确保 matplotlib 的字体、配置等资源被正确打包,避免可视化功能运行报错。

                                  • 打包时间:仅需 2-3 分钟(因包含 matplotlib,略长于基础工具);
                                  • exe 位置dist单词统计与查找分析工具 目录下的 单词统计与查找分析工具.exe
                                  • 体积:约 120-180MB(因包含 matplotlib 依赖,对比全局环境打包的 2GB+,大幅精简);
                                  • 功能验证:双击 exe,测试文本导入 / 输入、策略切换、ASL 可视化、单词统计等核心功能,和原代码完全一致。

                                  • 增加 “单词频次排行榜”:展示出现次数最多的前 N 个单词;
                                  • 支持文件导入:解析文本文件(.txt),而非仅手动输入;
                                  • 算法对比可视化:用柱状图展示三种策略的 ASL 差异;
                                  • 自定义哈希表大小:允许用户调整 HASH_SIZE,观察冲突率变化;
                                  • 增加单词长度统计:分析文本中单词的平均长度、最长单词等指标。

                                  import tkinter as tk
                                  from tkinter import ttk, messagebox, filedialog
                                  import re
                                  import sys
                                  import matplotlib
                                  
                                  # 设置matplotlib后端为TkAgg,适配tkinter
                                  matplotlib.use('TkAgg')
                                  import matplotlib.pyplot as plt
                                  from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
                                  
                                  # ===================== 全局常量(基础默认值) =====================
                                  MAX_LINEAR_SIZE = 10000  # 线性表最大容量
                                  DEFAULT_HASH_SIZE = 1009  # 默认哈希表大小
                                  MAX_WORD_LEN = 50  # 单词最大长度
                                  DEFAULT_RANKING_N = 10  # 默认排行榜展示前10个单词
                                  
                                  
                                  # ===================== 核心算法函数(兼容自定义哈希表大小+性能优化) =====================
                                  def normalize(token: str, pos: list) -> tuple[bool, str]:
                                      """
                                      标准化单词:跳过非字母字符,提取连续字母并转小写(性能优化版)
                                      :param token: 待处理字符串
                                      :param pos: 当前处理位置(用列表传引用,Python整数不可变)
                                      :return: (是否提取到单词, 标准化后的单词)
                                      """
                                      start = pos[0]
                                      # 跳过非字母字符(优化循环逻辑)
                                      while start < len(token) and not token[start].isalpha():
                                          start += 1
                                  
                                      if start >= len(token):
                                          pos[0] = start
                                          return False, ""
                                  
                                      # 提取连续字母(一次性切片,减少循环次数)
                                      end = start
                                      while end < len(token) and token[end].isalpha():
                                          end += 1
                                  
                                      pos[0] = end
                                      return True, token[start:end].lower()
                                  
                                  
                                  def my_hash(word: str, hash_size: int) -> int:
                                      """Time33哈希函数(适配自定义哈希表大小)"""
                                      h = 0
                                      for char in word:
                                          h = (h << 5) + h + ord(char)  # h = h*33 + 字符ASCII
                                      return h % hash_size
                                  
                                  
                                  def linear_search(linear_list: list, word: str) -> tuple[bool, int]:
                                      """
                                      顺序查找
                                      :return: (是否找到, 比较次数)
                                      """
                                      cmp_count = 0
                                      for item in linear_list:
                                          cmp_count += 1
                                          if item["word"] == word:
                                              return True, cmp_count
                                      return False, cmp_count
                                  
                                  
                                  # 快速排序相关函数(按单词字典序)
                                  def swap_linear_node(linear_list: list, i: int, j: int):
                                      """交换线性表中的两个元素"""
                                      linear_list[i], linear_list[j] = linear_list[j], linear_list[i]
                                  
                                  
                                  def partition(linear_list: list, low: int, high: int) -> int:
                                      """快排分区函数"""
                                      pivot = linear_list[high]["word"]
                                      i = low - 1  # 小于基准的区域边界
                                  
                                      for j in range(low, high):
                                          if linear_list[j]["word"] < pivot:
                                              i += 1
                                              swap_linear_node(linear_list, i, j)
                                  
                                      swap_linear_node(linear_list, i + 1, high)
                                      return i + 1
                                  
                                  
                                  def quick_sort(linear_list: list, low: int, high: int):
                                      """快速排序主函数"""
                                      if low < high:
                                          pi = partition(linear_list, low, high)
                                          quick_sort(linear_list, low, pi - 1)
                                          quick_sort(linear_list, pi + 1, high)
                                  
                                  
                                  def binary_search(linear_list: list, word: str) -> tuple[bool, int]:
                                      """
                                      二分查找(需先排序)
                                      :return: (是否找到, 比较次数)
                                      """
                                      cmp_count = 0
                                      low, high = 0, len(linear_list) - 1
                                  
                                      while low <= high:
                                          cmp_count += 1
                                          mid = (low + high) // 2
                                          mid_word = linear_list[mid]["word"]
                                  
                                          if mid_word == word:
                                              return True, cmp_count
                                          elif mid_word > word:
                                              high = mid - 1
                                          else:
                                              low = mid + 1
                                  
                                      return False, cmp_count
                                  
                                  
                                  # ===================== 新增工具函数 =====================
                                  def calculate_word_length_stats(word_list: list) -> dict:
                                      """计算单词长度统计指标"""
                                      if not word_list:
                                          return {
                                              "avg_length": 0.0,
                                              "max_len_word": "",
                                              "max_length": 0,
                                              "min_len_word": "",
                                              "min_length": 0
                                          }
                                  
                                      lengths = [len(word["word"]) for word in word_list]
                                      avg_length = sum(lengths) / len(lengths)
                                      max_idx = lengths.index(max(lengths))
                                      min_idx = lengths.index(min(lengths))
                                  
                                      return {
                                          "avg_length": round(avg_length, 2),
                                          "max_len_word": word_list[max_idx]["word"],
                                          "max_length": max(lengths),
                                          "min_len_word": word_list[min_idx]["word"],
                                          "min_length": min(lengths)
                                      }
                                  
                                  
                                  def get_word_ranking(word_list: list, top_n: int) -> list:
                                      """生成单词频次排行榜(降序)"""
                                      if not word_list:
                                          return []
                                      # 按频次降序排序,频次相同按单词字典序升序
                                      sorted_list = sorted(word_list, key=lambda x: (-x["count"], x["word"]))
                                      # 处理top_n超过列表长度的情况
                                      top_n = min(top_n, len(sorted_list))
                                      return sorted_list[:top_n]
                                  
                                  
                                  def analyze_all_strategies(input_text: str, hash_size: int) -> dict:
                                      """批量分析三种策略的ASL,用于可视化"""
                                      # 第一步:解析文本得到所有单词
                                      pos = [0]
                                      token = input_text
                                      all_words = []
                                      while True:
                                          has_word, word = normalize(token, pos)
                                          if not has_word:
                                              break
                                          all_words.append(word)
                                  
                                      if not all_words:
                                          return {"strategy1_asl": 0, "strategy2_asl": 0, "strategy3_asl": 0}
                                  
                                      # 策略1:顺序查找
                                      linear_list1 = []
                                      for word in all_words:
                                          found, _ = linear_search(linear_list1, word)
                                          if found:
                                              for item in linear_list1:
                                                  if item["word"] == word:
                                                      item["count"] += 1
                                                      break
                                          else:
                                              linear_list1.append({"word": word, "count": 1})
                                      unique1 = len(linear_list1)
                                      total_cmp1 = sum([linear_search(linear_list1, item["word"])[1] for item in linear_list1])
                                      strategy1_asl = total_cmp1 / unique1 if unique1 > 0 else 0
                                  
                                      # 策略2:快排+二分
                                      linear_list2 = linear_list1.copy()
                                      quick_sort(linear_list2, 0, len(linear_list2) - 1)
                                      total_cmp2 = sum([binary_search(linear_list2, item["word"])[1] for item in linear_list2])
                                      strategy2_asl = total_cmp2 / unique1 if unique1 > 0 else 0
                                  
                                      # 策略3:哈希表
                                      hash_table = [[] for _ in range(hash_size)]
                                      for word in all_words:
                                          h = my_hash(word, hash_size)
                                          found = False
                                          for item in hash_table[h]:
                                              if item["word"] == word:
                                                  item["count"] += 1
                                                  found = True
                                                  break
                                          if not found:
                                              hash_table[h].append({"word": word, "count": 1})
                                      unique3 = sum([len(bucket) for bucket in hash_table])
                                      total_cmp3 = sum([idx + 1 for bucket in hash_table for idx, item in enumerate(bucket)])
                                      strategy3_asl = total_cmp3 / unique3 if unique3 > 0 else 0
                                  
                                      return {
                                          "strategy1_asl": round(strategy1_asl, 2),
                                          "strategy2_asl": round(strategy2_asl, 2),
                                          "strategy3_asl": round(strategy3_asl, 2)
                                      }
                                  
                                  
                                  # ===================== GUI主类(集成所有新增功能) =====================
                                  class WordAnalyzerApp:
                                      def __init__(self, root):
                                          self.root = root
                                          self.root.title("单词统计与查找分析工具(增强版)")
                                          self.root.geometry("1000x800")  # 扩大窗口适配新功能
                                  
                                          # 添加窗口关闭事件处理(优雅退出)
                                          self.root.protocol("WM_DELETE_WINDOW", self._on_window_close)
                                  
                                          # 核心变量
                                          self.strategy_var = tk.StringVar(value="1")
                                          self.hash_size_var = tk.StringVar(value=str(DEFAULT_HASH_SIZE))
                                          self.ranking_n_var = tk.StringVar(value=str(DEFAULT_RANKING_N))
                                          self.all_strategies_asl = {"strategy1_asl": 0, "strategy2_asl": 0, "strategy3_asl": 0}
                                  
                                          # 初始化UI
                                          self._setup_ui()
                                  
                                      def _setup_ui(self):
                                          """构建GUI界面(新增功能组件)"""
                                          # 主容器
                                          main_frame = ttk.Frame(self.root, padding="20")
                                          main_frame.pack(fill=tk.BOTH, expand=True)
                                  
                                          # 1. 文件导入 + 文本输入区域
                                          file_frame = ttk.Frame(main_frame)
                                          file_frame.pack(fill=tk.X, pady=(0, 5))
                                  
                                          # 导入文件按钮
                                          import_btn = ttk.Button(file_frame, text="导入文本文件(.txt)", command=self._import_file)
                                          import_btn.pack(side=tk.LEFT, padx=(0, 10))
                                  
                                          # 哈希表大小设置
                                          hash_label = ttk.Label(file_frame, text="哈希表大小:")
                                          hash_label.pack(side=tk.LEFT, padx=(10, 5))
                                          hash_entry = ttk.Entry(file_frame, textvariable=self.hash_size_var, width=10)
                                          hash_entry.pack(side=tk.LEFT, padx=(0, 10))
                                          ttk.Label(file_frame, text="(建议输入质数)").pack(side=tk.LEFT)
                                  
                                          # 文本输入区域
                                          input_label = ttk.Label(main_frame, text="请输入待分析文本(输入#结束):")
                                          input_label.pack(anchor=tk.W)
                                          self.text_input = tk.Text(main_frame, height=8, wrap=tk.WORD)
                                          self.text_input.pack(fill=tk.X, pady=(0, 5))
                                  
                                          # 实时提示标签
                                          self.input_tip_label = ttk.Label(main_frame, text="", foreground="#666666")
                                          self.input_tip_label.pack(anchor=tk.W)
                                          self.text_input.bind("<<Modified>>", self._on_text_changed)
                                          self.text_input_modified = False
                                  
                                          # 2. 策略选择 + 排行榜设置区域
                                          setting_frame = ttk.LabelFrame(main_frame, text="分析设置", padding="10")
                                          setting_frame.pack(fill=tk.X, pady=(10, 5))
                                  
                                          # 策略单选按钮
                                          strategy_subframe = ttk.Frame(setting_frame)
                                          strategy_subframe.pack(side=tk.LEFT, padx=10)
                                          ttk.Radiobutton(
                                              strategy_subframe, text="策略1:顺序查找",
                                              variable=self.strategy_var, value="1",
                                              command=self._on_strategy_toggled
                                          ).pack(side=tk.LEFT, padx=5)
                                          ttk.Radiobutton(
                                              strategy_subframe, text="策略2:快速排序+二分查找",
                                              variable=self.strategy_var, value="2",
                                              command=self._on_strategy_toggled
                                          ).pack(side=tk.LEFT, padx=5)
                                          ttk.Radiobutton(
                                              strategy_subframe, text="策略3:哈希表查找",
                                              variable=self.strategy_var, value="3",
                                              command=self._on_strategy_toggled
                                          ).pack(side=tk.LEFT, padx=5)
                                  
                                          # 排行榜设置
                                          ranking_subframe = ttk.Frame(setting_frame)
                                          ranking_subframe.pack(side=tk.RIGHT, padx=10)
                                          ttk.Label(ranking_subframe, text="频次排行榜前N个单词:").pack(side=tk.LEFT, padx=5)
                                          ranking_entry = ttk.Entry(ranking_subframe, textvariable=self.ranking_n_var, width=5)
                                          ranking_entry.pack(side=tk.LEFT, padx=5)
                                  
                                          # 3. 功能按钮区域
                                          btn_frame = ttk.Frame(main_frame)
                                          btn_frame.pack(fill=tk.X, pady=(10, 10))
                                  
                                          # 开始分析按钮
                                          analyze_btn = ttk.Button(btn_frame, text="开始分析", command=self._on_analyze_clicked)
                                          analyze_btn.pack(side=tk.LEFT, padx=(0, 10))
                                  
                                          # ASL可视化按钮
                                          asl_chart_btn = ttk.Button(btn_frame, text="ASL算法对比可视化", command=self._show_asl_chart)
                                          asl_chart_btn.pack(side=tk.LEFT)
                                  
                                          # 4. 结果显示区域
                                          result_label = ttk.Label(main_frame, text="分析结果:")
                                          result_label.pack(anchor=tk.W)
                                          self.result_display = tk.Text(main_frame, height=12, wrap=tk.WORD, state=tk.DISABLED)
                                          self.result_display.pack(fill=tk.BOTH, expand=True)
                                  
                                      def _import_file(self):
                                          """导入txt文本文件"""
                                          file_path = filedialog.askopenfilename(
                                              title="选择文本文件",
                                              filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
                                          )
                                          if not file_path:
                                              return
                                  
                                          try:
                                              with open(file_path, "r", encoding="utf-8") as f:
                                                  content = f.read()
                                              # 清空原有内容,插入文件内容
                                              self.text_input.delete("1.0", tk.END)
                                              self.text_input.insert(tk.END, content)
                                              messagebox.showinfo("成功", f"已导入文件:{file_path}")
                                          except Exception as e:
                                              messagebox.showerror("错误", f"文件导入失败:{str(e)}")
                                  
                                      def _on_text_changed(self, event):
                                          """文本输入实时监控"""
                                          if self.text_input_modified:
                                              return
                                          self.text_input_modified = True
                                  
                                          input_text = self.text_input.get("1.0", tk.END).strip()
                                          char_count = len(input_text)
                                          has_sharp = "#" in input_text
                                  
                                          tip = f"实时状态:已输入 {char_count} 个字符 | "
                                          if has_sharp:
                                              tip += "检测到#,分析时会截断#后的内容"
                                              self.input_tip_label.config(foreground="#E67E22")
                                          else:
                                              tip += "未检测到#,将分析全部文本"
                                              self.input_tip_label.config(foreground="#666666")
                                          self.input_tip_label.config(text=tip)
                                  
                                          self.text_input.edit_modified(False)
                                          self.text_input_modified = False
                                  
                                      def _on_strategy_toggled(self):
                                          """策略切换反馈"""
                                          strategy_id = self.strategy_var.get()
                                          strategy_names = {
                                              "1": "顺序查找",
                                              "2": "快速排序+二分查找",
                                              "3": "哈希表查找"
                                          }
                                          strategy_name = strategy_names.get(strategy_id, "未知")
                                          self._update_result(f"已切换为【{strategy_name}】策略,请点击「开始分析」重新计算结果", "#3498DB")
                                  
                                      def _update_result(self, text: str, color: str = "#000000"):
                                          """更新结果显示区"""
                                          self.result_display.config(state=tk.NORMAL)
                                          self.result_display.delete("1.0", tk.END)
                                          self.result_display.insert(tk.END, text)
                                          self.result_display.config(foreground=color, state=tk.DISABLED)
                                  
                                      def _show_asl_chart(self):
                                          """绘制ASL算法对比柱状图"""
                                          input_text = self.text_input.get("1.0", tk.END).strip()
                                          if "#" in input_text:
                                              input_text = input_text.split("#")[0]
                                          if not input_text.strip():
                                              messagebox.showwarning("提示", "请先输入/导入文本内容!")
                                              return
                                  
                                          # 验证哈希表大小输入
                                          try:
                                              hash_size = int(self.hash_size_var.get())
                                              if hash_size <= 0:
                                                  raise ValueError
                                          except ValueError:
                                              messagebox.showerror("错误", "哈希表大小必须为正整数!")
                                              return
                                  
                                          # 批量分析三种策略的ASL
                                          self.all_strategies_asl = analyze_all_strategies(input_text, hash_size)
                                  
                                          # 创建图表窗口
                                          chart_window = tk.Toplevel(self.root)
                                          chart_window.title("ASL算法对比柱状图")
                                          chart_window.geometry("600x400")
                                  
                                          # 关键修改:字体设置移到创建图表之前,确保生效
                                          plt.rcParams["font.family"] = ["SimHei", "Microsoft YaHei", "WenQuanYi Micro Hei"]
                                          plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题
                                  
                                          # 绘制柱状图
                                          fig, ax = plt.subplots(figsize=(8, 5))
                                  
                                          strategies = ["顺序查找", "快排+二分查找", "哈希表查找"]
                                          asl_values = [
                                              self.all_strategies_asl["strategy1_asl"],
                                              self.all_strategies_asl["strategy2_asl"],
                                              self.all_strategies_asl["strategy3_asl"]
                                          ]
                                  
                                          ax.bar(strategies, asl_values, color=['#FF6B6B', '#4ECDC4', '#45B7D1'])
                                  
                                          # 优化y轴刻度(解决数据差异过大导致小值被压缩的问题)
                                          ax.set_yscale("log")  # 改用对数刻度,适配ASL的数量级差异
                                          ax.set_xlabel("查找策略")
                                          ax.set_ylabel("平均查找长度(ASL,对数刻度)")
                                          ax.set_title("不同查找策略的ASL对比")
                                          ax.grid(axis='y', linestyle='--', alpha=0.7)
                                  
                                          # 调整数值标签位置(适配对数刻度)
                                          for i, v in enumerate(asl_values):
                                              # 数值标签显示在柱子顶部,避免重叠
                                              ax.text(i, v * 1.1, f"{v:.2f}", ha='center', va='bottom', fontsize=10)
                                  
                                          # 将图表嵌入tkinter窗口
                                          canvas = FigureCanvasTkAgg(fig, master=chart_window)
                                          canvas.draw()
                                          canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
                                  
                                      def _on_analyze_clicked(self):
                                          """分析按钮点击事件(集成所有新增统计)"""
                                          # 1. 输入验证与预处理
                                          input_text = self.text_input.get("1.0", tk.END).strip()
                                          strategy = int(self.strategy_var.get())
                                          if "#" in input_text:
                                              input_text = input_text.split("#")[0]
                                          if not input_text.strip():
                                              self._update_result("请输入/导入待分析的文本内容!", "#E74C3C")
                                              return
                                  
                                          # 验证哈希表大小输入
                                          try:
                                              hash_size = int(self.hash_size_var.get())
                                              if hash_size <= 0:
                                                  raise ValueError
                                          except ValueError:
                                              messagebox.showerror("错误", "哈希表大小必须为正整数!")
                                              return
                                  
                                          # 验证排行榜N值输入
                                          try:
                                              ranking_n = int(self.ranking_n_var.get())
                                              if ranking_n <= 0:
                                                  raise ValueError
                                          except ValueError:
                                              messagebox.showerror("错误", "排行榜N值必须为正整数!")
                                              return
                                  
                                          # 2. 初始化数据结构
                                          linear_list = []
                                          hash_table = [[] for _ in range(hash_size)]
                                          total_words = 0
                                          unique_words = 0
                                          total_cmp = 0
                                          word_length_records = []  # 存储所有单词(用于长度统计)
                                  
                                          # 3. 解析并统计单词
                                          pos = [0]
                                          token = input_text
                                          while True:
                                              has_word, word = normalize(token, pos)
                                              if not has_word:
                                                  break
                                              total_words += 1
                                  
                                              # 策略1/2:线性表处理
                                              if strategy in (1, 2):
                                                  found, _ = linear_search(linear_list, word)
                                                  if found:
                                                      for item in linear_list:
                                                          if item["word"] == word:
                                                              item["count"] += 1
                                                              break
                                                  else:
                                                      linear_list.append({"word": word, "count": 1})
                                                  word_length_records = linear_list  # 同步到长度统计列表
                                  
                                              # 策略3:哈希表处理
                                              elif strategy == 3:
                                                  h = my_hash(word, hash_size)
                                                  found = False
                                                  for item in hash_table[h]:
                                                      if item["word"] == word:
                                                          item["count"] += 1
                                                          found = True
                                                          break
                                                  if not found:
                                                      hash_table[h].append({"word": word, "count": 1})
                                                  # 整理哈希表数据用于长度统计
                                                  word_length_records = []
                                                  for bucket in hash_table:
                                                      word_length_records.extend(bucket)
                                  
                                          # 4. 计算核心指标
                                          asl = 0.0
                                          if strategy == 1:
                                              unique_words = len(linear_list)
                                              total_cmp = sum([linear_search(linear_list, item["word"])[1] for item in linear_list])
                                              asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                          elif strategy == 2:
                                              unique_words = len(linear_list)
                                              if unique_words > 0:
                                                  quick_sort(linear_list, 0, unique_words - 1)
                                                  total_cmp = sum([binary_search(linear_list, item["word"])[1] for item in linear_list])
                                              asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                          elif strategy == 3:
                                              unique_words = sum([len(bucket) for bucket in hash_table])
                                              total_cmp = sum([idx + 1 for bucket in hash_table for idx, item in enumerate(bucket)])
                                              asl = total_cmp / unique_words if unique_words > 0 else 0.0
                                  
                                          # 5. 计算新增统计指标
                                          length_stats = calculate_word_length_stats(word_length_records)
                                          ranking_list = get_word_ranking(word_length_records, ranking_n)
                                  
                                          # 6. 格式化结果展示
                                          result = f"===== 基础统计 =====n"
                                          result += f"Total Words(总单词数): {total_words}n"
                                          result += f"Unique Words(唯一单词数): {unique_words}n"
                                          result += f"ASL(平均查找长度): {asl:.2f}nn"
                                  
                                          result += f"===== 单词长度统计 =====n"
                                          result += f"平均单词长度: {length_stats['avg_length']}n"
                                          result += f"最长单词: {length_stats['max_len_word']}(长度:{length_stats['max_length']})n"
                                          result += f"最短单词: {length_stats['min_len_word']}(长度:{length_stats['min_length']})nn"
                                  
                                          result += f"===== 单词频次排行榜(前{ranking_n}个)=====n"
                                          if ranking_list:
                                              for idx, item in enumerate(ranking_list, 1):
                                                  result += f"{idx}. {item['word']} - 出现次数:{item['count']}n"
                                          else:
                                              result += "暂无单词数据n"
                                  
                                          self._update_result(result)
                                  
                                      def _on_window_close(self):
                                          """优雅关闭窗口,避免强制退出导致的中断报错"""
                                          self.root.quit()
                                          self.root.destroy()
                                  
                                  
                                  # ===================== 主函数(捕获中断+优雅退出) =====================
                                  if __name__ == "__main__":
                                      try:
                                          root = tk.Tk()
                                          app = WordAnalyzerApp(root)
                                          root.mainloop()
                                      except KeyboardInterrupt:
                                          print("程序已被用户手动终止,正在优雅退出...")
                                          root.quit()
                                          root.destroy()
                                      except Exception as e:
                                          print(f"程序运行出错:{str(e)}")
                                          sys.exit(1)
                                  

                                  • 在 UI 中新增哈希表大小输入框,默认值为 1009,支持用户自定义;
                                  • 增加输入验证(必须为正整数),避免无效输入;
                                  • 核心哈希函数my_hash新增hash_size参数,适配自定义大小。

                                  • 新增 “导入文本文件 (.txt)” 按钮,支持选择本地 txt 文件;
                                  • 处理文件读取异常(编码、文件不存在等),给出友好提示;
                                  • 导入后自动将文件内容填充到文本输入框。

                                  • 新增calculate_word_length_stats函数,计算:
                                    • 平均单词长度;
                                    • 最长单词(及长度);
                                    • 最短单词(及长度);
                                  • 分析结果中单独展示长度统计模块,数据格式化输出。

                                  • 新增排行榜 N 值输入框(默认前 10),支持自定义展示数量;
                                  • 新增get_word_ranking函数,按频次降序排序(频次相同按单词字典序);
                                  • 处理 N 值超过唯一单词数的边界情况,避免报错。

                                  • 集成 matplotlib,适配 tkinter 后端;
                                  • 新增analyze_all_strategies函数,批量计算三种策略的 ASL;
                                  • 点击 “ASL 算法对比可视化” 按钮,弹出独立窗口展示柱状图,直观对比三种策略的 ASL 差异;
                                  • 柱状图添加数值标签、网格线,提升可读性。

                                  1. 运行前需安装 matplotlib:pip install matplotlib
                                  2. 哈希表大小建议输入质数(如 1009、997 等),可减少哈希冲突;
                                  3. 可视化功能需先执行文本分析,确保有有效数据;
                                  4. 支持的文本文件编码为 UTF-8,若导入其他编码文件(如 GBK),可手动修改_import_file函数中的编码参数。

                                  根据本文的打包项目的方法,扩展版和原始版的代码必须在同一目录下,可以直接运行下面命令:

                                  pyinstaller -w -n 单词统计与查找分析工具(增强版) -D --collect-data matplotlib 单词统计与查找分析工具扩展版.py

                                  本文介绍了一款单词统计与查找分析工具的设计与实现。该工具支持三种查找策略(顺序查找、快速排序+二分查找、哈希表查找),可计算文本中的单词总数、唯一单词数和平均查找长度(ASL)。工具采用Python开发,包含核心算法层和GUI交互层,具有文本标准化处理、实时状态提示和多策略对比功能。扩展版新增了文件导入、单词长度统计、频次排行榜和ASL可视化等功能,支持自定义哈希表大小。文章详细阐述了工具的技术选型、架构设计、核心算法实现和测试优化过程,并提供了完整的Python代码实现和打包方法。

                                  以上就是基于Python实现的单词统计与查找分析工具的详细内容,更多关于Python单词统计与查找工具的资料请关注风君子博客其它相关文章!

                                  您可能感兴趣的文章:

                                  • Python可视化单词统计词频统计中文分词的实现步骤
                                  • Python实战之单词打卡统计
                                  • 利用Python3实现统计大量单词中各字母出现的次数和频率的方法
                                  • python统计文章中单词出现次数实例
                                  • Python实现的统计文章单词次数功能示例

                                  站内搜索