6 3 8 1 5 7 9 0 2 4
二叉搜索树是 左子树的关键字 <= 父节点的关键字 <= 右子树关键字的二叉树,而完全二叉树是叶子节点只分布在最后两层,同时倒数第二层被填满,最后一层从左到右依次填满的二叉树,同时具有上述特性的二叉树叫做完全二叉搜索树。
要求输入n个值,建立完全二叉搜索树,然后输出该树的层序遍历。
不难得出对于一个确定的序列,完全二叉树只有一个(不然怎么比较答案对不对)。首先对于一个长度为n的序列来说,由它建立的完全二叉搜索树形状只有一个,同时,我们知道如果对一个二叉搜索树进行中序遍历就是一个由小到大的序列,所以每一个位置的关键字的排序必然是确定的。就比如说最左边的一个一定是最小的,他的父节点倒数第二,右兄弟倒数第三等等依次类推。。。。
解法1:
根节点的左边的关键字比其小,右边的关键字比其大,而树的形状又是确定的,所以可以由此确定根节点的位置,然后再递归的求解左右子树的根节点。该方法是我刚开始的想法,编程比较复杂,我没有实现出来。
解法2:
第二种方法是基于一种观察的规律,我发现最后一层其序号一定是1 3 5 7 ..... 倒数第二层一定是 2 6 10 14 。。。。。 (可以通过中序遍历的结果推导出来)。
其倒数第n层是 n 3*n 5*n 7*n .....
import math def build(nu,length): k = math.log(length+1,2) #计算树的高度k(每层节点都算一单位的高度),k为小数时说明最后一层不满。 nu1 = [None] result = [None for m in xrange(length+1)] t = 1 if int(k) < k: #最后一层不满 k = int(k) last = 2**k #计算最后一层第一个元素位置 i = 0 for m in xrange(last,length+1): #最后一层在区间[last,length]内,依次为1,3,5,7..... n = t*(2*i+1) result[m] = nu[n] nu1.append(nu[n+1]) #当最后一层不满时,需要将未上树的关键字全部取出来重新生成一个输入序列。 i += 1 nu1.extend(nu[n+2:]) nu = nu1 if k > 0: #满树时正好满足前面分析的规律。 k = int(k) last = 2**(k-1) while(last>0): i = 0 for m in xrange(last,2*last): result[m] = nu[t*(2*i+1)] i += 1 t *= 2 last = last >> 1 result = [str(m) for m in result[1:]] return result length = input() if length > 0: nu = raw_input().split() nu = [int(m) for m in nu] nu.sort() nu.insert(0,None) result = build(nu,length) print ' '.join(result)
解法3:
第三种解法是在网上找到的,其实与解法二类似,但是比较巧妙的利用了二叉树中序遍历的规律。
我们知道完全二叉树可以用一个数组来表示节点i的子节点为2×i+1 与2×i+2(根节点为0)。
我们首先建立一个长为n的数组,我们假设它上面有一个完全二叉搜索树,我们对其进行中序遍历,遍历过程中我们把取元素操作变为相应的位置按顺序放入序号。
其次我们将输入的序列存为数组,然后将其由小到大排序。
最后顺序遍历该数组,并输出数组中所存序号对应的已排序的输入序列的值。
代码如下
def build(i): #为了节省内存,结果与输入序列长度我都采用全局变量 left = 2*i + 1 #左子树的位置 if left < length: #超出length时儿子节点不存在。 build(left) #遍历左边 result[i]=nu.pop() #由小到大设置节点值 right = left + 1 if right < length: build(right) length = input() #读入长度 number = raw_input().split() #读入输入数据 nu = range(length-1,-1,-1) # 生成从上到下依次增大的栈 result = [0 for m in xrange(length)] # 初始化结果数组 build(0) #创建完全二叉树 number = [int[m] for m in number] number.sort() #排序输入数据 result = [str(number[m]) for m in result] print ' '.join(result)