您的位置:首页 > 理论基础 > 数据结构算法

【数据结构】二叉树

2016-05-03 11:34 423 查看
特点

1、二叉树的每个结点至多只有二棵子树(不存在度大于2的结点);

2、在非空二叉树的k层上,至多有2^(k-1)个节点(k>0);

3、高度为k的二叉树中,最多有2^k-1个节点(k>0);

4、对于任何一棵非空的二叉树,如果叶节点个数为n0,度数为2的节点个数为n2,则有: n0 = n2 + 1。

注:通过网上学习得知,国外的教材对于数的高度和深度通常都是从0开始,而国内比较偏向从1开始,所以要注意这个概念上的定义,例如我上文定义的(K>1)。


(从二叉树特点判断,以上二图中的树都为二叉树)

满二叉树

满二叉树是二叉树的一种,除了具备二叉树的特征,还需要满足的条件是:若一棵深度为k,且有2^k-1个节点称之为满二叉树。就是一个挂满节点的二叉树,叫满二叉树,如下图:



以上二叉树为满二叉树,其中深度K=3,总节点数为2^3-1 = 7。

完全二叉树

除基本二叉树特点外,还需要满足的条件是除最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干结点。换句话说,叶子结点只可能在最大的两层上出现,对任意结点,若其右分支下的子孙最大层次为L,则其左分支下的子孙的最大层次必为L 或 L+1;



(从完全二叉树特点判断,以上二图中的树都为完全二叉树)

由于二叉树的特点可以得出:

1、满二叉树是一颗挂满节点的数,所以满二叉树一定是完全二叉树,而完全二叉树不一定是满二叉树。

2、根据公式进行推导,假设n0是度为0的结点总数(即叶子结点数),n1是度为1的结点总数,n2是度为2的结点总数,由二叉树的性质可知:n0=n2+1,则n= n0+n1+n2(其中n为完全二叉树的结点总数),由上述公式把n2消去得:n= 2n0+n1-1,由于完全二叉树中度为1的结点数只有0或1两种可能,由此得到n0=(n+1)/2或n0=n/2。总结起来,就是 n0=[n/2],其中[]表示上取整。如上图左边的完全二叉树,n = 6;得知n0 = [6/2] = 3;右边的同理,n0 = [5/2] = 3。

二叉树的实现练习





对树的基本运算操作有获取树的高度、获取树的节点数、获取节点的双亲节点和对树遍历,其中,遍历二叉树 是指以一定的次序访问二叉树中的每个结点,遍历二叉树的过程实质是把二叉树的结点进行线性排列的过程,那么遍历的结果得到一个线性序列。从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:

(1)访问结点本身(N),

(2)遍历该结点的左子树(L),

(3)遍历该结点的右子树(R)。

以上三种操作有六种执行次序:NLR、LNR、LRN、NRL、RNL、RLN。因为前三种次序与后三种次序对称,故只需要讨论先左后右的前三种次序并加以解析。NLR、LNR和LRN分别又称为先根遍历(前序遍历DLR)、中根遍历(中序遍历LDR)和后根遍历(后续遍历LRD)。

前序遍历:ABDECF

前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。

中序遍历:DBEAFC

中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。

后序遍历:DEBFCA

后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。

Java实现例子

public class BinaryTree {

private TreeNode root=null;

/**
* 创建一棵二叉树
*           A
*     B          C
*  D     E            F
*/
public void createBinTree(){
TreeNode root_A = new TreeNode("A");
TreeNode node_B = new TreeNode("B");
TreeNode node_C = new TreeNode("C");
TreeNode node_D = new TreeNode("D");
TreeNode node_E = new TreeNode("E");
TreeNode node_F = new TreeNode("F");
root = root_A;
root.leftChild=node_B;
root.rightChild=node_C;
root.leftChild.leftChild=node_D;
root.leftChild.rightChild=node_E;
root.rightChild.rightChild=node_F;
}

/**
* 获取树的高度
* @param subTree
* @return
*/
private int height(TreeNode subTree){
if(subTree==null)
return 0;//递归结束:空树高度为0
else{
int i=height(subTree.leftChild);
int j=height(subTree.rightChild);
return (i<j)?(j+1):(i+1);
}
}

/**
* 获取数的节点数
* @param subTree
* @return
*/
private int size(TreeNode subTree){
if(subTree==null){
return 0;
}else{
return 1+size(subTree.leftChild)+size(subTree.rightChild);
}
}

/**
* 获取节点的双亲节点
* @param element
* @return
*/
public TreeNode parent(TreeNode element){
return (root==null|| root==element)?null:parent(root, element);
}

public TreeNode parent(TreeNode subTree,TreeNode element){
if(subTree==null)
return null;
if(subTree.leftChild==element||subTree.rightChild==element)
//返回父结点地址
return subTree;
TreeNode p;
//现在左子树中找,如果左子树中没有找到,才到右子树去找
if((p=parent(subTree.leftChild, element))!=null)
//递归在左子树中搜索
return p;
else
//递归在右子树中搜索
return parent(subTree.rightChild, element);
}

//前序遍历
public void preOrder(TreeNode subTree){
if(subTree!=null){
visted(subTree);
preOrder(subTree.leftChild);
preOrder(subTree.rightChild);
}
}

//中序遍历
public void inOrder(TreeNode subTree){
if(subTree!=null){
inOrder(subTree.leftChild);
visted(subTree);
inOrder(subTree.rightChild);
}
}

//后续遍历
public void postOrder(TreeNode subTree) {
if (subTree != null) {
postOrder(subTree.leftChild);
postOrder(subTree.rightChild);
visted(subTree);
}
}

public void visted(TreeNode subTree){
System.out.print(subTree.data);
}

/**
* 二叉树的节点数据结构
*/
private class  TreeNode{

private String data=null;
private TreeNode leftChild=null;
private TreeNode rightChild=null;

public TreeNode(){}

public TreeNode(String data){
this.data=data;
}
}

public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.createBinTree();
System.out.println("tree height:"+bt.height(bt.root));
bt.preOrder(bt.root);
System.out.println("---前序遍历");
bt.inOrder(bt.root);
System.out.println("---中序遍历");
bt.postOrder(bt.root);
System.out.println("---后序遍历");
}
}


执行结果:

tree height:3
ABDECF---前序遍历
DBEAFC---中序遍历
DEBFCA---后序遍历
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: