二叉树学习(一):二叉树概念及存储结构

来源:互联网 发布:淘宝与京东哪个更可靠 编辑:程序博客网 时间:2024/05/17 11:04

1、树的定义与术语与存储结构

1.1树(Tree)的定义

树(Tree)是由n(>=0)个结点的有限集。n=0称为空树,在任意非空树中:
1、有且仅有一个根节点(Root),根节点没有前驱;
2、树中结点可以有一个或多个前驱。

1.2树(Tree)的术语

结点:
表示树中的元素,包括数据项以及若干指向其子树的分支;
结点的度:
结点所拥有的子树的个数称为该结点的度;
叶子结点:
度为0的结点称为叶子结点,无后继结点,或称为终端结点;
分支结点:
度不为0的结点称为分支结点。或称为非终端结点。一棵树的结点除了叶子结点外,其余都是分支结点;
结点的层数:
规定树的根节点的层数为1,其余结点的层数等于它的双亲结点的层数加1;
树的度:
树中所有结点的度的最大值称为该树的度;
树的深度(高度):
树中所有结点的的最大层数称为树的深度;
有序树和无序树:
如果一棵树中结点的各子树从左到右是有次序的,即若交换了某结点各子树的相对位置,则构成不同的树,称这棵树是有序树;反之,则称为无序树;
祖先、子孙:
在树中,如果有一条路径从结点M到N,那么M就成为N的祖先,N称为M的子孙;
路径、路径长度:
如果一棵树的一串结点n1,n2,n3…..nk中,若结点ni是n(i+1)的父结点(1<=i<=k),就把n1,n2,n3…..nk称为一条由n1至nk的路径。这条路径长度是k-1;
孩子、双亲、兄弟:
若在树中一个结点A的子树根节点是B,则称B为A的孩子(也称子节点),称A为B的双亲(也称父结点)。具有同一双亲的子结点称为兄弟。

1.3树的存储结构

双亲表示法:
除了根节点以外,所有结点必有双亲(父结点)。假设一组连续空间存储树的结点,同时在每个结点中,附设一个指示器指示双亲结点到链表中的位置。即,每个结点除了知道自己,还知道双亲结点在哪。其结点结构如下:
这里写图片描述
其中data是数据域,存储结点的数据信息。parent是指针域,存储该结点的双亲在数组中的下标。
孩子表示法:
树中每个结点可能有多颗子树,可以使用多重链表,即每个结点有多个指针域,其中每个指针指向同一颗子树的根节点,我们把这种方法叫做多重链表表示法。因为树的每个节点的度,即它的孩子个数是不同的,所以有两种设计方案来解决。

方案一:
指针域的个数就等于树的度,其结构如下图:
这里写图片描述

方案二:
每个结点指针域的个数等于该结点的度,专门取一个位置来存储结点指针域的个数,结构如下:
这里写图片描述
data为数据域,degree为度域,即存储该结点的孩子结点的个数,child1到child2为指针域,指向该结点的各个孩子的结点。

孩子兄弟表示法
任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。因此设置两个两个指针,分别指向该结点的第一个孩子和该结点的右兄弟。
这里写图片描述
data是数据域,firstchild为指针域,存储该结点的第一个孩子结点的存储地址,rightsib是指针域,存储该结点的右兄弟结点的存储地址。

2、二叉树

2.1、二叉树基本概念与性质

2.1.1、二叉树概念

二叉树是有序树,每个结点最多有两个子树,其中第一个子树被称为左子树,第二个子树被称为右子树。二叉树结点个数为0是,称为空树。

2.1.2、二叉树性质

(1) 在二叉树的第i层上最多有2i1 个结点 。(i>=1)
(2) 二叉树中如果深度为k,那么最多有2k1个结点。(k>=1)
(3) n0=n2+1 n0表示度数为0的结点个数, n2表示度数为2的结点个数
(4) 具有n个节点的完全二叉树的深度为[log2n]+1,[log2n]+1是向下取整。
(5) 若对含 n 个结点的完全二叉树,从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的结点:
(5).1 若 i=1,则该结点是二叉树的根,无双亲, 否则,编号为 [i/2](向下取整) 的结点为其双亲结点;
(5).2 若 2i>n,则该结点无左孩子, 否则,编号为 2i 的结点为其左孩子结点;
(5).3 若 2i+1>n,则该结点无右孩子结点, 否则,编号为2i+1 的结点为其右孩子结点。

2.2特殊二叉树

2.2.1满二叉树

这里写图片描述
定义:如果所有分支结点都存在左子和右子树,且所有叶子结点都在同一层。
特点:
(1)叶子只能出现在最下层;
(2)非叶子结点的度一定是2;
(3)在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。

2.2.2完全二叉树

这里写图片描述
定义:叶子结点只能出现在最下层或次下层,且最下层叶子结点集中在树的左边。
特点:
(1)叶子结点只能出现在最下两层;
(2)最下层叶子一定集中在左部连续位置;
(3)倒数第二层,若有叶子结点,一定集中在树的右边连续位子;
(4)如果结点度为1,则该结点只有左孩子,即不存在右子树;
(5)同样结点树的二叉树,完全二叉树的深度最小。

2.2 二叉树的存储结构

2.2.1 顺序存储结构

顺序存储结构就是用一组地址连续的存储单元以此自上而下、自左至右存储二叉树上的结点元素。这样的结点在存储位置上的前驱后继并不一定就是他们在逻辑上的邻接关系,要通过一些方法确定某结点在逻辑上的前驱结点和后继结点,这种存储才有意义。完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映结点之间的逻辑关系。
先看看完全二叉树的顺序存储:
这里写图片描述

将这个二叉树存入到数组中,相应的下标的对应同样的位置:
这里写图片描述
这即是完全二叉树的优越,但对于一般二叉树,把不存在的结点设为“^”,下图中4、6、8、9是不存在的结点
这里写图片描述
这里写图片描述
此种情况下,只有添加一些并不存在的空结点,使之成为一颗完全二叉树,再使用顺序存储,这种方法造成很大空间浪费,最坏的情况是,一棵深度为k的右单支树,需要分配2k1个存储单元。

2.2.2 二叉链表存储

二叉树每个结点最多两个孩子,所以设计一个数据域两个指针域,分别用来指出该结点左孩子和右孩子的存储地址,结点存储结构为:

这里写图片描述
其中data是数据域,lchild和rchild是指针域,分别存放左孩子和右孩子的指针,当左孩子或右孩子不存在时,相应的为空null
二叉链表存储的每个结点可描述为:

class Node<T>{    public Node<T> lChild; //左孩子    private T data;    //数据域    public Node<T> rChild;  // 右孩子    public Node(){ //构造函数,创建一个空结点        data = null;        lChild = null;        rChild = null;    }    public Node(T x){//重载构造,创建数据值为x的结点        data = x;        lChild = null;        rChild = null;          }}

结构示意图:
这里写图片描述

在Java中确定二叉树的根,代码如下:

class BinaryTree<T>{    public Node<T> root;    public BinaryTree(){   //创建一棵空二叉树        this.root = root;    }    public BinaryTree(T x){  //创建一棵以数据元素x为根结点的二叉树        this.root = new Node<T>(x);    }}

2.2.3三叉链表存储

每个结点有四个域组成
这里写图片描述
parent域指向该结点双亲结点,其余域同二叉链表存储。这种结构方便查找孩子结点,也方便查找双亲结点。但增加了空间开销。一般二叉链表是最常用的二叉树存储方式。

0 0