如果树遍历的成本与实际操作的成本相比较低,那么值得预先计算进度数据。
最简单的方法
如您所述,计算所有节点,然后在应用操作时跟踪已完成的节点数。
足以应付 99% 的情况。需要注意的是,如果操作正在进行一些修剪(跳过不必要的节点等),则节点计数不能准确描述进度,因为跳过的节点对计数没有贡献。因此,完成后条形图可能会从 60% 跃升至 100%。
在下面的例子中,进程跳转到B下面的节点
A
/ \
/ \
(B) F
/|\ /|\
C D E G H I
进度条会显示:
[Node] [True Progress] [Displayed]
A 10% 10%
B 20% 20%
F 60% 30%
G 70% 40%
H 80% 50%
I 90% 60%
- 100% 100%
使用地标的更精确方式
您可以在初始设置期间放置地标。跟踪列表中的前 200 个项目。当你达到 200 时,放开列表中的所有其他对象(回到 100 项)。现在跟踪遇到的每个其他节点。当您遇到总共 400 个节点时,该列表将增长回 200 个对象。你再次放开其他人,但从这一点开始跟踪四分之一的物体,等等。
这样,地标列表在 100/200 个节点之间振荡。当树被完全解析时,列表上可能有大约 120 个对象,均匀分布在树周围。现在您可以开始操作了。当遇到一个节点时,检查它是否是列表。如果是,您可以将进度条跳转到该元素的位置(如果元素是#84,则进度为 84 / 120 = 70%
操作可能会跳过一些节点,但进度最终应该会遇到一些地标,所以进度会跳回到合适的进度比率。
所有数字都是可调整的,因此可以增加地标列表的大小以获得更好的精度/反应性。
使用相同的示例,列出 5 个地标
Node Landmarks Steps Comments
A [A----] 1 -
B [AB---] 1 -
A C [ABC--] 1 -
/ \ D [ABCD-] 1 -
/ \ E [ABCDE] 1 -
(B) F F [BDF--] 2 Cleanup of A&C&E
/|\ /|\ G [BDF--] 2 G is skipped
C D E G H I H [BDFH-] 2 -
I [BDFH-] 2 Done
我们得到一个包含 5 个地标的列表,每个地标代表 20%
现在在执行操作时(完全跳过 B),进度条将指示:
[Node] [True Progress] [Displayed]
A 10% 0%
B 20% 20%
F 60% 60%
G 70% 60%
H 80% 80%
I 90% 80%
- 100% 100%
改进
可以跟踪两个连续地标的最低共同祖先 (LCA)。
如果操作退出 LCA,它可以推断其进度已跳过下一个地标,因此即使跳过了地标 #85,也会提供一些进度信息。
进入和退出节点之间的行为会发生变化:您注册进入地标,并退出 LCA
Node Landmarks LCA Steps Comments
A [A----] [----] 1 -
B [AB---] [A---] 1 A is LCA of A&B
A C [ABC--] [AB--] 1 B is LCA of B&C
/ \ D [ABCD-] [ABB-] 1 B is LCA of C&D
/ \ E [ABCDE] [ABBB] 1 B is LCA of D&E
(B) F F [BDF--] [BA--] 2 Cleanup, recompute LCAs
/|\ /|\ G [BDF--] [BA--] 2 Skipped
C D E G H I H [BDFH-] [BAF-] 2 F is LCA of F&H
I [BDFHI] [BAFF] 2 Should be skipped, is Registered as last node of the tree (F is LCA of H&I)
现在在执行操作时(完全跳过 B),进度条将指示:
[Node] [True Progress] [Displayed] [Tracked ] [Tracked] [Comments]
[Landmark] [ LCA ]
->A 10% 0% B - Tracking landmark B...
->B 20% 20% D B Found Tracked Landmark B, Now tracking D (LCA of D,B is B)
(B) 20% 20% D B (Process skips Nodes C/D/E)
<-B 60% 40% F A Exiting LCA B, must have jumped over Landmark D, now tracking F
A 60% 40% F A -
->F 60% 60% H F Entering Landmark F, now tracking H (LCA of F,H is F)
->G 70% 60% H F -
->H 80% 80% I F Found Tracked Landmark H, now tracking I (LCA if H, I is F)
->I 90% 100% Found Tracked Landmark I (last item), operation should be complete