二叉树涉及到的东西很多,分成几天来复习
一.基本概念(参考电子科大mooc内容)
递归定义:
二叉树或为空树,或由一个根节点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成。
相关概念:
1.结点的度:结点拥有的子树个数
2.叶子:度为0的结点
3.child:结点子树的根
4.parent:child结点的上层结点
5.子孙:以某节点为根的子树中的任意一个结点
6. 祖先:从叶子走到根结点所经的所有结点
7. 结点的层次:根为一层,其孩子为第二层,孩子的孩子为第三层,以此类推
8. 兄弟:同一个结点的孩子
9. 堂兄:双亲在同一层的结点
10.二叉树的度:最大的结点度(二叉树度最大为2)
11.深度:结点的最大层次数
特点:
1 . 每一个节点最多有两颗子树,不存在节点度大于2的节点
2 . 子树有左右之分,不能颠倒
几种基本形态:
1 .空树
2 .只含根结点
3 .右子树为空树(左子树为空树)
4 .左右子树均不为空树
两种特殊的二叉树:
1.满二叉树:除了叶子结点,所有结点的度都为2,且叶子节点在同一层
2.完全二叉树:除了最后一层,其他各层结点都达到最大个数,最后一层所有节点集中在左边(结点只可能出现在最下层或次最下层,结点数n满足:
2
k
−
1
−
1
2^{k-1}-1
2k−1−1<n<=
2
k
−
1
2^k-1
2k−1
满二叉树是完全二叉树,反之不成立
二叉树的性质:
1.在二叉树的第i层上至多有(
2
i
−
1
2^{i-1}
2i−1)个结点(i>=1)(即每层最大节点数是确定的)
2.深度为k的二叉树至多含(
2
k
2^k
2k )-1个结点(k>=1)
3.叶节点与双分支结点的关系:
对任何一棵二叉树,设叶子节点数为n0,度为2的结点数为n2,则有n0=n2+1
4.具有n个结点的完全二叉树深度为:
l
o
g
2
n
log_2{n}
log2n+1
5.对一个完全二叉树(n个结点)结点按层序编号,对任意一个结点i有:
若i=1,则结点为二叉树的根,i>1,则其双亲为i/2(向下取整)
若2i>n,则结点i无左孩子,若2i<=n,则其左孩子为2i
若2i+1>n,则结点i无右孩子,若2i<=n,则其右孩子为2i+1
二.二叉树构建分析(c++)
(一)相关操作:
创建二叉树
三种方式遍历(先序,中序,后序)
找到结点并填入数据
销毁二叉树
今天就先实现这么多,免得消化不良
(二)相关定义和声明
结点定义:
//包含:左右子树,序号,数据
template<typename T>
class BiNode{
public:
BiNode<T> *lchild;
BiNode<T> *rchild;
T data;
char No;
};
二叉树定义:
/*包含:构造函数,析构函数
三种遍历函数
输入数据函数*/
template<typename T>
class My_BiTree{
public:
My_BiTree();
~My_BiTree();
void CreateBiTree();
void PreTraversing();
void InTraversing();
void PostTraversing();
void InputData(char n,T data)
private:
BiNode<T> *parent;
};
(三)函数实现代码
template<typename T>
My_BiTree<T>::My_BiTree()
{
parent=new BiNode<T>;
parent->lchild=NULL;
parent->rchild=NULL;
std::cout<<"please input char as no.,'#' to stop"<<std::endl;
parent=CreateBiTree();
};
template<typename T>
BiNode<T>* My_BiTree<T>::CreateBiTree()
{
BiNode<T> *node;
char temp;
std::cin>>temp;
if(temp=='#')
{
return NULL;
}
else
{
node=new BiNode<T>;
node->No=temp;
std::cout<<"add success:"<<node->No<<std::endl;
node->lchild=CreateBiTree();
node->rchild=CreateBiTree();
return node;
}
};
template<typename T>
void My_BiTree<T>::PreTraversing(BiNode<T> *node)
{
if(node)
{
std::cout<<node->No<<" ";
PreTraversing(node->lchild);
PreTraversing(node->rchild);
}
};
template<typename T>
void My_BiTree<T>::PreTraversing()
{
PreTraversing(parent);
std::cout<<std::endl;
}
template<typename T>
void My_BiTree<T>::InTraversing(BiNode<T> *node)
{
if(node!=NULL)
{
InTraversing(node->lchild);
std::cout<<node->No<<" ";
InTraversing(node->rchild);
}
};
template<typename T>
void My_BiTree<T>::InTraversing()
{
InTraversing(parent);
std::cout<<std::endl;
}
template<typename T>
void My_BiTree<T>::PostTraversing(BiNode<T> *node)
{
if(node!=NULL)
{
PostTraversing(node->lchild);
PostTraversing(node->rchild);
std::cout<<node->No<<" ";
}
};
template<typename T>
void My_BiTree<T>::PostTraversing()
{
PostTraversing(parent);
std::cout<<std::endl;
}
template<typename T>
void My_BiTree<T>::InputData(BiNode<T> *node)
{
if(node!=NULL)
{
std::cout<<"this is no."<<node->No<<" please input data"<<std::endl;
std::cin>>node->data;
InputData(node->lchild);
InputData(node->rchild);
}
}
template<typename T>
void My_BiTree<T>::DestroyTree(BiNode<T> *node)
{
if(node!=NULL)
{
DestroyTree(node->lchild);
DestroyTree(node->rchild);
if(node==parent)std::cout<<"destruction complete"<<std::endl;
delete node;
}
};
template<typename T>
My_BiTree<T>::~My_BiTree()
{
DestroyTree(parent);
};
int main()
{
My_BiTree<int> b1;
b1.PreTraversing();
b1.InTraversing();
b1.PostTraversing();
return 0;
}
在CreateTree上卡了很久…一开始用的void来写的,在指针传值上被搞晕了,后面直接改成返回一个Binode的指针,以赋值的形式来创建就好了
结果:
没问题