【数据结构】二叉树知识点总结|期末复习

基础知识

基本概念

包含n个数据元素的有限集合

  • n=0:空树
  • n>0:有且仅有一个没有前驱,只有后继的结点,被称为根(root)

【树本质就是一个族谱一样的东西,这里拿灰太狼家举个例子】

结点

树里的每一个元素称为一个结点

【族谱里的人,比如灰太狼、夜太郎……】

根节点

没有前驱的,第一层的结点

【相当于武大狼在狼群,或者软绵绵在羊群的地位】

终端节点/叶子节点

度为0的结点

【未婚未孕的人,比如小灰灰】

非终端节点/分支节点/内部节点

度不为0的结点

【已婚已孕的人,比如灰太狼】

孩子/双亲

注意的是双亲虽然叫双亲,但是只是一个结点,其实叫父亲更贴切

你只有一个生父,所以双亲只有一个;

但你爸可以有很多孩子。

【小灰灰的(双亲)是灰太狼;灰太狼的(孩子)是小灰灰和他的弟弟妹妹】

兄弟

同一个爹

堂兄弟

双亲在同一层

【爸妈是同一辈,比如灰太狼和夜太郎】

!!!互为堂兄弟的结点,双亲不一定是兄弟,也有可能是堂兄弟

【比如小灰灰和夜太郎的孩子,也是堂兄弟】

祖先

从结点x往上到根节点途经的所有结点都是他的祖先

【你爸、你爷、你太爷都是你的祖先,但你二大爷不是】

子孙

以结点x为根的子树的所有结点都是他的子孙

结点的度

官方的回答是:一个结点的子树的数目

实际就是,他的后继/或者说分支的个数。

显然的,二叉树的 结点的度 只有0、1、2三种情况。

【结点的度就是孩子的个数,比如灰太狼的度就是5】

树的度

节点中最大的度为树的度。

!!!!max{ 结点的度 }

结点的层次

根节点为第一层

【辈分:灰太狼是第十八层,武大狼是第一层】

树的深度/高度

结点的最大层次。

【树的深度就是现在传到第几代,比如灰太狼是第十八代,那现在他们家族谱的深度就是十九(小灰灰这一层)】

有序树/无序树
  • 有序:有次序,同一层从左到右
  • 无序:同一层没有次序
森林

【两个没有联系的族谱】

二叉树

定义
二叉树定义

度为2的有序树

  • 结点的度可以为0,1,2
  • 有序!!!分左右结点/左右孩子
满二叉树定义

高度为 h 的树,有(2^{h}-1)个结点

  • 结点的度为0、2
完全二叉树定义

从上到下、从左到右依次增加结点

  • 满二叉树 是 完全二叉树
性质
二叉树性质
  • 分支数 等于 结点数-1 
  • 已知高度h, 结点个数:

                                        min:  h

                                        max: (2^{h}-1)【满二叉树】

  • 已知结点数n,高度:

                                        min:  log_{2}(n+1)【不一定是完全二叉树】

                                        max: n

完全二叉树性质

n 个节点,从上到下,从左到右,用  i=0,1,2... n-1 表示每个节点:

  • 高度:  log_{2}(n+1)
  • i=0:根节点,无双亲
  • i>0:双亲为  \left \lceil \frac{i}{2}\right \rceil-1

【!!!注意:从1开始表示的话:\left \lfloor \frac{i}{2} \right \rfloor

  • 2*i+2<=n时,左孩子:2i+1; 右孩子:2i+2
  • i为范围内奇数时,为左孩子;i为范围内偶数,为右孩子

【!!!注意:从1开始表示的话:相反(因为相当于整体-1)】

存储结构

顺序存储

定义:

采用一组连续存储空间(数组)从上到下,从左到右依次存储元素。

【满足上述完全二叉树的性质,但是把空的结点存为空】

优点:

  1. 可以方便计算出双亲和左右孩子的位置,快速访问
  2. 适用于存储完全二叉树

缺点:

  1. 一般二叉树,空间利用率低

【!!注意:使用自定义标记表示这个地方为空结点】

链式存储

链表表示法

二叉链表

leftChild

Data

rightChild

依据上图,构造节点类 

//二叉链表的结点类模板

template <class T>
struct bTreeNode
{
//数据成员
    T data;                      //数据域
    bTreeNode<T>* leftChild;     //左孩子
    bTreeNode<T>* rightChild;    //右孩子

//函数成员
    bTreeNode();    //无参的构造函数
    bTreeNode(const T &d, bTreeNode<T>* LChild=NULL,  bTreeNode<T>* RChild=NULL);
                    //已知元素、左右孩子
};

//无参的构造函数
template <class T>
bTreeNode<T>:: bTreeNode()    //空结点
{
    leftChild=NULL;
    rightChild=NULL;
}

//含参的
template <class T>
bTreeNode<T>:: bTreeNode(const T &d, bTreeNode<T>* LChild=NULL,  bTreeNode<T>* RChild=NULL)
{
    data=d;
    leftChild=LChild;
    rightChild=RChild;
}    

链表类模板

//最基本的二叉链表的链表类模板

template <class T>
class bTree
{
protected:
    bTreeNode<T>* root;    //根节点    //相当于普通链表类里的头结点
    
    void Destroy(bTreeNode<T> *&r);    //删除二叉树

public:
    bTree();              //无参的构造函数
    bTree(const &T r);    //已知根节点元素的构造函数
    virtual ~bTree();     //析构
};

具体函数

template <class T>
bTree<T>::bTree()              //无参的构造函数
{
    root = NULL;
}

template <class T>
bTree<T>::bTree(const &T rData)   //已知根节点元素的构造函数
{
    root->data = rData;
}


template <class T>
virtual bTree<T>:: ~bTree()    //析构
{
    Destroy(root);
}  

template <class T>
void bTree<T>::Destroy(bTreeNode<T> *&r)    // 操作结果:删除以r的二叉树
{
	if(r != NULL)	{	// r非空,实施删除
		Destroy(r->leftChild);		// 删除左子树
		Destroy(r->rightChild);		// 删除右子树
		delete r;					// 删除根结点
		r = NULL;
	}
} 

三叉链表

leftChild

Data

Partent

rightChild

 三叉链表的结点类模板

//二叉链表的结点类模板

template <class T>
struct bTreeNode
{
//数据成员
    T data;                      //数据域
    bTreeNode<T>* leftChild;     //左孩子
    bTreeNode<T>* rightChild;    //右孩子
    bTreeNode<T>* parent;       //双亲结点

//函数成员
    bTreeNode();    //无参的构造函数
    bTreeNode(const T &d, bTreeNode<T>* Parent=NULL, bTreeNode<T>* LChild=NULL,  bTreeNode<T>* RChild=NULL);
                    //已知元素、双亲、左右孩子
};

//无参的构造函数
template <class T>
bTreeNode<T>:: bTreeNode()    //空结点
{
    leftChild=NULL;
    rightChild=NULL;
}

//含参的
template <class T>
bTreeNode<T>:: bTreeNode(const T &d, bTreeNode<T>* Parent=NULL, bTreeNode<T>* LChild=NULL,  bTreeNode<T>* RChild=NULL)
{
    data=d;
    leftChild=LChild;
    rightChild=RChild;
    parent = Parent;
}    

线索二叉树
定义

在某种遍历过后,二叉树的层序结构可以得到一个线性结构

【先看遍历】

leftChild

leftTag

Data

rightTag

rightChild

  • left/rightTag = 0
    • leftChild:左孩子
    • rightChild:右孩子
  • left/rightTag = 1
    • leftChild:前驱
    • rightChild:后继

【有孩子就为孩子,没孩子就为前驱/后继】

【!!!前驱/后继 不一定是 双亲】

遍历二叉树

先序遍历

中序遍历

后序遍历

层序遍历

应用

哈夫曼树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值