Complete Binary Search Tree(mooc)

04-树6 Complete Binary Search Tree (30分)

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

The left subtree of a node contains only nodes with keys less than the node's key.

The right subtree of a node contains only nodes with keys greater than or equal to the node's key.

Both the left and right subtrees must also be binary search trees.

A Complete Binary Tree (CBT) is a tree that is completely filled, with the possible exception of the bottom level, which is filled from left to right.

Now given a sequence of distinct non-negative integer keys, a unique BST can be constructed if it is required that the tree must also be a CBT. You are supposed to output the level order traversal sequence of this BST.
Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N<1000. Then N distinct non-negative integer keys are given in the next line. All the numbers in a line are separated by a space and are no greater than 2000.
Output Specification:

For each test case, print in one line the level order traversal sequence of the corresponding complete binary search tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.
Sample Input:

10
1 2 3 4 5 6 7 8 9 0

Sample Output:

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)

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值