文章目录
二叉树的存储链表数组
二叉树的基本操作插入递归非递归
删除查找并修改计算结点数计算树高
二叉树的算法二叉树遍历前序遍历中序遍历后序遍历层序遍历
二叉树判别判别完全二叉树思路1 入队列 & 最后一个非叶结点后的结点必无孩子思路2 入队列 & 出现空结点后不能再有非空
判别满二叉树思路1 完全二叉树 & 树高h+总结点数==2^树高^-1思路2 层序遍历 & 每层结点数==2^当前层高度^-1
判别二叉搜索树思路1 中序遍历为升序序列思路2 中序遍历 & 前一个数必小于后一个数
二叉树的存储
链表
数组
适用于 完全二叉树、满二叉树
二叉树的基本操作
插入
递归
void insert_dg(Node
* &p
, int x
) {
if(p
==NULL) {
p
= new Node(x
);
return;
}
if(p
->d
==x
)return;
else if(p
->d
>x
)
insert_dg(p
->l
,x
);
else
insert_dg(p
->r
,x
);
}
非递归
void insert(int x
) {
if(root
==NULL) {
root
= new Node(x
);
return;
}
Node
* p
=root
;
while(p
!=NULL) {
if(p
->d
==x
)return;
else if(p
->d
>x
) {
if(p
->l
==NULL) {
p
->l
= new Node(x
);
}
p
= p
->l
;
} else {
if(p
->l
==NULL) {
p
->r
= new Node(x
);
}
p
= p
->r
;
}
}
}
删除
查找并修改
bool search_update(Node
* root
,int x
,int newx
) {
if(root
==NULL)return false;
if(root
->d
==x
) {
root
->d
=newx
;
return true;
}
bool f
= search_update(root
->l
,x
,newx
);
if(f
) return true;
return search_update(root
->r
,x
,newx
);
}
计算结点数
void count(Node
* nd
,int &c
){
if(nd
==NULL)return;
c
++;
count(nd
->l
,c
);
count(nd
->r
,c
);
}
int count(Node
*nd
){
if(nd
==NULL)return 0;
int lc
= count(nd
->l
);
int rc
= count(nd
->r
);
return lc
+rc
+1;
}
计算树高
int high(Node
* nd
){
if(nd
==NULL)return 0;
int lh
= high(nd
->l
);
int rh
= high(nd
->r
);
return max(lh
,rh
)+1;
}
二叉树的算法
二叉树遍历
前序遍历
void pre_order(Node
*p
) {
if(p
==NULL)return;
printf("%d ",p
->d
);
pre_order(p
->l
);
pre_order(p
->r
);
}
中序遍历
void in_order(Node
*p
) {
if(p
==NULL)return;
in_order(p
->l
);
printf("%d ",p
->d
);
in_order(p
->r
);
}
后序遍历
void post_order(Node
*p
) {
if(p
==NULL)return;
post_order(p
->l
);
post_order(p
->r
);
printf("%d ",p
->d
);
}
层序遍历
void level_order() {
if(root
==NULL)return;
queue
<Node
*> q
;
q
.push(root
);
while(!q
.empty()) {
Node
* now
= q
.front();
q
.pop();
printf("%d ",now
->d
);
if(now
->l
!=NULL)q
.push(now
->l
);
if(now
->r
!=NULL)q
.push(now
->r
);
}
}
二叉树判别
判别完全二叉树
思路1 入队列 & 最后一个非叶结点后的结点必无孩子
BFS 将每一个节点都加入到队列,同时执行下面的判断
当前节点有右孩子,但没有左孩子,直接返回 false当前节点有左孩子没右孩子,那么接下来遇到的所有节点必须是叶子节点
bool isCBT(){
queue
<Node
*> q
;
q
.push(root
);
bool leaf
=false;
while(!q
.empty()){
Node
* now
= q
.front();
q
.pop();
if(leaf
&&(now
->l
!=NULL||now
->r
!=NULL))return false;
if(now
->l
!=NULL)q
.push(now
->l
);
else if(now
->r
!=NULL) return false;
if(now
->r
!=NULL)q
.push(now
->r
);
else leaf
= true;
}
return true;
}
思路2 入队列 & 出现空结点后不能再有非空
bool isCBT(){
queue
<Node
*> q
;
q
.push(root
);
while(!q
.empty()){
Node
* now
= q
.front();
q
.pop();
if(now
==NULL)break;
q
.push(now
->l
);
q
.push(now
->r
);
}
while(!q
.empty()){
Node
* now
= q
.front();
q
.pop();
if(now
!=NULL)return false;
}
return true;
}
判别满二叉树
思路1 完全二叉树 & 树高h+总结点数==2树高-1
bool isFBT() {
bool cbt
= isCBT();
if(cbt
==false)return false;
int h
= high(root
);
int c
= count(root
);
if(c
==pow(2,h
)-1)return true;
return false;
}
思路2 层序遍历 & 每层结点数==2当前层高度-1
判别二叉搜索树
思路1 中序遍历为升序序列
思路2 中序遍历 & 前一个数必小于后一个数
bool isBST(Node
* nd
,int &pre
){
if(nd
==NULL)return true;
bool l
= isBST(nd
->l
,pre
);
if(l
==false)return false;
if(pre
>nd
->d
)return false;
pre
=nd
->d
;
return isBST(nd
->r
,pre
);
}