[英]How to return the doubly linked list and remove leaves of the tree?
我當時正在從事類似SPOJ的任務。 目的是在二叉樹(不一定是BST)中找到葉子,將它們從樹中刪除,並使用相同的結構TreeNode而不是其他導入將它們作為一種雙鏈表返回。 例如,如果從樹中刪除了節點2、4和3,則函數返回列表的firs非null元素:null <-2 <-> 4 <-> 3-> null。 TreeNode有一個值以及左右指針。
我使用了遞歸並取消了葉子,以將其從樹中刪除,並在列表中重新創建了它們。 為了保持向列表末尾添加元素的效率,我保留了指向列表最后一個元素的指針。 這就產生了一個眾所周知的更改傳遞給函數的對象的問題。 這是我的代碼:
public TreeNode getLeaves(TreeNode root)
{
if(root == null)
return null;
TreeNode start = new TreeNode(Integer.MIN_VALUE);
TreeNode[] end = {start};
getLeaves(root, start, end);
return start;
}
private void getLeaves(TreeNode root, TreeNode start, TreeNode[] end)
{
if(root == null)
return;
if(root.left == null && root.right == null)
{
addToList(root, start, end);
root = null;
return;
}
getLeaves(root.left, start, end);
getLeaves(root.right, start, end);
}
private void addToList(TreeNode element, TreeNode start, TreeNode[] end)
{
if(end[0].value != Integer.MIN_VALUE)
{
TreeNode t = new TreeNode (element.value);
end[0].right = t;
t.left = end[0];
end[0] = t;
}
else
{
start.value = element.value;
}
}
從樹中刪除葉子不起作用,但是列表已正確返回。 但是,將“ start” TreeNode的值設置為最小int值而不是使用null引用會讓我很煩,使用數組也是如此。 使用“原子引用”會使IMHO更加混亂。 我非常確定,有一種方法可以通過更優雅的方式(並正確刪除葉子)來實現,可能是通過更改分配開始和結束TreeNodes的方法來實現的。 我的方法和/或對所有工作方式的理解都出了問題。 您能幫我把它變成整潔的代碼並解釋我的壞處嗎?
您的第二個GetLeaves
函數中有一個錯誤。 語句root = null;
將局部變量 root
的值設置為null,但是其父級將保留對葉子的引用。
如果將方法bool isLeaf()
到TreeNode
您的時間會容易得多。 我將您的代碼修改為我認為可能有用的代碼。
private bool isLeaf()
{
// This method should be in TreeNode
return left == null && right == null;
}
// Also, TreeNode should have an Add(TreeNode) method
public TreeNode getLeaves(TreeNode root)
{
if( root == null ) // check if the whole tree is empty
return null; // return something relevant here
else if( root.isLeaf() )
return root; //cannot remove this leaf, unfortunately
TreeNode leaves = new TreeNode()
getLeaves(root, leaves);
return leaves;
}
private void getLeaves(TreeNode current, TreeNode leaves)
{
// current is guaranteed to be non-null and not a leaf itself.
if( current.left.isLeaf() ) {
leaves.add(current.left);
current.left = null;
} else {
getLeaves(current.left, leaves);
}
if( current.right.isLeaf() ) {
leaves.add(current.right);
current.right = null;
} else {
getLeaves(current.right, leaves);
}
}
大衛,你是100%正確的。 感謝您的幫助。 如果有人想知道的話,這是迄今為止我提出的最優雅的解決方案,包括David的改進。 我唯一不確定的是addToList方法應該是靜態的還是在元素的上下文中調用它更合適/更通用。
public TreeNode getLeaves(TreeNode root)
{
if(root == null)
return null;
if(root.isLeaf())
return root;
TreeNode[] listEdges = {null, null};
getLeaves(root, listEdges);
return listEdges[0];
}
private void getLeaves(TreeNode root, TreeNode[] edges)
{
if(root == null)
return;
if(root.left != null && root.left.isLeaf())
{
addToList(edges, root.left);
root.left = null;
}
if(root.right != null && root.right.isLeaf())
{
addToList(edges, root.right);
root.right = null;
}
getLeaves(root.left, edges);
getLeaves(root.right, edges);
}
private static void addToList(TreeNode[] edges, TreeNode element)
{
if(edges[1] != null)
{
edges[1].right = element;
element.left = edges[1];
edges[1] = element;
}
else
{
edges[0] = element;
edges[1] = edges[0];
}
}
public boolean isLeaf()
{
return this.right == null && this.left == null;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.