二叉树的后继节点
什么是二叉树的后继节点呢? 就是这颗二叉树中序遍历顺序中,当前节点的下一个节点称为这个当前节点的后继节点。
与之相反的是前驱节点,前驱节点,就是二叉树中序遍历的顺序中,当前节点的上一个节点。
如下图:

那么下面我们来看一道具体的面试题 :
【题目】 现在有一种新的二叉树节点类型如下,在此节点类型的二叉树中找到一个节点的后继节点
class Node(object):
"""含有父节点属性的节点类"""
def __init__(self, elem, lchild=None, rchild=None, parent=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild
self.parent = parent
注:该结构比普通二叉树节点结构多了一个指向父节点的parent指针。假设有一 棵Node类型的节点组成的二叉树,树中每个节点的parent指针都正确地指向 自己的父节点,头节点的parent指向None
下面我们来看看这题的思路是什么?
由题目可知,我们的节点类型很特殊,再结合中序遍历的特点是(左,中,右)那么找一个节点的后继节点会有如下两种情况:
情况1:当前节点有右子树
那么针对这个情况,结合我们的中序遍历特点,总结出一个规律 : 如果当前节点有右子树,那么其后继节点为其右子树的最左节点

情况2:当前节点没有有右子树
针对这种情况,那么我们就要用到题目给的条件了,每个节点都有个父节点的属性,我们能通过子节点找到父节点
那么其规律是:如果当前节点没有右子树,定义第一个指针指向当前节点,然后找其父节点,用第二个指针指向它,如果指针1所指的节点是指针2的左孩子,那该指针2节点就是其后继节点,如果不是其左孩子,那么指针1指向其父节点,原来的指针2也指向他的父节点(也就是指针1和指针2都往上调一格)直到指针1所指的节点是指针2节点的左孩子,那么指针2所指的节点就是其后继节点。

所以这就是上面的两种情况,下面贴上完整的代码示例
class Node(object):
"""含有父节点属性的节点类"""
def __init__(self, elem, lchild=None, rchild=None, parent=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild
self.parent = parent
class Tree(object):
"""二叉树"""
def __init__(self):
self.root = None
def add(self, item):
node = Node(item)
if self.root is None:
self.root = node
return
queue = [self.root] # 定义一个队列
while queue:
cur_node = queue.pop(0)
if cur_node.lchild is None:
node.parent = cur_node # 设置当前节点的父节点是队列里弹出的节点
cur_node.lchild = node
return
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
node.parent = cur_node # 设置当前节点的父节点是队列里弹出的节点
cur_node.rchild = node
return
else:
queue.append(cur_node.rchild)
def inorder(self, node):
"""中序遍历"""
if node is None:
return
self.inorder(node.lchild)
print(node.elem, end=" ")
self.inorder(node.rchild)
def getSuccessorNode(self, node):
"""获取节点的后继节点"""
if node is None:
return
if node.rchild is not None: # 右子树不为空
return self.getLeftMost(node.rchild)
else: # 右子树为空
node_parent = node.parent
while node_parent is not None and node_parent.lchild != node: # 当前节点不是父节点的左孩子时,循环 ,当父节点为空时 直接返回空,说明没有后继节点
node = node_parent
node_parent = node.parent
return node_parent
def getLeftMost(self, node):
if node is None:
return None
while node.lchild is not None:
node = node.lchild # 找到最左节点
return node
if __name__ == '__main__':
tree = Tree()
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
tree.add(10)
tree.add(11)
print("中序遍历的结果:")
tree.inorder(tree.root) # 递归方式打印: 8 4 9 2 10 5 11 1 6 3 7
print(" ")
print("节点2的值是:"+ str(tree.root.lchild.elem))
# 查找节点2 的后继节点
# tree.root.lchild ==> 2
node = tree.getSuccessorNode(tree.root.lchild)
print("节点2的后继节点为:"+ str(node.elem))
print(" ")
print("节点8的值是:" + str(tree.root.lchild.lchild.lchild.elem))
# 查找节点8 的后继节点
# tree.root.lchild.lchild.lchild ==> 8
node = tree.getSuccessorNode(tree.root.lchild.lchild.lchild)
print("节点8的后继节点为:" + str(node.elem))
print(" ")
print("节点9的值是:" + str(tree.root.lchild.lchild.rchild.elem))
# 查找节点9 的后继节点
# tree.root.lchild.lchild.rchild ==> 9
node = tree.getSuccessorNode(tree.root.lchild.lchild.rchild)
print("节点9的后继节点为:" + str(node.elem))
print(" ")
print("节点7的值是:" + str(tree.root.rchild.rchild.elem))
# 查找节点7 的后继节点
# tree.root.rchild.rchild ==> 7
node = tree.getSuccessorNode(tree.root.rchild.rchild)
if node is not None:
print("节点7的后继节点为:" + str(node.elem))
else:
print("节点7的后继节点为:None")
结果如下:

新增:求前驱节点
后增加上与求后继节点同理的求前驱节点的代码
class Node(object):
"""含有父节点属性的节点类"""
def __init__(self, elem, lchild=None, rchild=None, parent=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild
self.parent = parent
class Tree(object):
"""二叉树"""
def __init__(self):
self.root = None
def add(self, item):
node = Node(item)
if self.root is None:
self.root = node
return
queue = [self.root] # 定义一个队列
while queue:
cur_node = queue.pop(0)
if cur_node.lchild is None:
node.parent = cur_node # 设置当前节点的父节点是队列里弹出的节点
cur_node.lchild = node
return
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
node.parent = cur_node # 设置当前节点的父节点是队列里弹出的节点
cur_node.rchild = node
return
else:
queue.append(cur_node.rchild)
def inorder(self, node):
"""中序遍历"""
if node is None:
return
self.inorder(node.lchild)
print(node.elem, end=" ")
self.inorder(node.rchild)
def getPrecursorNode(self,node):
"""获取节点的前驱节点"""
if node is None:
return
if node.lchild is not None: # 左子树不为空
return self.getRightMost(node.lchild)
else:
node_parent = node.parent
while node_parent is not None and node_parent.rchild != node:
# 当前节点是父节点的右孩子时停止循环,父节点为None时,停止循环
node = node_parent
node_parent = node.parent
return node_parent
def getRightMost(self, node):
if node is None:
return None
while node.rchild is not None:
node = node.rchild # 找到最右节点
return node
if __name__ == '__main__':
tree = Tree()
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
tree.add(10)
tree.add(11)
print("中序遍历的结果:")
tree.inorder(tree.root) # 递归方式打印: 8 4 9 2 10 5 11 1 6 3 7
print(" ")
print("节点2的值是:" + str(tree.root.lchild.elem))
# 查找节点2 的后继节点
#tree.root.lchild ==> 2
node = tree.getPrecursorNode(tree.root.lchild)
print("节点2的前驱节点为:" + str(node.elem))
print(" ")
print("节点8的值是:" + str(tree.root.lchild.lchild.lchild.elem))
# 查找节点8 的前驱节点
# tree.root.lchild.lchild.lchild ==> 8
node = tree.getPrecursorNode(tree.root.lchild.lchild.lchild)
if node is not None:
print("节点8的前驱节点为:" + str(node.elem))
else:
print("节点8的前驱节点为None")
print(" ")
print("节点9的值是:" + str(tree.root.lchild.lchild.rchild.elem))
# 查找节点9 的前驱节点
# tree.root.lchild.lchild.rchild ==> 9
node = tree.getPrecursorNode(tree.root.lchild.lchild.rchild)
print("节点9的前驱节点为:" + str(node.elem))
print(" ")
print("节点10的值是:" + str(tree.root.lchild.rchild.lchild.elem))
# 查找节点10 的前驱节点
# tree.root.lchild.rchild.lchild ==> 10
node = tree.getPrecursorNode(tree.root.lchild.rchild.lchild)
print("节点10的前驱节点为:" + str(node.elem))
结果如下:

综上,就是二叉树求前驱和后继节点的全部内容啦,如有不正确的地方,还望加以评论指正。
1万+



被折叠的 条评论
为什么被折叠?



