目录
树的介绍
二叉树定义
二叉树图解
特殊的二叉树
完全二叉树:
满二叉树:
二叉搜索树:
二叉平衡树(AVL):
B树,B+树:
红黑树:
二叉树的性质
(1):一颗非空二叉树的第n层最多有2^(n-1)个节点
(2):若一颗非空二叉树的深度为h,那么它最多能有2^h-1个节点
(3):具有N个节点的二叉树,它的深度h=ceil(㏒₂(N+1))ceil表示向上取整,例如ceil(2.23)=ceil(2.64)=ceil(3)=3
★(4):一颗二叉树,2度节点和叶子节点(度为0)满足以下关系:D₀=D₂+1 也就是说叶子节点个数始终等于二度节点个数加一
★(5):一颗二叉树,若他的节点个数是2n个,那么他的叶子节点个数为n个
二叉树的基本代码实现
二叉数的定义
二叉树通常采用孩子表示法,因此定义的代码为:
//定义二叉树
typedef struct BTNode {
char data;//数据域
BTNode* left;//指向左孩子节点
BTNode* right;//指向右孩子节点
}BinaryTree;
/*该结构体有两个名字
分别翻译为节点(BTNode),二叉树(BinaryTree)加以区分
*/
二叉树的输入(创建)
由于二叉树是一对多结构,我们无法得知某某数据,它具体是谁的孩子节点,因此使得它不能像链表这样循环输入,而只能递归回溯输入。
所以涉及到回溯算法
★★★二叉树包含大量的回溯算法
回溯算法初步介绍
二叉树创建代码:
//创建二叉树
void BTCreate(BinaryTree* &root) {
BTNode *q; //创建新节点
q=new BTNode;//初始化节点,相当于malloc函数
cin>>q->data;//输入数据
if(q->data=='#') {//判断是否为'#"
root=q=NULL; //若是,则设置虚拟节点q,并接到二叉树上
return; //返回上一个节点
}
root=q; //若否,则将节点q接在二叉数上
BTCreate(root->left); //进入左孩子
BTCreate(root->right); //进入右孩子
return; //返回上一个节点
}
二叉树创建图解
以上就是二叉树:ABC##D###的创建过程。
主要还是回溯算法,当创建了空节点的时候,就回溯返回上一个节点,不再递归分治。
二叉树的遍历
二叉树的深度优先遍历
前序遍历,又叫先根遍历。遍历顺序:根 - > 左孩子 - >右孩子。
//前序遍历
void BTProOrder(BinaryTree* &root) {
if(root==NULL) return;
cout<<root->data<<" ";
BTProOrder(root->left);
BTProOrder(root->right);
}
中序遍历,又叫中根遍历。遍历顺序:左孩子 -> 根 -> 右孩子
//中序遍历
void BTInOrder(BinaryTree* &root) {
if(root==NULL) return;
BTInOrder(root->left);
cout<<root->data<<" ";
BTPostOrder(root->right);
}
后序遍历,又叫后根遍历。遍历顺序:左孩子 -> 右孩子 -> 根
//后序遍历
void BTPostOrder(BinaryTree* &root) {
if(root==NULL) return;
BTPostOrder(root->left);
BTPostOrder(root->right);
cout<<root->data<<" ";
}
二叉树的广度优先遍历
层序遍历。顾名思义,就是按照树的层次,从第1层到第n层,从上到下,从左到右进行遍历输出。
像这样,就是层序遍历。
//层序遍历
void BTLevelOrder(BinaryTree* &root) {
queue<BinaryTree*>Q;
Q.push(root);
BTNode *q;
while(!Q.empty()) {
cout<<Q.front()->data;
q=Q.front();
Q.pop();
if(q->left!=NULL) Q.push(q->left);
if(q->right!=NULL) Q.push(q->right);
}
}
二叉树的基本功能函数的实现
返回宽度和深度
深度
int Height(BinaryTree* &root) {
if(root==NULL) return 0;
else return max(Height(root->left),Height(root->right))+1;//左子树或者右子树的最大值
}//max(a,b):返回a,b的最大值
宽度
int a[10005];//数组a表示储存第key层有几个节点
//key表示第几层,刚开始key为1,也就是第一层
//ans表示最终答案
void Wide(BinaryTree* &root,int key,int &ans) {
if(root==NULL) return;
else {
a[key]++;
ans=max(ans,a[key]);
Wide(root->left,key+1,ans);
Wide(root->right,key+1,ans);
}
}
返回节点个数
返回二度节点
int node_two(BinaryTree* &root) {
if(root==NULL) return 0;
//同时搜索左右孩子节点
//当左右孩子节点都不为空,说明是2度节点,值加一
if(root->left!=NULL&&root->right!=NULL) return node_two(root->left)+node_two(root->right)+1;
//否则直接搜索
else return node_two(root->left)+node_two(root->right);
}
返回一度节点
int node_one(BinaryTree* &root) {
if(root==NULL) return 0;
//同时搜素左右孩子节点
//当左右孩子节点有一个不为空,一个为空,说明是1度节点,值加一
if(root->left!=NULL&&root->right==NULL || root->right!=NULL&&root->left==NULL) return node_one(root->left)+node_one(root->right)+1;
//否则直接搜索
else return node_one(root->left)+node_one(root->right);
}
返回叶子节点(0度)
int node_zero(BinaryTree* &root) {
if(root==NULL) return 0;
//同时搜素左右孩子节点
//当左右孩子节点都为空,说明是0度节点,返回1
if(root->left==NULL && root->right==NULL) return 1;
//否则直接搜索
else return node_zero(root->left)+node_zero(root->right);
}
返回空节点(NULL)
int node_NULL(BinaryTree* &root) {
//当该节点为空,返回1
if(root=NULL) return 1;
//否则搜索左右孩子
else return node_NULL(root->left)+node_NULL(root->right);
}
二叉树基本特点函数的实现
翻转二叉树
翻转二叉树可以先镜面先序遍历(根->右孩子->左孩子),并储存。然后再依次先序创建之前储存的镜面先序遍历。
//创建翻转二叉树
char node[10005];
int sum2=0;
void create(BinaryTree* &root) {
BTNode *q;
q=new BTNode;
q->data=node[sum2++];
if(q->data=='#') {
root=q=NULL;
return;
}
root=q;
create(root->left);
create(root->right);
}
//镜面先序遍历
int sum1=0;
void sy_BTProOrder(BinaryTree* &root) {
if(root==NULL) {
node[sum1++]='#';
return;
}
node[sum1++]=root->data;
sy_BTProOrder(root->right);
sy_BTProOrder(root->left);
}
二叉树性质的判断
完全二叉树
判断是否为完全二叉树,根据定义,和宽度优先遍历(层序遍历)有点类似
bool isCompleteTree(BinaryTree* &root) {
queue<BinaryTree*>Q;
Q.push(root);
BTNode *q;
while(!Q.empty()) {
if(Q.front()==NULL) break;
q=Q.front();
Q.pop();
Q.push(q->left);
Q.push(q->right);
}
while(!Q.empty()) {
if(Q.front()!=NULL) return false;
Q.pop();
}
return true;
}
平衡二叉树
根据定义,判断左右子树深度的绝对值之差,若不大于1,并且左右子树也为平衡二叉树,则该树为平衡二叉树。
//求二叉树深度
int depth(BinaryTree* &root) {
if(root==NULL) return 0;
else return max(depth(root->left),depth(root->right))+1;
}
//判断是否为平衡二叉树
bool isBalanced(BinaryTree* &root) {
if(root==NULL) return true;
int leftDepth=depth(root->left);
int rightDepth=depth(root->right);
if(abs(leftDepth-rightDepth)>1) return false;
//判断左右子树是否也为平衡二叉树
return isBalanced(root->left) && isBalanced(root->right);
}
对称二叉树
就像照镜子一样,从根开始。整两个遍历轴,一个往左遍历,一个往右遍历,形成镜面对称。
若其中有不同,那么结束遍历,返回false。
//两个遍历轴,遍历函数
bool symmetry(BinaryTree* &rootL,BinaryTree* &rootR) {
if(rootL==NULL&&rootR==NULL) return true;
if(rootL==NULL||rootR==NULL) return false;
if(rootL->data!=rootR->data) return false;
else return (rootL->left,rootR->right) && (rootL->right,rootR->left);
}
//主判断函数
bool isSymmetryTree(BinaryTree* &root) {
if(root==NULL) return true;
return symmetry(root->left,root->right);
}
单值二叉树
单值二叉树是指所有节点的data都一样
bool isUnivalTree(BinaryTree* &root) {
if(root==NULL) return true;
if(root->data != root->left->data) return false;
if(root->data != root->right->data) return false;
return isUnivalTree(root->left) && isUnivalTree(root->right);
}