文章目录
1. 树的概念以及相关概念
树是一种非线性数据结构,由(n>0)个节点组成的一个具有层次关系的集合。
根节点:没有父节点的节点
叶子结点:没有子节点的节点,即度为0的节点
节点的度:一个节点含有的子节点的个数称为该节点的度
树的度:一个树中最大的节点的度为该树的度
相关公式:
节点数=分支数+1
节点数=度为0的节点+度为1的节点+度为2的节点
分支数=度为1的节点+2*度为2的节点
2. 树的存储方式以及其区别
树的存储方式有:双亲表示法,孩子表示法,双亲孩子表示法。
双亲表示法:
通常用一个二维数组,在存储节点时将对应节点的父节点也储存进来
特点:找父节点容易,找子节点难。
孩子表示法:
每个节点都储存在二维数组的第一列里,第二列指向子节点的链表,多个子节点之间以链表的形式连接,最后一个子节点指向空。
特点:找子节点容易,找父节点难。
双亲孩子表示法:
将双亲表示法与孩子表示法结合起来,既储存父节点下标又指向子节点链表。
特点:找子节点与父节点都比较方便,但是复杂度有所提升。
3. 树的应用场景
储存数据、目录
4. 二叉树
1>二叉树的相关概念以及性质特点
一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
(1)每个结点最多有两棵子树,即二叉树不存在度大于2的结点。
(2)二叉树的子树有左右之分,其子树的次序不能颠倒。
2>特殊的二叉树:满二叉树和完全二叉数
(1)满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。
(2)完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
3>最优二叉树(哈夫曼树)
给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
相关名词:
(1)路径和路径长度
在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中结点的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
(2)结点的权及带权路径长度
若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
(3)树的带权路径长度
树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。
6. 二叉树的静态存储与链式存储
二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。
(1)顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。(2)二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。
前序遍历:根左右
中序遍历:左根右
后序遍历:左右根
7. 实现链式数据结构的以下基本操作:
//树的孩子兄弟表示法中树的一个节点
typedef char BTDataType;
typedef struct BTNode
{
struct BTNode* _pLeft; //第一个孩子节点
struct BTNode* _pRight; //指向其下一个兄弟节点
BTDataType _data; //节点中的数据域
}BTNode;
//创建二叉树
//将大小为size的顺序结构的二叉树转换为链式储存
BTNode* CreateBinTree(BTDataType* array, int size);
// 拷贝二叉树
BTNode* CopyBinTree(BTNode* pRoot);
// 销毁二叉树
void DestroyBinTree(BTNode** pRoot);
// 二叉树的三种遍历方式
//前序遍历
void PreOrder(BTNode* pRoot);
void PreOrderNor(BTNode* pRoot){
};
void InOrder(BTNode* pRoot);
void InOrderNor(BTNode* pRoot){
};
void PostOrder(BTNode* pRoot);
void PostOrderNor(BTNode* pRoot);
void LevelOrder(BTNode* pRoot);
// 获取二叉树中节点的个数
int GetNodeCount(BTNode* pRoot);
// 求二叉树的高度
int Height(BTNode* pRoot);
// 检测二叉树是否平衡O(N^2)
int IsBalanceTree(BTNode* pRoot);
// 检测二叉树是否平衡O(N)
int IsBalanceTree_P(BTNode* pRoot, int* height);
// 获取二叉数中叶子节点的个数
int GetLeafNodeCount(BTNode* pRoot);
// 获取二叉树第K层节点的个数
int GetKLevelNodeCount(BTNode* pRoot, int K);
// 获取二叉树中某个节点的双亲节点
BTNode* GetNodeParent(BTNode* pRoot, BTNode* pNode);
// 求二叉树的镜像
void Mirror(BTNode* pRoot);