已开启
迷宫游戏-湖北工业大学-刘咏琪-徐承志 #151
阔阔阔落创建于 2025年6月28日
迷宫游戏-湖北工业大学-刘咏琪-徐承志 #151
已开启
阔阔阔落创建于 2025年6月28日
2 个文件变更+1034-0
AHBUT/main+516-0
@@ -0,0 +1,516 @@
1+import os
2+import time
3+import random
4+from typing import Optional, List, Tuple
5+ 
6+class TreeNode:
7+ """二叉搜索树节点,表示文件系统中的一个文件或目录"""
8+
9+ def __init__(self, file_path: str, is_directory: bool = False):
10+ self.file_path = file_path
11+ self.file_name = os.path.basename(file_path)
12+ self.is_directory = is_directory
13+ self.size = self._calculate_size()
14+ self.created_time = time.time()
15+ self.left: Optional[TreeNode] = None
16+ self.right: Optional[TreeNode] = None
17+
18+ def _calculate_size(self) -> int:
19+ """计算文件或目录的大小"""
20+ if not os.path.exists(self.file_path):
21+ return 0
22+
23+ if not self.is_directory:
24+ return os.path.getsize(self.file_path)
25+
26+ # 递归计算目录大小
27+ total_size = 0
28+ for dirpath, _, filenames in os.walk(self.file_path):
29+ for f in filenames:
30+ fp = os.path.join(dirpath, f)
31+ try:
32+ total_size += os.path.getsize(fp)
33+ except OSError:
34+ pass
35+ return total_size
36+
37+ def __str__(self) -> str:
38+ """节点的字符串表示"""
39+ node_type = "DIR" if self.is_directory else "FILE"
40+ size_str = self._format_size(self.size)
41+ created_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.created_time))
42+ return f"{node_type} | {self.file_name} | {size_str} | {created_str}"
43+
44+ def _format_size(self, size_bytes: int) -> str:
45+ """格式化文件大小为人类可读的形式"""
46+ if size_bytes < 1024:
47+ return f"{size_bytes} B"
48+ elif size_bytes < 1024 * 1024:
49+ return f"{size_bytes / 1024:.2f} KB"
50+ elif size_bytes < 1024 * 1024 * 1024:
51+ return f"{size_bytes / (1024 * 1024):.2f} MB"
52+ else:
53+ return f"{size_bytes / (1024 * 1024 * 1024):.2f} GB"
54+ 
55+ 
56+class BinarySearchTree:
57+ """二叉搜索树实现,用于文件系统索引管理"""
58+
59+ def __init__(self):
60+ self.root: Optional[TreeNode] = None
61+ self.node_count = 0
62+
63+ def insert(self, file_path: str, is_directory: bool = False) -> bool:
64+ """插入文件或目录到二叉搜索树"""
65+ if not os.path.exists(file_path):
66+ print(f"错误: 文件或目录不存在 - {file_path}")
67+ return False
68+
69+ new_node = TreeNode(file_path, is_directory)
70+
71+ if self.root is None:
72+ self.root = new_node
73+ self.node_count += 1
74+ return True
75+
76+ # 递归插入
77+ def _insert_recursive(node: TreeNode, new_node: TreeNode) -> TreeNode:
78+ if new_node.file_name < node.file_name:
79+ if node.left is None:
80+ node.left = new_node
81+ else:
82+ node.left = _insert_recursive(node.left, new_node)
83+ else:
84+ if node.right is None:
85+ node.right = new_node
86+ else:
87+ node.right = _insert_recursive(node.right, new_node)
88+ return node
89+
90+ _insert_recursive(self.root, new_node)
91+ self.node_count += 1
92+ return True
93+
94+ def search(self, file_name: str) -> Optional[TreeNode]:
95+ """根据文件名搜索节点"""
96+ def _search_recursive(node: Optional[TreeNode], target: str) -> Optional[TreeNode]:
97+ if node is None or node.file_name == target:
98+ return node
99+ if target < node.file_name:
100+ return _search_recursive(node.left, target)
101+ return _search_recursive(node.right, target)
102+
103+ return _search_recursive(self.root, file_name)
104+
105+ def delete(self, file_name: str) -> bool:
106+ """根据文件名删除节点"""
107+ if self.root is None:
108+ return False
109+
110+ deleted = [False] # 使用列表作为可变对象传递
111+
112+ def _delete_recursive(node: Optional[TreeNode], target: str) -> Optional[TreeNode]:
113+ if node is None:
114+ return None
115+
116+ if target < node.file_name:
117+ node.left = _delete_recursive(node.left, target)
118+ elif target > node.file_name:
119+ node.right = _delete_recursive(node.right, target)
120+ else:
121+ # 找到目标节点,执行删除
122+ deleted[0] = True
123+
124+ # 情况1: 没有子节点或只有一个子节点
125+ if node.left is None:
126+ return node.right
127+ elif node.right is None:
128+ return node.left
129+
130+ # 情况2: 有两个子节点,找到右子树中的最小节点
131+ temp = self._find_min(node.right)
132+ node.file_path = temp.file_path
133+ node.file_name = temp.file_name
134+ node.is_directory = temp.is_directory
135+ node.size = temp.size
136+ node.created_time = temp.created_time
137+ node.right = _delete_recursive(node.right, temp.file_name)
138+
139+ return node
140+
141+ self.root = _delete_recursive(self.root, file_name)
142+ if deleted[0]:
143+ self.node_count -= 1
144+ return deleted[0]
145+
146+ def _find_min(self, node: TreeNode) -> TreeNode:
147+ """找到以node为根的子树中的最小节点"""
148+ current = node
149+ while current.left is not None:
150+ current = current.left
151+ return current
152+
153+ def inorder_traversal(self) -> List[TreeNode]:
154+ """中序遍历(按文件名排序)"""
155+ result = []
156+
157+ def _inorder_recursive(node: Optional[TreeNode]):
158+ if node is not None:
159+ _inorder_recursive(node.left)
160+ result.append(node)
161+ _inorder_recursive(node.right)
162+
163+ _inorder_recursive(self.root)
164+ return result
165+
166+ def preorder_traversal(self) -> List[TreeNode]:
167+ """前序遍历"""
168+ result = []
169+
170+ def _preorder_recursive(node: Optional[TreeNode]):
171+ if node is not None:
172+ result.append(node)
173+ _preorder_recursive(node.left)
174+ _preorder_recursive(node.right)
175+
176+ _preorder_recursive(self.root)
177+ return result
178+
179+ def postorder_traversal(self) -> List[TreeNode]:
180+ """后序遍历"""
181+ result = []
182+
183+ def _postorder_recursive(node: Optional[TreeNode]):
184+ if node is not None:
185+ _postorder_recursive(node.left)
186+ _postorder_recursive(node.right)
187+ result.append(node)
188+
189+ _postorder_recursive(self.root)
190+ return result
191+
192+ def get_file_count(self) -> int:
193+ """获取文件总数"""
194+ return self.node_count
195+
196+ def get_total_size(self) -> int:
197+ """获取所有文件的总大小"""
198+ def _sum_size_recursive(node: Optional[TreeNode]) -> int:
199+ if node is None:
200+ return 0
201+ return node.size + _sum_size_recursive(node.left) + _sum_size_recursive(node.right)
202+
203+ return _sum_size_recursive(self.root)
204+
205+ def find_largest_file(self) -> Optional[TreeNode]:
206+ """查找最大的文件"""
207+ if self.root is None:
208+ return None
209+
210+ largest = self.root
211+
212+ def _find_largest_recursive(node: Optional[TreeNode]):
213+ nonlocal largest
214+ if node is None:
215+ return
216+
217+ if not node.is_directory and node.size > largest.size:
218+ largest = node
219+
220+ _find_largest_recursive(node.left)
221+ _find_largest_recursive(node.right)
222+
223+ _find_largest_recursive(self.root)
224+ return largest
225+
226+ def find_files_by_size(self, min_size: int, max_size: int) -> List[TreeNode]:
227+ """查找指定大小范围内的文件"""
228+ result = []
229+
230+ def _find_by_size_recursive(node: Optional[TreeNode]):
231+ if node is None:
232+ return
233+
234+ if not node.is_directory and min_size <= node.size <= max_size:
235+ result.append(node)
236+
237+ _find_by_size_recursive(node.left)
238+ _find_by_size_recursive(node.right)
239+
240+ _find_by_size_recursive(self.root)
241+ return result
242+ 
243+ 
244+class FileSystemIndexManager:
245+ """文件系统索引管理器,使用二叉搜索树实现"""
246+
247+ def __init__(self):
248+ self.bst = BinarySearchTree()
249+ self.history = [] # 操作历史记录
250+
251+ def add_path(self, path: str) -> bool:
252+ """添加文件或目录到索引"""
253+ if not os.path.exists(path):
254+ print(f"错误: 路径不存在 - {path}")
255+ return False
256+
257+ is_dir = os.path.isdir(path)
258+ success = self.bst.insert(path, is_dir)
259+
260+ if success:
261+ action = f"添加 {'目录' if is_dir else '文件'}: {path}"
262+ self.history.append(action)
263+ print(f"成功: {action}")
264+ return success
265+
266+ def add_directory_recursive(self, directory: str) -> int:
267+ """递归添加目录及其所有子目录和文件到索引"""
268+ if not os.path.isdir(directory):
269+ print(f"错误: 不是有效的目录 - {directory}")
270+ return 0
271+
272+ added_count = 0
273+
274+ # 首先添加根目录
275+ if self.add_path(directory):
276+ added_count += 1
277+
278+ # 递归添加子目录和文件
279+ for root, dirs, files in os.walk(directory):
280+ # 添加子目录
281+ for dir_name in dirs:
282+ dir_path = os.path.join(root, dir_name)
283+ if self.add_path(dir_path):
284+ added_count += 1
285+
286+ # 添加文件
287+ for file_name in files:
288+ file_path = os.path.join(root, file_name)
289+ if self.add_path(file_path):
290+ added_count += 1
291+
292+ action = f"递归添加目录: {directory},共添加 {added_count} 个项目"
293+ self.history.append(action)
294+ print(f"成功: {action}")
295+ return added_count
296+
297+ def search_file(self, file_name: str) -> None:
298+ """搜索文件并显示结果"""
299+ node = self.bst.search(file_name)
300+ if node:
301+ print(f"找到文件: {node}")
302+ else:
303+ print(f"未找到文件: {file_name}")
304+
305+ action = f"搜索文件: {file_name},结果: {'找到' if node else '未找到'}"
306+ self.history.append(action)
307+
308+ def delete_file(self, file_name: str) -> None:
309+ """从索引中删除文件"""
310+ success = self.bst.delete(file_name)
311+ if success:
312+ print(f"成功删除文件: {file_name}")
313+ else:
314+ print(f"删除失败: 未找到文件 {file_name}")
315+
316+ action = f"删除文件: {file_name},结果: {'成功' if success else '失败'}"
317+ self.history.append(action)
318+
319+ def list_files(self, sort_order: str = "name") -> None:
320+ """列出所有文件"""
321+ if self.bst.get_file_count() == 0:
322+ print("索引中没有文件")
323+ return
324+
325+ print("\n=== 文件列表 ===")
326+ print("类型 | 文件名 | 大小 | 创建时间")
327+ print("-" * 70)
328+
329+ if sort_order == "name":
330+ nodes = self.bst.inorder_traversal()
331+ elif sort_order == "size":
332+ nodes = self.bst.inorder_traversal()
333+ nodes.sort(key=lambda x: x.size, reverse=True)
334+ elif sort_order == "created":
335+ nodes = self.bst.inorder_traversal()
336+ nodes.sort(key=lambda x: x.created_time, reverse=True)
337+ else:
338+ print(f"无效的排序顺序: {sort_order},使用默认排序(按名称)")
339+ nodes = self.bst.inorder_traversal()
340+
341+ for node in nodes:
342+ print(node)
343+
344+ print(f"\n总计: {self.bst.get_file_count()} 个项目,总大小: {node._format_size(self.bst.get_total_size())}")
345+
346+ action = f"列出文件,排序方式: {sort_order}"
347+ self.history.append(action)
348+
349+ def find_largest_files(self, count: int = 5) -> None:
350+ """查找最大的N个文件"""
351+ if self.bst.get_file_count() == 0:
352+ print("索引中没有文件")
353+ return
354+
355+ all_files = [node for node in self.bst.inorder_traversal() if not node.is_directory]
356+ if not all_files:
357+ print("索引中没有文件,只有目录")
358+ return
359+
360+ all_files.sort(key=lambda x: x.size, reverse=True)
361+ largest_files = all_files[:min(count, len(all_files))]
362+
363+ print(f"\n=== 最大的 {len(largest_files)} 个文件 ===")
364+ print("文件名 | 大小 | 路径")
365+ print("-" * 70)
366+
367+ for file in largest_files:
368+ print(f"{file.file_name} | {file._format_size(file.size)} | {file.file_path}")
369+
370+ action = f"查找最大的 {count} 个文件"
371+ self.history.append(action)
372+
373+ def find_files_in_size_range(self, min_size: str, max_size: str) -> None:
374+ """查找指定大小范围内的文件"""
375+ def parse_size(size_str: str) -> int:
376+ """将人类可读的大小字符串解析为字节数"""
377+ size_str = size_str.strip().upper()
378+ if size_str.endswith('KB'):
379+ return int(float(size_str[:-2]) * 1024)
380+ elif size_str.endswith('MB'):
381+ return int(float(size_str[:-2]) * 1024 * 1024)
382+ elif size_str.endswith('GB'):
383+ return int(float(size_str[:-2]) * 1024 * 1024 * 1024)
384+ else:
385+ return int(size_str)
386+
387+ try:
388+ min_bytes = parse_size(min_size)
389+ max_bytes = parse_size(max_size)
390+
391+ if min_bytes > max_bytes:
392+ min_bytes, max_bytes = max_bytes, min_bytes
393+ print(f"注意: 自动交换了最小值和最大值,实际查找范围: {min_size} 到 {max_size}")
394+
395+ files = self.bst.find_files_by_size(min_bytes, max_bytes)
396+
397+ if not files:
398+ print(f"未找到大小在 {min_size} 到 {max_size} 范围内的文件")
399+ return
400+
401+ print(f"\n=== 大小在 {min_size} 到 {max_size} 范围内的文件 ({len(files)} 个) ===")
402+ print("文件名 | 大小 | 路径")
403+ print("-" * 70)
404+
405+ for file in files:
406+ print(f"{file.file_name} | {file._format_size(file.size)} | {file.file_path}")
407+
408+ action = f"查找大小在 {min_size} 到 {max_size} 范围内的文件,找到 {len(files)} 个"
409+ self.history.append(action)
410+
411+ except ValueError:
412+ print(f"错误: 无法解析大小格式,请使用例如 '10MB', '2GB' 或 '5000' (字节)")
413+
414+ def show_statistics(self) -> None:
415+ """显示索引统计信息"""
416+ file_count = self.bst.get_file_count()
417+ if file_count == 0:
418+ print("索引中没有文件")
419+ return
420+
421+ total_size = self.bst.get_total_size()
422+ largest_file = self.bst.find_largest_file()
423+
424+ print("\n=== 索引统计信息 ===")
425+ print(f"总项目数: {file_count}")
426+ print(f"总大小: {TreeNode('', False)._format_size(total_size)}")
427+
428+ if largest_file:
429+ print(f"最大文件: {largest_file.file_name} ({TreeNode('', False)._format_size(largest_file.size)})")
430+
431+ # 计算文件类型分布
432+ file_types = {}
433+ for node in self.bst.inorder_traversal():
434+ if not node.is_directory:
435+ ext = os.path.splitext(node.file_name)[1].lower()
436+ file_types[ext] = file_types.get(ext, 0) + 1
437+
438+ if file_types:
439+ print("\n文件类型分布:")
440+ for ext, count in sorted(file_types.items(), key=lambda x: x[1], reverse=True):
441+ print(f" {ext}: {count} 个文件")
442+
443+ action = "显示索引统计信息"
444+ self.history.append(action)
445+
446+ def show_history(self, limit: int = 10) -> None:
447+ """显示最近的操作历史"""
448+ print(f"\n=== 最近 {min(limit, len(self.history))} 条操作历史 ===")
449+ for i, action in enumerate(reversed(self.history[-limit:])):
450+ print(f"{len(self.history) - i}: {action}")
451+ 
452+ 
453+def main():
454+ """主函数,演示文件系统索引管理器的使用"""
455+ print("=== 文件系统索引管理器 (使用二叉搜索树实现) ===")
456+
457+ manager = FileSystemIndexManager()
458+
459+ # 示例:添加一些测试文件
460+ test_files = [
461+ ("C:/Users/Public/Documents", True), # 目录
462+ ("C:/Windows/System32/drivers/etc/hosts", False), # 系统文件
463+ ("C:/Program Files/Python310/LICENSE.txt", False), # 程序文件
464+ ("C:/Windows/notepad.exe", False), # 可执行文件
465+ ]
466+
467+ print("\n--- 添加测试文件 ---")
468+ for path, is_dir in test_files:
469+ if os.path.exists(path):
470+ manager.add_path(path)
471+ else:
472+ print(f"跳过不存在的路径: {path}")
473+
474+ # 示例:递归添加目录
475+ print("\n--- 递归添加用户目录 ---")
476+ user_dir = os.path.expanduser("~")
477+ manager.add_directory_recursive(user_dir)
478+
479+ # 示例:搜索文件
480+ print("\n--- 搜索文件 ---")
481+ manager.search_file("hosts")
482+ manager.search_file("non_existent_file.txt")
483+
484+ # 示例:列出文件
485+ print("\n--- 列出文件 (按名称排序) ---")
486+ manager.list_files("name")
487+
488+ print("\n--- 列出文件 (按大小排序) ---")
489+ manager.list_files("size")
490+
491+ # 示例:查找最大的文件
492+ print("\n--- 查找最大的文件 ---")
493+ manager.find_largest_files(3)
494+
495+ # 示例:查找特定大小范围内的文件
496+ print("\n--- 查找大小在 1MB 到 10MB 之间的文件 ---")
497+ manager.find_files_in_size_range("1MB", "10MB")
498+
499+ # 示例:显示统计信息
500+ print("\n--- 显示索引统计信息 ---")
501+ manager.show_statistics()
502+
503+ # 示例:显示操作历史
504+ print("\n--- 显示操作历史 ---")
505+ manager.show_history()
506+
507+ # 示例:删除文件
508+ print("\n--- 删除文件 ---")
509+ manager.delete_file("hosts")
510+ manager.search_file("hosts") # 验证已删除
511+
512+ print("\n=== 演示完成 ===")
513+ 
514+ 
515+if __name__ == "__main__":
516+ main()
@@ -0,0 +1,518 @@
1+import os
2+import time
3+import random
4+from typing import Optional, List, Tuple
5+ 
6+class TreeNode:
7+ """二叉搜索树节点,表示文件系统中的一个文件或目录"""
8+
9+ def __init__(self, file_path: str, is_directory: bool = False):
10+ self.file_path = file_path
11+ self.file_name = os.path.basename(file_path)
12+ self.is_directory = is_directory
13+ self.size = self._calculate_size()
14+ self.created_time = time.time()
15+ self.left: Optional[TreeNode] = None
16+ self.right: Optional[TreeNode] = None
17+
18+ def _calculate_size(self) -> int:
19+ """计算文件或目录的大小"""
20+ if not os.path.exists(self.file_path):
21+ return 0
22+
23+ if not self.is_directory:
24+ return os.path.getsize(self.file_path)
25+
26+ # 递归计算目录大小
27+ total_size = 0
28+ for dirpath, _, filenames in os.walk(self.file_path):
29+ for f in filenames:
30+ fp = os.path.join(dirpath, f)
31+ try:
32+ total_size += os.path.getsize(fp)
33+ except OSError:
34+ pass
35+ return total_size
36+
37+ def __str__(self) -> str:
38+ """节点的字符串表示"""
39+ node_type = "DIR" if self.is_directory else "FILE"
40+ size_str = self._format_size(self.size)
41+ created_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.created_time))
42+ return f"{node_type} | {self.file_name} | {size_str} | {created_str}"
43+
44+ def _format_size(self, size_bytes: int) -> str:
45+ """格式化文件大小为人类可读的形式"""
46+ if size_bytes < 1024:
47+ return f"{size_bytes} B"
48+ elif size_bytes < 1024 * 1024:
49+ return f"{size_bytes / 1024:.2f} KB"
50+ elif size_bytes < 1024 * 1024 * 1024:
51+ return f"{size_bytes / (1024 * 1024):.2f} MB"
52+ else:
53+ return f"{size_bytes / (1024 * 1024 * 1024):.2f} GB"
54+ 
55+ 
56+class BinarySearchTree:
57+ """二叉搜索树实现,用于文件系统索引管理"""
58+
59+ def __init__(self):
60+ self.root: Optional[TreeNode] = None
61+ self.node_count = 0
62+
63+ def insert(self, file_path: str, is_directory: bool = False) -> bool:
64+ """插入文件或目录到二叉搜索树"""
65+ if not os.path.exists(file_path):
66+ print(f"错误: 文件或目录不存在 - {file_path}")
67+ return False
68+
69+ new_node = TreeNode(file_path, is_directory)
70+
71+ if self.root is None:
72+ self.root = new_node
73+ self.node_count += 1
74+ return True
75+
76+ # 递归插入
77+ def _insert_recursive(node: TreeNode, new_node: TreeNode) -> TreeNode:
78+ if new_node.file_name < node.file_name:
79+ if node.left is None:
80+ node.left = new_node
81+ else:
82+ node.left = _insert_recursive(node.left, new_node)
83+ else:
84+ if node.right is None:
85+ node.right = new_node
86+ else:
87+ node.right = _insert_recursive(node.right, new_node)
88+ return node
89+
90+ _insert_recursive(self.root, new_node)
91+ self.node_count += 1
92+ return True
93+
94+ def search(self, file_name: str) -> Optional[TreeNode]:
95+ """根据文件名搜索节点"""
96+ def _search_recursive(node: Optional[TreeNode], target: str) -> Optional[TreeNode]:
97+ if node is None or node.file_name == target:
98+ return node
99+ if target < node.file_name:
100+ return _search_recursive(node.left, target)
101+ return _search_recursive(node.right, target)
102+
103+ return _search_recursive(self.root, file_name)
104+
105+ def delete(self, file_name: str) -> bool:
106+ """根据文件名删除节点"""
107+ if self.root is None:
108+ return False
109+
110+ deleted = [False] # 使用列表作为可变对象传递
111+
112+ def _delete_recursive(node: Optional[TreeNode], target: str) -> Optional[TreeNode]:
113+ if node is None:
114+ return None
115+
116+ if target < node.file_name:
117+ node.left = _delete_recursive(node.left, target)
118+ elif target > node.file_name:
119+ node.right = _delete_recursive(node.right, target)
120+ else:
121+ # 找到目标节点,执行删除
122+ deleted[0] = True
123+
124+ # 情况1: 没有子节点或只有一个子节点
125+ if node.left is None:
126+ return node.right
127+ elif node.right is None:
128+ return node.left
129+
130+ # 情况2: 有两个子节点,找到右子树中的最小节点
131+ temp = self._find_min(node.right)
132+ node.file_path = temp.file_path
133+ node.file_name = temp.file_name
134+ node.is_directory = temp.is_directory
135+ node.size = temp.size
136+ node.created_time = temp.created_time
137+ node.right = _delete_recursive(node.right, temp.file_name)
138+
139+ return node
140+
141+ self.root = _delete_recursive(self.root, file_name)
142+ if deleted[0]:
143+ self.node_count -= 1
144+ return deleted[0]
145+
146+ def _find_min(self, node: TreeNode) -> TreeNode:
147+ """找到以node为根的子树中的最小节点"""
148+ current = node
149+ while current.left is not None:
150+ current = current.left
151+ return current
152+
153+ def inorder_traversal(self) -> List[TreeNode]:
154+ """中序遍历(按文件名排序)"""
155+ result = []
156+
157+ def _inorder_recursive(node: Optional[TreeNode]):
158+ if node is not None:
159+ _inorder_recursive(node.left)
160+ result.append(node)
161+ _inorder_recursive(node.right)
162+
163+ _inorder_recursive(self.root)
164+ return result
165+
166+ def preorder_traversal(self) -> List[TreeNode]:
167+ """前序遍历"""
168+ result = []
169+
170+ def _preorder_recursive(node: Optional[TreeNode]):
171+ if node is not None:
172+ result.append(node)
173+ _preorder_recursive(node.left)
174+ _preorder_recursive(node.right)
175+
176+ _preorder_recursive(self.root)
177+ return result
178+
179+ def postorder_traversal(self) -> List[TreeNode]:
180+ """后序遍历"""
181+ result = []
182+
183+ def _postorder_recursive(node: Optional[TreeNode]):
184+ if node is not None:
185+ _postorder_recursive(node.left)
186+ _postorder_recursive(node.right)
187+ result.append(node)
188+
189+ _postorder_recursive(self.root)
190+ return result
191+
192+ def get_file_count(self) -> int:
193+ """获取文件总数"""
194+ return self.node_count
195+
196+ def get_total_size(self) -> int:
197+ """获取所有文件的总大小"""
198+ def _sum_size_recursive(node: Optional[TreeNode]) -> int:
199+ if node is None:
200+ return 0
201+ return node.size + _sum_size_recursive(node.left) + _sum_size_recursive(node.right)
202+
203+ return _sum_size_recursive(self.root)
204+
205+ def find_largest_file(self) -> Optional[TreeNode]:
206+ """查找最大的文件"""
207+ if self.root is None:
208+ return None
209+
210+ largest = self.root
211+
212+ def _find_largest_recursive(node: Optional[TreeNode]):
213+ nonlocal largest
214+ if node is None:
215+ return
216+
217+ if not node.is_directory and node.size > largest.size:
218+ largest = node
219+
220+ _find_largest_recursive(node.left)
221+ _find_largest_recursive(node.right)
222+
223+ _find_largest_recursive(self.root)
224+ return largest
225+
226+ def find_files_by_size(self, min_size: int, max_size: int) -> List[TreeNode]:
227+ """查找指定大小范围内的文件"""
228+ result = []
229+
230+ def _find_by_size_recursive(node: Optional[TreeNode]):
231+ if node is None:
232+ return
233+
234+ if not node.is_directory and min_size <= node.size <= max_size:
235+ result.append(node)
236+
237+ _find_by_size_recursive(node.left)
238+ _find_by_size_recursive(node.right)
239+
240+ _find_by_size_recursive(self.root)
241+ return result
242+ 
243+ 
244+class FileSystemIndexManager:
245+ """文件系统索引管理器,使用二叉搜索树实现"""
246+
247+ def __init__(self):
248+ self.bst = BinarySearchTree()
249+ self.history = [] # 操作历史记录
250+
251+ def add_path(self, path: str) -> bool:
252+ """添加文件或目录到索引"""
253+ if not os.path.exists(path):
254+ print(f"错误: 路径不存在 - {path}")
255+ return False
256+
257+ is_dir = os.path.isdir(path)
258+ success = self.bst.insert(path, is_dir)
259+
260+ if success:
261+ action = f"添加 {'目录' if is_dir else '文件'}: {path}"
262+ self.history.append(action)
263+ print(f"成功: {action}")
264+ return success
265+
266+ def add_directory_recursive(self, directory: str) -> int:
267+ """递归添加目录及其所有子目录和文件到索引"""
268+ if not os.path.isdir(directory):
269+ print(f"错误: 不是有效的目录 - {directory}")
270+ return 0
271+
272+ added_count = 0
273+
274+ # 首先添加根目录
275+ if self.add_path(directory):
276+ added_count += 1
277+
278+ # 递归添加子目录和文件
279+ for root, dirs, files in os.walk(directory):
280+ # 添加子目录
281+ for dir_name in dirs:
282+ dir_path = os.path.join(root, dir_name)
283+ if self.add_path(dir_path):
284+ added_count += 1
285+
286+ # 添加文件
287+ for file_name in files:
288+ file_path = os.path.join(root, file_name)
289+ if self.add_path(file_path):
290+ added_count += 1
291+
292+ action = f"递归添加目录: {directory},共添加 {added_count} 个项目"
293+ self.history.append(action)
294+ print(f"成功: {action}")
295+ return added_count
296+
297+ def search_file(self, file_name: str) -> None:
298+ """搜索文件并显示结果"""
299+ node = self.bst.search(file_name)
300+ if node:
301+ print(f"找到文件: {node}")
302+ else:
303+ print(f"未找到文件: {file_name}")
304+
305+ action = f"搜索文件: {file_name},结果: {'找到' if node else '未找到'}"
306+ self.history.append(action)
307+
308+ def delete_file(self, file_name: str) -> None:
309+ """从索引中删除文件"""
310+ success = self.bst.delete(file_name)
311+ if success:
312+ print(f"成功删除文件: {file_name}")
313+ else:
314+ print(f"删除失败: 未找到文件 {file_name}")
315+
316+ action = f"删除文件: {file_name},结果: {'成功' if success else '失败'}"
317+ self.history.append(action)
318+
319+ def list_files(self, sort_order: str = "name") -> None:
320+ """列出所有文件"""
321+ if self.bst.get_file_count() == 0:
322+ print("索引中没有文件")
323+ return
324+
325+ print("\n=== 文件列表 ===")
326+ print("类型 | 文件名 | 大小 | 创建时间")
327+ print("-" * 70)
328+
329+ if sort_order == "name":
330+ nodes = self.bst.inorder_traversal()
331+ elif sort_order == "size":
332+ nodes = self.bst.inorder_traversal()
333+ nodes.sort(key=lambda x: x.size, reverse=True)
334+ elif sort_order == "created":
335+ nodes = self.bst.inorder_traversal()
336+ nodes.sort(key=lambda x: x.created_time, reverse=True)
337+ else:
338+ print(f"无效的排序顺序: {sort_order},使用默认排序(按名称)")
339+ nodes = self.bst.inorder_traversal()
340+
341+ for node in nodes:
342+ print(node)
343+
344+ print(f"\n总计: {self.bst.get_file_count()} 个项目,总大小: {node._format_size(self.bst.get_total_size())}")
345+
346+ action = f"列出文件,排序方式: {sort_order}"
347+ self.history.append(action)
348+
349+ def find_largest_files(self, count: int = 5) -> None:
350+ """查找最大的N个文件"""
351+ if self.bst.get_file_count() == 0:
352+ print("索引中没有文件")
353+ return
354+
355+ all_files = [node for node in self.bst.inorder_traversal() if not node.is_directory]
356+ if not all_files:
357+ print("索引中没有文件,只有目录")
358+ return
359+
360+ all_files.sort(key=lambda x: x.size, reverse=True)
361+ largest_files = all_files[:min(count, len(all_files))]
362+
363+ print(f"\n=== 最大的 {len(largest_files)} 个文件 ===")
364+ print("文件名 | 大小 | 路径")
365+ print("-" * 70)
366+
367+ for file in largest_files:
368+ print(f"{file.file_name} | {file._format_size(file.size)} | {file.file_path}")
369+
370+ action = f"查找最大的 {count} 个文件"
371+ self.history.append(action)
372+
373+ def find_files_in_size_range(self, min_size: str, max_size: str) -> None:
374+ """查找指定大小范围内的文件"""
375+ def parse_size(size_str: str) -> int:
376+ """将人类可读的大小字符串解析为字节数"""
377+ size_str = size_str.strip().upper()
378+ if size_str.endswith('KB'):
379+ return int(float(size_str[:-2]) * 1024)
380+ elif size_str.endswith('MB'):
381+ return int(float(size_str[:-2]) * 1024 * 1024)
382+ elif size_str.endswith('GB'):
383+ return int(float(size_str[:-2]) * 1024 * 1024 * 1024)
384+ else:
385+ return int(size_str)
386+
387+ try:
388+ min_bytes = parse_size(min_size)
389+ max_bytes = parse_size(max_size)
390+
391+ if min_bytes > max_bytes:
392+ min_bytes, max_bytes = max_bytes, min_bytes
393+ print(f"注意: 自动交换了最小值和最大值,实际查找范围: {min_size} 到 {max_size}")
394+
395+ files = self.bst.find_files_by_size(min_bytes, max_bytes)
396+
397+ if not files:
398+ print(f"未找到大小在 {min_size} 到 {max_size} 范围内的文件")
399+ return
400+
401+ print(f"\n=== 大小在 {min_size} 到 {max_size} 范围内的文件 ({len(files)} 个) ===")
402+ print("文件名 | 大小 | 路径")
403+ print("-" * 70)
404+
405+ for file in files:
406+ print(f"{file.file_name} | {file._format_size(file.size)} | {file.file_path}")
407+
408+ action = f"查找大小在 {min_size} 到 {max_size} 范围内的文件,找到 {len(files)} 个"
409+ self.history.append(action)
410+
411+ except ValueError:
412+ print(f"错误: 无法解析大小格式,请使用例如 '10MB', '2GB' 或 '5000' (字节)")
413+
414+ def show_statistics(self) -> None:
415+ """显示索引统计信息"""
416+ file_count = self.bst.get_file_count()
417+ if file_count == 0:
418+ print("索引中没有文件")
419+ return
420+
421+ total_size = self.bst.get_total_size()
422+ largest_file = self.bst.find_largest_file()
423+
424+ print("\n=== 索引统计信息 ===")
425+ print(f"总项目数: {file_count}")
426+ print(f"总大小: {TreeNode('', False)._format_size(total_size)}")
427+
428+ if largest_file:
429+ print(f"最大文件: {largest_file.file_name} ({TreeNode('', False)._format_size(largest_file.size)})")
430+
431+ # 计算文件类型分布
432+ file_types = {}
433+ for node in self.bst.inorder_traversal():
434+ if not node.is_directory:
435+ ext = os.path.splitext(node.file_name)[1].lower()
436+ file_types[ext] = file_types.get(ext, 0) + 1
437+
438+ if file_types:
439+ print("\n文件类型分布:")
440+ for ext, count in sorted(file_types.items(), key=lambda x: x[1], reverse=True):
441+ print(f" {ext}: {count} 个文件")
442+
443+ action = "显示索引统计信息"
444+ self.history.append(action)
445+
446+ def show_history(self, limit: int = 10) -> None:
447+ """显示最近的操作历史"""
448+ print(f"\n=== 最近 {min(limit, len(self.history))} 条操作历史 ===")
449+ for i, action in enumerate(reversed(self.history[-limit:])):
450+ print(f"{len(self.history) - i}: {action}")
451+ 
452+ 
453+def main():
454+ """主函数,演示文件系统索引管理器的使用"""
455+ print("=== 文件系统索引管理器 (使用二叉搜索树实现) ===")
456+
457+ manager = FileSystemIndexManager()
458+
459+ # 示例:添加一些测试文件
460+ test_files = [
461+ ("C:/Users/Public/Documents", True), # 目录
462+ ("C:/Windows/System32/drivers/etc/hosts", False), # 系统文件
463+ ("C:/Program Files/Python310/LICENSE.txt", False), # 程序文件
464+ ("C:/Windows/notepad.exe", False), # 可执行文件
465+ ]
466+
467+ print("\n--- 添加测试文件 ---")
468+ for path, is_dir in test_files:
469+ if os.path.exists(path):
470+ manager.add_path(path)
471+ else:
472+ print(f"跳过不存在的路径: {path}")
473+
474+ # 示例:递归添加目录
475+ print("\n--- 递归添加用户目录 ---")
476+ user_dir = os.path.expanduser("~")
477+ manager.add_directory_recursive(user_dir)
478+
479+ # 示例:搜索文件
480+ print("\n--- 搜索文件 ---")
481+ manager.search_file("hosts")
482+ manager.search_file("non_existent_file.txt")
483+
484+ # 示例:列出文件
485+ print("\n--- 列出文件 (按名称排序) ---")
486+ manager.list_files("name")
487+
488+ print("\n--- 列出文件 (按大小排序) ---")
489+ manager.list_files("size")
490+
491+ # 示例:查找最大的文件
492+ print("\n--- 查找最大的文件 ---")
493+ manager.find_largest_files(3)
494+
495+ # 示例:查找特定大小范围内的文件
496+ print("\n--- 查找大小在 1MB 到 10MB 之间的文件 ---")
497+ manager.find_files_in_size_range("1MB", "10MB")
498+
499+ # 示例:显示统计信息
500+ print("\n--- 显示索引统计信息 ---")
501+ manager.show_statistics()
502+
503+ # 示例:显示操作历史
504+ print("\n--- 显示操作历史 ---")
505+ manager.show_history()
506+
507+ # 示例:删除文件
508+ print("\n--- 删除文件 ---")
509+ manager.delete_file("hosts")
510+ manager.search_file("hosts") # 验证已删除
511+
512+ print("\n=== 演示完成 ===")
513+ 
514+ 
515+if __name__ == "__main__":
516+ main()
517+ 
518+