1、基本概念。
二叉树:一种特化的树形结构。每个节点至多有两棵子树(每个节点的度小于等于2),即左子树与右子树,且左子树与右子树之间有左右差别。顺序不能颠倒。
满二叉树:每一层节点数为能所容纳的节点的最大数。
完全二叉树:最后一次层可以不满,但是要与满二叉树的节点编号对应。
2、二叉树的重要性质。
①第i层至多有[2^(i-1)]个结点。
②深度为d的二叉树至多共有[2^d-1]个结点。
③假定叶子结点个数为n0,度为2的节点个数为n2,则两者满足关系:n0=n1+1;
④节点个数为n的二叉树的深度为,Log2n+1;
⑤若一棵具有n个节点的完全二叉树的节点编号从上到下,从左到右,依次编号为1,2,3,...,n,则对于编号为i的节点,其父节点i/2;若2*i<=n,则其左子树根节点编号为2*i;若2*i+1<=n,则右子树节点编号为2*i+1;因此,最后一个非叶子节点为 [n/2-1]。
3、存储方式。
3-1、顺序存储;
3-2、链式存储。
4、实现。
4-1、二叉树的链式存储;
4-2、建立树;
4-3、遍历;
4-4、查找;
4-5、删除节点;
3、实现。
//定义树中的基本节点
struct BiTNode
{
//数据域
int data_;
//指向左右节点的指针
BiTNode *lChild_,*rChild_;
BiTNode(int data):
data_(data),
lChild_(nullptr),
rChild_(nullptr)
{
}
};
typedef BiTNode* BiTre;
//创建完全二叉树
void createTree(BiTre& tree)
{
char data_;
std::cin>>data_;
if(data_=='#')
{
tree=nullptr;
}
else
{
if(nullptr==tree)
tree=new BiTNode(data_);
//创建左子树
createTree(tree->lChild_);
//创建右子树
createTree(tree->rChild_);
}
return;
}
void printEle(BiTNode node)
{
std::cout<<node.data_<<"\t";
}
/*
* 递归的先序遍历二叉树
*/
void preTraverse(BiTre tree,void (*visited)(BiTNode node))
{
if(nullptr==tree)
return;
visited(*tree);
preTraverse(tree->lChild_,visited);
preTraverse(tree->rChild_,visited);
}
/*
* 递归的中序遍历二叉树
*/
void inorderTraverse(BiTre tree,void (*visited)(BiTNode node))
{
if(nullptr==tree)
return;
inorderTraverse(tree->lChild_,visited);
visited(*tree);
inorderTraverse(tree->rChild_,visited);
}
///*
// * 递归的后序遍历二叉树
// */
//void inorderTraverse(BiTre tree,void (*visited)(BiTNode node))
//{
// if(nullptr==tree)
// return;
// inorderTraverse(tree->lChild_,visited);
// inorderTraverse(tree->rChild_,visited);
// visited(*tree);
//}
/*
* 向二叉树的节点中插入一个值为value的节点
*/
void insertANode2Tree(BiTre& tree,int value)
{
BiTNode* newNode=new BiTNode(value);
BiTre q=tree;
//0、空树
if(nullptr==q)
q=newNode;
//1、非空树,查找插入位置
while(true)
{
//1-0 要插入的节点的值==当前节点的值,不做插入操作
if(value==q->data_)
{
break;
}
//1-1 比当前节点的值小且左子树不为空,左子树中找
else if(value<q->data_&&
nullptr!=q->lChild_)
q=q->lChild_;
//1-2 比当前节点的值小且左子树为空,直接插入左子树,结束while loop
else if(value<q->data_&&
nullptr==q->lChild_)
{
q->lChild_=newNode;
break;
}
//1-3 比当前节点的值大且右子树不为空,右子树中找
else if(value>q->data_&&
nullptr!=q->lChild_)
q=q->rChild_;
//1-4 比当前节点的值大且右子树为空,直接插入右子树,结束while loop
else
{
q->rChild_=newNode;
break;
}
}
return;
}
/*
* 从二叉树的中查找一个值为value的节点
* 查找成功,返回指向值为value的节点的指针
* 查找失败,返回空指针
*/
BiTNode* findANodeFromTree(BiTre& tree,int value)
{
BiTNode* newNode=nullptr;
BiTre q=tree;
//0、空树
if(nullptr==q)
return newNode;
//1、非空树,查找位置
while(true)
{
//1-0 要插入的节点的值==当前节点的值 返回
if(value==q->data_)
{
newNode=q;
break;
}
//1-1 比当前节点的值小且左子树不为空,左子树中找
else if(value<q->data_&&
nullptr!=q->lChild_)
q=q->lChild_;
//1-2 比当前节点的值小且左子树为空,结束查找
else if(value<q->data_&&
nullptr==q->lChild_)
{
break;
}
//1-3 比当前节点的值大且右子树不为空,右子树中找
else if(value>q->data_&&
nullptr!=q->lChild_)
q=q->rChild_;
//1-4 比当前节点的值大且右子树为空,结束查找
else
{
break;
}
}
return newNode;
}
BiTNode* inOrderPost(BiTNode* p)
{
BiTNode* pre=nullptr;
//1、空树
if(nullptr==p)
return pre;
//2、当前节点的右子树
pre=p->rChild_;
//3、走到右子树的最左端
while(nullptr!=pre->lChild_)
pre=pre->lChild_;
return pre;
}
/**
* @brief searchPre
* 寻找一个节点的父母
* @return 指向父母节点的指针
*/
BiTNode* searchPre(BiTre& tree,BiTNode& p)
{
BiTNode* q=tree;
if(nullptr!=q)
{
//0、找到了,q是p的父节点
if(q->lChild_==&p||q->rChild_==&p)
return q;
//1、递归地在当前结点的左右子树中分别查找
//1.2、当前结点q不是p的父母结点,递归地在当前结点的左子树中查找
BiTNode* lRes=searchPre(q->lChild_,p);
if(nullptr!=lRes)
return lRes;
//1.2、当前结点q不是p的父母结点且左子树中未找到
//递归地在当前结点的右子树中查找
BiTNode* rRes=searchPre(q->rChild_,p);
if(nullptr!=rRes)
return rRes;
}
//在tree中不存在结点p的父母结点
return nullptr;
}
bool deleteNodeFromTree(BiTre& tree,int value)
{
BiTre q=tree;
//0、空树
if(nullptr==q)
return false;
//1、非空树,查找位置
while(true)
{
//1-0 要删除的节点的值==当前节点的值 删除当前结点
if(value==q->data_)
{
//1-0-1、当前结点的左右子树均为空
if(q->lChild_==nullptr&&q->rChild_==nullptr)
{
BiTNode* p=searchPre(tree,*q);
//根结点没有父结点
if(nullptr==p)
{
p=q;
delete p;
p=nullptr;
}
else
{
if(p->lChild_==q)
{
p->lChild_=nullptr;
delete q;
q=nullptr;
}
else
{
p->rChild_=nullptr;
delete q;
q=nullptr;
}
}
}
//1-0-2、当前结点的右子树为空
else if(q->lChild_!=nullptr&&q->rChild_==nullptr)
{
BiTNode* p=searchPre(tree,*q);
//根结点没有父结点
if(nullptr==p)
{
p=q;
q=q->lChild_;
delete p;
p=nullptr;
}
else
{
if(p->lChild_==q)
{
p->lChild_=q->lChild_;
delete q;
q=nullptr;
}
else
{
p->rChild_=q->rChild_;
delete q;
q=nullptr;
}
}
}
//1-0-2、当前结点的左子树为空
else if(q->lChild_==nullptr&&q->rChild_!=nullptr)
{
BiTNode* p=searchPre(tree,*q);
//根结点没有父结点
if(nullptr==p)
{
p=q;
q=q->lChild_;
delete p;
p=nullptr;
}
else
{
if(p->lChild_==q)
{
p->lChild_=q->rChild_;
delete q;
q=nullptr;
}
else
{
p->rChild_=q->lChild_;
delete q;
q=nullptr;
}
}
}
else
//当前结点的左右子树均不为空
{
//寻找q节点的后继p
BiTNode* p=inOrderPost(q);
q->data_=p->data_;
BiTNode* pre=searchPre(tree,*q);
pre->lChild_=q->rChild_;
delete q;
q=nullptr;
}
return true;
}
//1-1 比当前节点的值小且左子树不为空,左子树中找
else if(value<q->data_&&
nullptr!=q->lChild_)
q=q->lChild_;
//1-2 比当前节点的值小且左子树为空,结束查找
else if(value<q->data_&&
nullptr==q->lChild_)
{
break;
}
//1-3 比当前节点的值大且右子树不为空,右子树中找
else if(value>q->data_&&
nullptr!=q->lChild_)
q=q->rChild_;
//1-4 比当前节点的值大且右子树为空,结束查找
else
{
break;
}
}
return false;
}