擁有原始和「最終」/ 結果樹。我想比較這些樹木並「重現」這些步驟,這些步驟將被攜帶以獲得相同的結果。將原始樹合併到結果樹中的步驟
現實生活中的例子:在數據庫中有原始樹。工作人員已準備好更改(在App中生成新的結果樹),現在我們需要更新數據庫。我們無法刪除數據庫並重新上傳,因爲可能有尚未生成的數據。
類/表定義:
class TreeNode
{
public string Text { get; set; }
public TreeNode Parent { get; set; }
/* some other properties */
}
實施例的樹木:
Origin Result
|A |A
| -1 | -2
| -2 |C
|B | -3
| -5 |D
| --£ | -1
|C | --£
|F | -5
| -7 |E
|H | -6
|G
| -4
|H
我希望是有一個算法,通過該我將被允許處理時的對象是加入 ,刪除或移動。
重要信息:有其他家長不應該刪除和加入後面的對象,相反,他們應該只有下其他家長感動!刪除會導致數據丟失。
實施例:
Mark B as removed
Mark F as removed
Add D
Add E
Add G
Move 1 under D
Move 5 under D
Mark 7 as removed
Add 3 under C
Add 6 under E
Add 4 under G
Move £ under 1
Removed 7
Removed F
Removed B
自己的解決方案
我創建樣品與的Win-形式和的TreeView。我的算法僅適用於每個級別的基礎(例如,將1從A移動到D),但不能跨越。元素是第一個被刪除的市場,最後被刪除。
代碼:
//Recursive loop to find all nodes in Nth level
private IEnumerable<TreeNode> getNodesOnLevel(TreeNodeCollection aCollection, int aLevel)
{
var lResultTreeNodeCol = new List<TreeNode>();
if (aLevel == 1)
return aCollection.Cast<TreeNode>();
foreach(TreeNode nNode in aCollection)
{
lResultTreeNodeCol.AddRange(getNodesOnLevel(nNode.Nodes, aLevel - 1));
}
return lResultTreeNodeCol;
}
//Called once
public void UpdateTrees(TreeNodeCollection aCollectionA, TreeNodeCollection aCollectionB)
{
List<TreeNode> lRemoved = new List<TreeNode>();
for (int i = 1; UpdateWithLevel(aCollectionA, aCollectionB, i, ref lRemoved) > 0; i++)
{
}
var lRem = lRemoved.LastOrDefault();
do
{
W($"Removed {lRem.Text}");
lRemoved.Remove(lRem);
} while ((lRem = lRemoved.LastOrDefault()) != null);
}
//Called per level
private int UpdateWithLevel(TreeNodeCollection aCollectionA, TreeNodeCollection aCollectionB, int level, ref List<TreeNode> aRemoved)
{
int lNumOfUpdates = 0;
var colA = getNodesOnLevel(aCollectionA, level);
var colB = getNodesOnLevel(aCollectionB, level);
//Search Original collection, compare to Result collection
foreach (TreeNode nodeA in colA)
{
//Find nodeA in Result collection
var lNodeAinColB = colB.FirstOrDefault((a) => a.Text == nodeA.Text);
if(lNodeAinColB == null) //NodeA not found in result collection - delete
{
aRemoved.Add(nodeA);
W($"Mark {nodeA.Text} as removed");
lNumOfUpdates++;
}
else if((lNodeAinColB.Parent?.Text ?? "") != (nodeA.Parent?.Text ?? "")) //NodeA exists in Result collection, different parrent -> must be moved
{
W($"Move {nodeA.Text} under {lNodeAinColB.Parent.Text}");
lNumOfUpdates++;
}
}
//Search Result collection, if Original collection does not have nodeB, we must create it (add)
foreach (TreeNode nodeB in colB)
{
if (!colA.Contains(nodeB, new TestNodeEquality()))
{
W($"Add {nodeB.Text}" + ((nodeB.Parent != null)?$" under {nodeB.Parent.Text}":""));
lNumOfUpdates++;
}
}
return lNumOfUpdates;
}
我還沒有找到一個適合我的問題,也不是寶貴的資源&我真的想避免重複輪的任何話題。
問題(S):
有現有&工作alghoritm(名稱/參考)?什麼是這種被稱爲(Tree Diff/Merge/Lookup/..)的alghorithms/actions?
我可以以任何方式優化alghoritm嗎?
@jdweng你能指點我指導文章嗎? – Tatranskymedved
如果每個節點都有一個唯一的標識,那麼您可以輕鬆比較它們的狀態更改,逐個節點忽略級別,然後應用更改,我想呢? – AKX
https://en.wikipedia.org/wiki/Tree_sort https://en.wikipedia.org/wiki/Binary_search_tree https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree https:// en .wikipedia.org/wiki/Binary_tree https://en.wikipedia.org/wiki/Heapsort – jdweng