题目描述:
对于一棵二叉排序树,令f=(最大值+最小值)/2,设计一个算法,找出距离 f 值最近、大于 f 值的结点。例如,下图所给定的二叉排序树中,最大值为7,最小值为1,所以 f=(1+7)/2=4,那么在这棵二叉树中,距离结点4最近且大于4的结点为5。
思路:
首先需要找出二叉排序树中的最大值和最小值。由于二叉排序树的特点是,对于任意一个结点,它的左子树上所有结点的值都小于这个结点的值,它的右子树上所有结点的值都大于这个结点的值。所以,在二叉排序树中,最小值一定是最左下的结点,最大值一定是最右下的结点。根据最大值与最小值很容易求出 f 的值。接下来对二叉树进行中序遍历。如果当前结点的值小于 f,那么在这个结点的右子树( 左小右大 )中接着遍历,否则遍历这个结点的左子树。
代码实现:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2020/1/26 11:40
# @Author : buu
# @Software: PyCharm
# @Blog :https://blog.csdn.net/weixin_44321080
class BiTNode:
def __init__(self):
self.data = None
self.lchild = None
self.rchild = None
def getMin(root):
"""
查找值最小的结点
:param root: 二叉树的根结点
:return: 最小值的结点
"""
if root == None:
return root
while root.lchild != None:
root = root.lchild
return root
def getMax(root):
"""
查找值最大的结点
:param root: 二叉树的根结点
:return: 最大值的结点
"""
if root == None:
return root
while root.rchild != None:
root = root.rchild
return root
def array2treee(arr, start, end):
"""
把有序数组转换为二叉树
:param arr:数组
:param start:数组起点
:param end:数组终点
:return:
"""
root = None
if end >= start:
root = BiTNode()
mid = (start + end + 1) // 2
root.data = arr[mid] # 树的根节点为数组中间的元素
# print(root.data,end=' ')
root.lchild = array2treee(arr, start, mid - 1) # 递归地构建左子树
root.rchild = array2treee(arr, mid + 1, end) # 递归地构建右子树
else:
root = None
return root
def getNode(root):
if root == None:
return root
minNode = getMin(root)
maxNode = getMax(root)
midVal = (minNode.data + maxNode.data) / 2
result = None
while root != None:
if root.data <= midVal: # 当前值的结点不大于中间值,则在当前结点的右子树上查找
root = root.rchild
else: # 若当前结点的值大于中间值,则在当前结点的左子树上查找
result = root # 先记录下第一个大于中间值的结点,
# 因为左子树小于当前结点root的值,所以继续向左寻找
root = root.lchild # 直至找到第一个(即距离中间值最近)大于中间值的结点
return result
if __name__ == '__main__':
arr = [1, 2, 3, 4, 5, 6, 7]
root = array2treee(arr, 0, len(arr) - 1)
print('find val: ', end='')
print(getNode(root).data)
结果:
算法性能分析:
这种方法查找最大结点与最小结点的时间复杂度为O(h),h为树的高度。对于有 n 个结点的二叉排序树,最大的高度为O(n),最小的高度为O(logn),所以在查找满足条件的结点的时候,时间复杂度为O(h)。综上,此方法的时间复杂度在最好的情况下是O(logn),最坏的情况下是O(n);
end