@@ -128,15 +128,16 @@ extension Megrez.Compositor {
128128 let sortedStates = visited. sorted { $0. distance > $1. distance }
129129 let statesToRemove = Array ( sortedStates. dropFirst ( keepRecentCount) )
130130
131- // 先從 Set 中移除,再清理參據 (避免 hash 不一致)
131+ // 先從 Set 中移除(避免 hash 不一致)
132132 for state in statesToRemove {
133133 visited. remove ( state)
134- state. node = nil
135- state. prev = nil
136134 }
135+
136+ // 採用鏈條逆向清理策略清理要移除的狀態
137+ Self . cleanSearchStateChains ( allStates: Set ( statesToRemove) )
137138 }
138139
139- /// 即時清理策略:直接清理各個資料結構,避免額外的 Set 集合
140+ /// 即時清理策略:採用鏈條逆向清理避免循環引用
140141 /// - Parameters:
141142 /// - visited: 已訪問的狀態集合
142143 /// - openSet: 優先序列中剩餘的狀態
@@ -146,23 +147,65 @@ extension Megrez.Compositor {
146147 openSet: inout HybridPriorityQueue < PrioritizedState > ,
147148 leadingState: SearchState
148149 ) {
149- // 策略1: 直接清理 visited set 中的所有狀態
150+ // 收集所有需要清理的 SearchState 物件
151+ var allStates = Set < SearchState > ( )
152+
153+ // 1. 新增 visited set 中的所有狀態
150154 for state in visited {
151- state. node = nil
152- state. prev = nil
155+ allStates. insert ( state)
153156 }
154157
155- // 策略2: 直接清理 openSet 中剩餘的所有狀態
158+ // 2. 新增 openSet 中剩餘的所有狀態
156159 while !openSet. isEmpty {
157160 if let prioritizedState = openSet. dequeue ( ) {
158- prioritizedState. state. node = nil
159- prioritizedState. state. prev = nil
161+ allStates. insert ( prioritizedState. state)
160162 }
161163 }
162164
163- // 策略3: 清理 leadingState
164- leadingState. node = nil
165- leadingState. prev = nil
165+ // 3. 新增 leadingState
166+ allStates. insert ( leadingState)
167+
168+ // 4. 採用鏈條逆向清理策略
169+ Self . cleanSearchStateChains ( allStates: allStates)
170+ }
171+
172+ /// 採用鏈條逆向清理策略,從最遠端的 prev 開始逐一退行清理
173+ /// - Parameter allStates: 所有需要清理的狀態集合
174+ private static func cleanSearchStateChains( allStates: Set < SearchState > ) {
175+ var processedStates = Set < SearchState > ( )
176+
177+ // 對每個狀態進行鏈條逆向清理
178+ for state in allStates {
179+ guard !processedStates. contains ( state) else { continue }
180+
181+ // 找到鏈條的末端(最遠端的 prev)
182+ var chainStates = [ SearchState] ( )
183+ var current : SearchState ? = state
184+
185+ // 追溯整個鏈條,收集所有狀態
186+ while let currentState = current {
187+ // 避免無限循環(檢測循環引用)
188+ if chainStates. contains ( where: { $0 === currentState } ) {
189+ break
190+ }
191+ chainStates. append ( currentState)
192+ current = currentState. prev
193+ }
194+
195+ // 從鏈條末端開始逐一清理(逆向清理)
196+ for i in stride ( from: chainStates. count - 1 , through: 0 , by: - 1 ) {
197+ let stateToClean = chainStates [ i]
198+
199+ // 首先清理 node 引用
200+ stateToClean. node = nil
201+
202+ // 然後清理 prev 引用(從末端開始,確保沒有懸掛指針)
203+ stateToClean. prev = nil
204+
205+ // 標記為已處理
206+ processedStates. insert ( stateToClean)
207+ }
208+ }
166209 }
167210}
168211
@@ -196,9 +239,9 @@ extension Megrez.Compositor {
196239
197240 // MARK: Internal
198241
199- var node : Megrez . Node ? // 當前節點(可變,用於清理)
242+ weak var node : Megrez . Node ? // 當前節點(可變,用於清理)
200243 let position : Int // 在輸入串中的位置
201- var prev : SearchState ? // 前一個狀態
244+ weak var prev : SearchState ? // 前一個狀態
202245 var distance : Double // 累計分數
203246
204247 // MARK: - Hashable 協定實作
@@ -207,11 +250,33 @@ extension Megrez.Compositor {
207250 lhs. originalNodeRef === rhs. originalNodeRef && lhs. position == rhs. position
208251 }
209252
210- /// 清理單一 SearchState 的參據
253+ /// 清理單一 SearchState 的參據,採用鏈條逆向清理策略
211254 /// 注意:由於新的清理策略是直接清理各個集合,這個方法現在主要用於向下相容
212255 func cleanState( ) {
213- node = nil
214- prev = nil
256+ // 對於單一狀態,我們使用簡化的鏈條清理
257+ var chainStates = [ Self] ( )
258+ var current : SearchState ? = self
259+
260+ // 追溯整個鏈條,收集所有狀態
261+ while let currentState = current {
262+ // 避免無限循環(檢測循環引用)
263+ if chainStates. contains ( where: { $0 === currentState } ) {
264+ break
265+ }
266+ chainStates. append ( currentState)
267+ current = currentState. prev
268+ }
269+
270+ // 從鏈條末端開始逐一清理(逆向清理)
271+ for i in stride ( from: chainStates. count - 1 , through: 0 , by: - 1 ) {
272+ let stateToClean = chainStates [ i]
273+
274+ // 首先清理 node 引用
275+ stateToClean. node = nil
276+
277+ // 然後清理 prev 引用(從末端開始,確保沒有懸掛指針)
278+ stateToClean. prev = nil
279+ }
215280 }
216281
217282 func hash( into hasher: inout Hasher ) {
0 commit comments