|
| 1 | +# Design Document |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +算法解释增强系统旨在为全排列可视化工具添加更深入的算法概念展示功能。参考 LeetCode 题解的讲解方式,通过 Used 数组可视化、递归调用栈展示、"选择-探索-撤销"模式高亮、伪代码同步等功能,帮助用户深入理解回溯算法的执行原理。 |
| 6 | + |
| 7 | +核心功能包括: |
| 8 | +- Used 数组状态可视化 |
| 9 | +- 递归调用栈实时展示 |
| 10 | +- 回溯三阶段模式高亮 |
| 11 | +- 伪代码同步高亮 |
| 12 | +- 剪枝原因提示 |
| 13 | + |
| 14 | +## Architecture |
| 15 | + |
| 16 | +```mermaid |
| 17 | +graph TB |
| 18 | + subgraph UI Layer |
| 19 | + App[App Component] |
| 20 | + UsedArrayPanel[UsedArrayPanel] |
| 21 | + RecursionStackPanel[RecursionStackPanel] |
| 22 | + PhaseIndicator[PhaseIndicator] |
| 23 | + PseudocodePanel[PseudocodePanel] |
| 24 | + TreeVisualization[TreeVisualization Enhanced] |
| 25 | + end |
| 26 | + |
| 27 | + subgraph Logic Layer |
| 28 | + AlgorithmStateEngine[AlgorithmStateEngine] |
| 29 | + UsedArrayTracker[UsedArrayTracker] |
| 30 | + StackFrameBuilder[StackFrameBuilder] |
| 31 | + PseudocodeMapper[PseudocodeMapper] |
| 32 | + end |
| 33 | + |
| 34 | + subgraph State Management |
| 35 | + AppState[React State] |
| 36 | + end |
| 37 | + |
| 38 | + App --> UsedArrayPanel |
| 39 | + App --> RecursionStackPanel |
| 40 | + App --> PhaseIndicator |
| 41 | + App --> PseudocodePanel |
| 42 | + App --> TreeVisualization |
| 43 | + |
| 44 | + AlgorithmStateEngine --> UsedArrayTracker |
| 45 | + AlgorithmStateEngine --> StackFrameBuilder |
| 46 | + AlgorithmStateEngine --> PseudocodeMapper |
| 47 | + |
| 48 | + UsedArrayTracker --> AppState |
| 49 | + StackFrameBuilder --> AppState |
| 50 | + PseudocodeMapper --> AppState |
| 51 | + |
| 52 | + AppState --> UsedArrayPanel |
| 53 | + AppState --> RecursionStackPanel |
| 54 | + AppState --> PhaseIndicator |
| 55 | + AppState --> PseudocodePanel |
| 56 | +``` |
| 57 | + |
| 58 | +## Components and Interfaces |
| 59 | + |
| 60 | +### Used Array Tracker |
| 61 | + |
| 62 | +```typescript |
| 63 | +// Used 数组状态 |
| 64 | +interface UsedArrayState { |
| 65 | + numbers: number[]; // 原始输入数组 |
| 66 | + used: boolean[]; // 每个数字的使用状态 |
| 67 | + lastChangedIndex: number | null; // 最近变化的索引(用于动画) |
| 68 | + changeType: 'select' | 'backtrack' | null; // 变化类型 |
| 69 | +} |
| 70 | + |
| 71 | +// Used 数组追踪器 |
| 72 | +interface IUsedArrayTracker { |
| 73 | + getUsedArray(inputNumbers: number[], currentPath: number[]): UsedArrayState; |
| 74 | + getChangedIndex(prevPath: number[], currentPath: number[], inputNumbers: number[]): number | null; |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +### Recursion Stack |
| 79 | + |
| 80 | +```typescript |
| 81 | +// 栈帧结构 |
| 82 | +interface StackFrame { |
| 83 | + depth: number; // 递归深度(从0开始) |
| 84 | + path: number[]; // 当前路径 |
| 85 | + available: number[]; // 可选数字 |
| 86 | + currentChoice: number | null; // 当前选择的数字 |
| 87 | +} |
| 88 | + |
| 89 | +// 递归栈状态 |
| 90 | +interface RecursionStackState { |
| 91 | + frames: StackFrame[]; |
| 92 | + maxDepth: number; |
| 93 | +} |
| 94 | + |
| 95 | +// 栈帧构建器 |
| 96 | +interface IStackFrameBuilder { |
| 97 | + buildStack(currentPath: number[], available: number[], inputNumbers: number[]): RecursionStackState; |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +### Phase Indicator |
| 102 | + |
| 103 | +```typescript |
| 104 | +// 回溯阶段 |
| 105 | +type BacktrackPhase = 'choose' | 'explore' | 'unchoose' | 'complete' | 'idle'; |
| 106 | + |
| 107 | +// 阶段指示器状态 |
| 108 | +interface PhaseIndicatorState { |
| 109 | + phase: BacktrackPhase; |
| 110 | + targetNumber: number | null; // 选择或撤销的数字 |
| 111 | + description: string; // 阶段描述 |
| 112 | +} |
| 113 | + |
| 114 | +// 阶段颜色映射 |
| 115 | +const PHASE_COLORS: Record<BacktrackPhase, string> = { |
| 116 | + choose: '#4CAF50', // 绿色 - 选择 |
| 117 | + explore: '#2196F3', // 蓝色 - 探索 |
| 118 | + unchoose: '#FF9800', // 橙色 - 撤销 |
| 119 | + complete: '#9C27B0', // 紫色 - 完成 |
| 120 | + idle: '#9E9E9E' // 灰色 - 空闲 |
| 121 | +}; |
| 122 | +``` |
| 123 | + |
| 124 | +### Pseudocode Mapper |
| 125 | + |
| 126 | +```typescript |
| 127 | +// 伪代码行 |
| 128 | +interface PseudocodeLine { |
| 129 | + lineNumber: number; |
| 130 | + code: string; |
| 131 | + indent: number; |
| 132 | + type: 'function' | 'condition' | 'action' | 'recursion' | 'return'; |
| 133 | +} |
| 134 | + |
| 135 | +// 伪代码状态 |
| 136 | +interface PseudocodeState { |
| 137 | + lines: PseudocodeLine[]; |
| 138 | + highlightedLine: number | null; |
| 139 | + highlightType: 'select' | 'backtrack' | 'complete' | 'recursion' | null; |
| 140 | +} |
| 141 | + |
| 142 | +// 伪代码映射器 |
| 143 | +interface IPseudocodeMapper { |
| 144 | + getHighlightedLine(stepType: StepType): number; |
| 145 | + getPseudocode(): PseudocodeLine[]; |
| 146 | +} |
| 147 | + |
| 148 | +// 回溯算法伪代码 |
| 149 | +const BACKTRACK_PSEUDOCODE: PseudocodeLine[] = [ |
| 150 | + { lineNumber: 1, code: 'function backtrack(path, used):', indent: 0, type: 'function' }, |
| 151 | + { lineNumber: 2, code: ' if path.length == n:', indent: 1, type: 'condition' }, |
| 152 | + { lineNumber: 3, code: ' result.add(path.copy()) // 添加结果', indent: 2, type: 'action' }, |
| 153 | + { lineNumber: 4, code: ' return', indent: 2, type: 'return' }, |
| 154 | + { lineNumber: 5, code: ' for i in range(n):', indent: 1, type: 'condition' }, |
| 155 | + { lineNumber: 6, code: ' if used[i]: continue // 剪枝', indent: 2, type: 'condition' }, |
| 156 | + { lineNumber: 7, code: ' path.append(nums[i]) // 选择', indent: 2, type: 'action' }, |
| 157 | + { lineNumber: 8, code: ' used[i] = true', indent: 2, type: 'action' }, |
| 158 | + { lineNumber: 9, code: ' backtrack(path, used) // 递归', indent: 2, type: 'recursion' }, |
| 159 | + { lineNumber: 10, code: ' path.pop() // 撤销选择', indent: 2, type: 'action' }, |
| 160 | + { lineNumber: 11, code: ' used[i] = false', indent: 2, type: 'action' }, |
| 161 | +]; |
| 162 | +``` |
| 163 | + |
| 164 | +### React Components Props |
| 165 | + |
| 166 | +```typescript |
| 167 | +// Used 数组面板 Props |
| 168 | +interface UsedArrayPanelProps { |
| 169 | + state: UsedArrayState; |
| 170 | +} |
| 171 | + |
| 172 | +// 递归栈面板 Props |
| 173 | +interface RecursionStackPanelProps { |
| 174 | + state: RecursionStackState; |
| 175 | + currentDepth: number; |
| 176 | +} |
| 177 | + |
| 178 | +// 阶段指示器 Props |
| 179 | +interface PhaseIndicatorProps { |
| 180 | + state: PhaseIndicatorState; |
| 181 | +} |
| 182 | + |
| 183 | +// 伪代码面板 Props |
| 184 | +interface PseudocodePanelProps { |
| 185 | + state: PseudocodeState; |
| 186 | +} |
| 187 | +``` |
| 188 | + |
| 189 | +## Data Models |
| 190 | + |
| 191 | +### Extended Animation Step |
| 192 | + |
| 193 | +```typescript |
| 194 | +// 扩展的动画步骤(包含算法解释信息) |
| 195 | +interface ExtendedAnimationStep extends AnimationStep { |
| 196 | + usedArray: boolean[]; |
| 197 | + stackDepth: number; |
| 198 | + phase: BacktrackPhase; |
| 199 | + highlightedPseudocodeLine: number; |
| 200 | +} |
| 201 | +``` |
| 202 | + |
| 203 | +### Algorithm Explanation State |
| 204 | + |
| 205 | +```typescript |
| 206 | +interface AlgorithmExplanationState { |
| 207 | + // Used 数组 |
| 208 | + usedArrayState: UsedArrayState; |
| 209 | + |
| 210 | + // 递归栈 |
| 211 | + recursionStackState: RecursionStackState; |
| 212 | + |
| 213 | + // 阶段指示 |
| 214 | + phaseState: PhaseIndicatorState; |
| 215 | + |
| 216 | + // 伪代码 |
| 217 | + pseudocodeState: PseudocodeState; |
| 218 | +} |
| 219 | +``` |
| 220 | + |
| 221 | +## Correctness Properties |
| 222 | + |
| 223 | +*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.* |
| 224 | + |
| 225 | +### Property 1: Used Array Consistency |
| 226 | +*For any* animation step with a current path, the used array SHALL have `true` for exactly those numbers that appear in the current path, and `false` for all other numbers. |
| 227 | +**Validates: Requirements 1.1, 1.2, 1.3** |
| 228 | + |
| 229 | +### Property 2: Stack Depth Equals Path Length |
| 230 | +*For any* animation step, the recursion stack depth SHALL equal the length of the current path. |
| 231 | +**Validates: Requirements 2.1, 2.2, 2.3** |
| 232 | + |
| 233 | +### Property 3: Stack Frame Path Consistency |
| 234 | +*For any* stack frame at depth d, the path stored in that frame SHALL be a prefix of length d of the current path. |
| 235 | +**Validates: Requirements 2.4** |
| 236 | + |
| 237 | +### Property 4: Phase Indicator Correctness |
| 238 | +*For any* select step, the phase indicator SHALL show "choose" with the last number in the current path. *For any* backtrack step, the phase indicator SHALL show "unchoose" with the number that was removed. |
| 239 | +**Validates: Requirements 3.1, 3.3** |
| 240 | + |
| 241 | +### Property 5: Pseudocode Line Mapping |
| 242 | +*For any* step type, the highlighted pseudocode line SHALL correspond to the correct action: select → line 7/8, backtrack → line 10/11, complete → line 3. |
| 243 | +**Validates: Requirements 4.2, 4.3, 4.4, 4.5** |
| 244 | + |
| 245 | +## Error Handling |
| 246 | + |
| 247 | +### State Inconsistency |
| 248 | + |
| 249 | +| Error Condition | Handling | |
| 250 | +|----------------|----------| |
| 251 | +| Used array length mismatch | Reset to match input numbers length | |
| 252 | +| Stack depth exceeds input size | Cap at input size | |
| 253 | +| Invalid phase for step type | Default to 'idle' phase | |
| 254 | +| Pseudocode line out of range | Highlight no line | |
| 255 | + |
| 256 | +### Edge Cases |
| 257 | + |
| 258 | +- 空输入数组:显示空的 used 数组和栈 |
| 259 | +- 单元素数组:栈深度最大为 1 |
| 260 | +- 动画重置:清空所有状态到初始值 |
| 261 | + |
| 262 | +## Testing Strategy |
| 263 | + |
| 264 | +### Unit Testing |
| 265 | + |
| 266 | +使用 Vitest 进行单元测试: |
| 267 | + |
| 268 | +- `UsedArrayTracker.getUsedArray` 的状态计算 |
| 269 | +- `StackFrameBuilder.buildStack` 的栈构建 |
| 270 | +- `PseudocodeMapper.getHighlightedLine` 的行映射 |
| 271 | +- React 组件的渲染和状态显示 |
| 272 | + |
| 273 | +### Property-Based Testing |
| 274 | + |
| 275 | +使用 fast-check 进行属性测试: |
| 276 | + |
| 277 | +- 配置每个属性测试运行至少 100 次迭代 |
| 278 | +- 每个属性测试必须标注对应的正确性属性 |
| 279 | +- 格式:`**Feature: algorithm-explanation-enhancement, Property {number}: {property_text}**` |
| 280 | + |
| 281 | +测试重点: |
| 282 | +1. Used 数组与当前路径的一致性 |
| 283 | +2. 递归栈深度与路径长度的对应关系 |
| 284 | +3. 阶段指示器与步骤类型的匹配 |
| 285 | +4. 伪代码高亮行与步骤类型的映射 |
0 commit comments