二叉树
二叉树是一种典型的树形结构
在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
来源:百度百科
1.定义
二叉树的特点是每个结点至多有两棵子树,即二叉树的度
是2,并且二叉树的子树有左右之分,不可任意颠倒次序
1.1空二叉树
结点个数为0的二叉树
1.2满二叉树
一棵深度为k,且有2^k - 1个结点的二叉树,称为满二叉树。
特点是每一层上的结点数都是最大结点数。
1.3完全二叉树
在一棵二叉树中,除最后一层外,若其余层都是满的,并且或者最后一层是满的,或者是在右边缺少连续若干结点,则此二叉树为完全二叉树。
a:满二叉树/完全二叉树
b:完全二叉树
c&d:非完全二叉树
1.4二叉树形态
- 空二叉树
- 只有根结点
- 根结点只有左子树
- 根结点只有右子树
- 根结点既有左子树又有右子树
1.5结点实现
由上面的基本形态易得,每个二叉树必然包含3部分
- 数据部分
- 左子树指针
- 右子树指针
//二叉树结点定义
template<typename DataType>class Bitnode
{
public:
//构建空结点
Bitnode()
{
data = NULL;
lchild = NULL;
rchild = NULL;
}
//构建指定数据域的结点
Bitnode(DataType newData)
{
data = newData;
lchild = NULL;
rchild = NULL;
}
private:
DataType data;//数据域
Bitnode *lchild;//左子树指针
Bitnode *rchild;//右子树指针
};
2.二叉树的性质
2.1二叉树区别于树
- 树中结点的最大度数没有限制;二叉树的结点的最大度数为2
- 树的结点无左右之分,表现为无序;二叉树的结点有左右之分 是有序的
2.2特殊性质
- 具有n个结点的非空二叉树有且仅有n-1个分支
- 非空二叉树的第i层最多有2^(i-1)个结点
- 深度为k的二叉树最多有2^k - 1个结点
- 在任意非空二叉树中,若叶子结点的数目为n_0,度为2的结点数目为n_2,则n_0=n_2+1成立
- 具有n(n>0)个结点的完全二叉树的深度为k=n/2(向下取整)
2.3完全二叉树结点性质
结点i的定义:
若对具有n个结点的完全二叉树的所有结点按层从上到下,每层从左到右的次序依次对结点从1开始编号 那么结点i有如下性质
- i=1时,i为二叉树的根结点
- i>1时,i的父亲结点为i/2(向下取整)
- 若2i<=n,则i的左儿子的编号为2i
- 若2i>n,则i没有左儿子
- 若2i+1<=n,则i的右儿子的编号为2i+1
- 若2i+1>n,则i没有右儿子
3.二叉树的存储结构
3.1顺序存储结构
使用一块连续的存储空间存储二叉树
优点:结构紧凑,没有额外的指针空间,随机存取能力强
缺点:插入和删除元素时操作费时,所需空间大时,容易崩溃,不利于对碎片空间的利用
由完全二叉树结点性质可得出结点的序号关系:
编号为i的结点的左儿子的编号为2i(如果存在左结点的话)
编号为i的结点的右儿子的编号为2i+1(如果存在右结点的话)
而非完全二叉树也可以使用上面的规则编号,就是会有许多编号无人认领,造成浪费
//二叉树线性表示
template <typename DataType>
class SeqBt
{
private:
int maxNode;
DataType *data;
public:
SeqBt(int nodes)
{
if(nodes>0)
{
maxNode = nodes;
data = new DataType[maxNode];
}
}
~SeqBt()
{
delete[] data;
}
};
3.1链式存储结构
二叉树是一种非线性的结构
使用链式结构能够很直观地表示二叉树的逻辑结构
并且即使二叉树是非二叉树的时候 仍旧能够很好的表示,不会像顺序结构产生空结点
优点:能够很好的利用内存中的碎片空间,提高内存空间的利用效率
缺点:不能随机存取某个结点,需要进行遍历,耗时
//二叉树链式表示
template <typename DataType>class Bintree
{
private:
Bitnode<DataType> *root;//设置根结点
public:
Bintree()
{
root = new Bitnode < DataType > ();//初始化根结点
}
};