Если стоимость обхода дерева ниже по сравнению со стоимостью фактической операции, то стоит предварительно рассчитать данные о ходе выполнения.
Самый простой способ
Как вы описали, подсчитывает все узлы, а затем отслеживает, сколько узлов было завершено по мере применения операции.
Достаточно хорошо для 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 объектов. Вы снова отпускаете друг друга, но с этого момента следите за 1 из 4 объектов и т. Д.
Таким образом, список ориентиров колеблется между 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