Why do I need if node after while queue to invert binary tree
Question:
I was trying to invert a binary tree (i.e. swap all left & right children)
class Node(object):
def __init__(self, value=None, left=None, right=None):
self.value = value
self.left = left
self.right = right
def __repr__(self):
return f"Node({self.value}, {self.left}, {self.right})"
from collections import deque
def invert(root):
q=deque([root])
while q:
n=q.popleft() #n as in node
if n: #why do I need this
n.left,n.right=n.right,n.left
q.append(n.left)
q.append(n.right)
return root
root = Node(1, Node(2), Node(3))
invert(root)
I realized if I remove if n
, I get NoneType
error. I was thinking if while q
is true, then if n
will always be true so if n
is redundant code.
Answers:
It is needed.
First of all it is needed when the tree is empty, because then that q=deque([root])
will have put a None
value on the queue, which should be ignored in the loop.
But also when the tree is not empty it is needed:
When a node n
does not have both left and right children, then one (or both) of the q.append
calls will append a None
value on the queue. And so in one of the next iterations of the loop this None
value will be popped from the queue. But in that case nothing should happen.
So yes, the if
is needed.
You can rearrange the code, but somewhere you’ll have to detect None
values. For instance, take this variant:
(NB: the comment "n as in node" indicates you should just name it node
instead of n
)
if not root:
return
queue = deque([root])
while queue:
node = queue.popleft()
node.left, node.right = node.right, node.left
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root
This version avoids that the queue would ever receive a None
value, but it still means you need an if
— in this case three of them!
I was trying to invert a binary tree (i.e. swap all left & right children)
class Node(object):
def __init__(self, value=None, left=None, right=None):
self.value = value
self.left = left
self.right = right
def __repr__(self):
return f"Node({self.value}, {self.left}, {self.right})"
from collections import deque
def invert(root):
q=deque([root])
while q:
n=q.popleft() #n as in node
if n: #why do I need this
n.left,n.right=n.right,n.left
q.append(n.left)
q.append(n.right)
return root
root = Node(1, Node(2), Node(3))
invert(root)
I realized if I remove if n
, I get NoneType
error. I was thinking if while q
is true, then if n
will always be true so if n
is redundant code.
It is needed.
First of all it is needed when the tree is empty, because then that q=deque([root])
will have put a None
value on the queue, which should be ignored in the loop.
But also when the tree is not empty it is needed:
When a node n
does not have both left and right children, then one (or both) of the q.append
calls will append a None
value on the queue. And so in one of the next iterations of the loop this None
value will be popped from the queue. But in that case nothing should happen.
So yes, the if
is needed.
You can rearrange the code, but somewhere you’ll have to detect None
values. For instance, take this variant:
(NB: the comment "n as in node" indicates you should just name it node
instead of n
)
if not root:
return
queue = deque([root])
while queue:
node = queue.popleft()
node.left, node.right = node.right, node.left
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root
This version avoids that the queue would ever receive a None
value, but it still means you need an if
— in this case three of them!