今天我们来聊聊二叉树。
(性质可以收集起来)
(1)在二叉树的第 i 层上至多有 2的(n-1)次方个结点
(2)深度为 k 的二叉树至多有 2的 k 次方-1 个结点
(3)具有 n 个结点的完全二叉树的深度为【n的对数】+1
二叉链表来储存每个结点。
(这个也是,写出自己的思考逻辑)
前序遍历:
先访问“根结点”,然后前序遍历左子树,再前序遍历右子树。
中序遍历:(207)
遍历根节点的左子树,然后是访问“根结点”,最后遍历右子树。
后序遍历:(最先打印的是“根结点”的右子树)
遍历左右子树,最后是访问“根结点”。
(1)知道前序遍历和中序遍历,可以唯一确定一颗二叉树。
(2)知道后序遍历和中序遍历,可以唯一确定一颗二叉树。
题目:面试题6:重建二叉树(剑指offer)
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路
前序遍历序列中,第一个数字总是树的根结点的值。在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边。剩下的我们可以递归来实现,具体如图:
python 实现:
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
if len(pre) == 0:
return None
if len(pre) == 1:
return TreeNode(pre[0])
else:
flag = TreeNode(pre[0])
flag.left = self.reConstructBinaryTree(pre[1:tin.index(pre[0])+1],tin[:tin.index(pre[0])])
flag.right = self.reConstructBinaryTree(pre[tin.index(pre[0])+1:],tin[tin.index(pre[0])+1:] )
return flag
(大话数据结构 209页)
已知一颗二叉树的前序遍历为 ABCDEF,中序遍历为 CBAEDF,请问这个数的后续遍历结果是什么?
(1)A 是根结点
(2)BC 是左节点,DEF 是右节点
(3)看前序遍历可以知道,B 是左孩子,再看中序遍历为 CBA ,可以知道 C 是 B 的左孩子。
(4)从前序遍历 DEF 可以看得出来 D 是 A 的右节点,并且 E,F 可能是 D 的孩子或者是孙子,而中序遍历 EDF 可以看出 E 是 D 的左孩子,而 F 是 D 的右孩子。
二叉链表:
每个结点最多有两个节点,所以为他设计一个数据域和两个指针域。
二叉树的遍历:
是指从根节点出发,按照某种次序访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。
指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树就称为线索二叉树。
对二叉树以某种次序遍历使其变为线索二叉树的过程称作是线索化。
218
如果所用的二叉树需要经常遍历或查找结点时需要遍历序列中的前驱和后继,那么采用线索二叉链表的存储结构就是非常不错的选择。
红黑树(红黑二叉查找树):
哈夫曼树
带全路径长度 WPL 最小的二叉树称做哈夫曼树。
什么是哈夫曼树?
他们的带权路径长度分别为:
图a:WPL = 5*2 + 7*2 + 2*2 + 13*2 = 54
图b:WPL = 5*3 + 2*3 + 7*2 + 13*1 = 48
所以,图b 的带权路径长度较小,我们可以证明图b就是哈夫曼树。
按下面步骤构建:
1,将所有左,右子树都为空的作为根节点。
2,在森林中选出两棵根节点的权值最小的树作为一棵新树的左,右子树,且置新树的附加根节点的权值为其左,右子树上根节点的权值之和。注意,左子树的权值应小于右子树的权值。
3,从森林中删除这两棵树,同时把新树(如下图(b)中 “2” 跟 “5” 合并的 “7”)加入到森林中。
4,重复2,3步骤,直到森林中只有一棵树为止,此树便是哈夫曼树。
参考链接:
(1)http://www.cnblogs.com/mcgrady/p/3329825.html