树定义
定义
- 树是一种常用的非线性结构,其递归定义如下:
树是n(n>=0)个结点的有限集合。若n=0,则称为空树,否则,有且仅有一个特定的结点被称为根,当n>1时,其余结点被分为m个互不相交的子集,每个子集又是一棵树。 - 常见树结构
组织机构关系
血缘关系
树的组织
文件系统
基本概念
- 结点
数据元素的内容及其指向其子树根的分支统称为结点。 - 结点的度
一个结点所拥有的分支数。 - 树的度
所有结点的度的最大值。 - 终端结点(叶子)
度为0的结点。 - 非终端结点
度不为0的结点。 - 结点的层次
- 树的深度
- 有序树、无序树
如果树中每棵子树从左向右的排列拥有一定的顺序,不得互换,则称为有序树,否则为无序树。
二叉树
二叉树定义
- 二叉树是另一种树形结构
- 二叉树与树形结构的区别
每个节点最多有两颗子树
子树有左右之分 - 二叉树的递归定义
二叉树是n(n>=0)个结点的有限集合。当n=0时,称为空二叉树;当n》0时,有且仅有一个结点为二叉树的根,其余结点被分两个不相交的子集,一个为左子集一个为右子集。
- 满二叉树
- 完全二叉树
存储结构
- 用一组连续的存储单元按照完全二叉树的每个结点编号的顺序存放结点内容。
- 二叉树的链式存储结构
顺序存储的不足
① 对于非完全二叉树,进行顺序存储需要将空缺的位置用特定的符号填补,如果空缺结点较多,则导致空间利用率下降;
② 仅适用于完全二叉树。
链式存储
二叉链表
三叉链表
- 链式存储结构描述
//二叉链表存储
typedef struct bbtnode{
ElemType data;
struct bbtnode *lchild,*rchild;
}bbtnode;
//三叉链表存储
typedef struct tbtnode{
ElemType data;
struct tbtnode *parent;
struct tbtnode *lchild,*rchild;
}tbtnode;
二叉树的遍历
- 二叉树是一种非线性的数据结构,在对它进行操作时,需要逐一对每个数据元素实施操作。
- 所谓遍历二叉树就是按照某种顺序访问二叉树中的每一个结点一次且仅一次,的过程。这里的访问可以是输出、比较、更新、查看元素内容等等操作。
① 遍历操作实际上是将非线性结构线性化的过程;
② 遍历操作是一个递归的过程。 - 二叉树的遍历方式分为两大类
① 按照根、左子树、右子树三部分进行访问:先序遍历;中序遍历;后续遍历;
//先序遍历
void preorder(bbtnode *BT){
if(BT){
visit(BT);
preorder(BT->lchild);
preorder(BT->rchild);
}
}
//中序遍历
void inorder(bbtnode *BT){
if(BT){
inorder(BT->lchild);
visit(BT);
inorder(BT->rchild);
}
}
//后续遍历
void postorder(bbtnode *BT){
if(BT){
postorder(BT->lchild);
postorder(BT->rchild);
visit(BT);
}
}
② 按照层次进行访问
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
//二维数组ret用存放结果
vector <vector <int>> ret;
//判断是否为空树
if (!root) return ret;
//定义一个队列存放Treenode的指针
queue <TreeNode*> q;
//将根元素压入队列
q.push(root);
while (!q.empty()) {
//当前层数
int currentLevelSize = q.size();
//先放入一个动态数组
ret.push_back(vector <int> ());
//进入循环
for (int i = 1; i <= currentLevelSize; ++i) {
//auto类型得到队列中指针元素
auto node = q.front();
//出队
q.pop();
//ret容器存入当前结果
//back()得到数组的最后一个单元的引用
ret.back().push_back(node->val);
//队列中加入上一个结点的左右孩子
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}
return ret;
}
};
- 统计叶子结点个数
//统计叶子结点数
int n2=0;
void countLeafNode(BTNode *p)
{
if(p!=NULL)
{
if(p->lchild==NULL&&p->rchild==NULL)//判断是否叶子结点
++n2;
countLeafNode(p->lchild);
countLeafNode(p->rchild);
}
}
- 计算二叉树的高度
int height(bbtnode* BT){
if(BT==NULL){
return 0;
}else{
hl=height(BT->lchild);
hr=height(BT->rchild);
return max{hl,hr}+1
}
}
- 交换二叉树左右子树
void exchange(bbtnode* BT){
if(BT){
temp=BT->lchild;
BT->lchild=BT->rchild;
BT->rchild=temp;
exchange(BT->lchild);
exchange(BT->rchild);
}
}