概述
一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
二叉树作为树的一种,是一种重要的数据结构,二叉树中的面试题比较常见的题型大概有下面几个:创建一颗二叉树(先序,中序,后序)、遍历一颗二叉树(先序,中序,后序和层次遍历)、求二叉树中叶子节点的个数、求二叉树的高度、求二叉树中两个节点的最近公共祖先、打印和为某一值的全部路径、求某一节点是否在一个树中等等。
二叉树节点BinTreeNode:
//二叉树节点
class BinTreeNode
{
private:
int data;
BinTreeNode*left,*right;
public:
//构造函数用初始化列表进行初始化
BinTreeNode(const int&item,BinTreeNode*lptr=NULL,BinTreeNode*rptr=NULL):data(item),left(lptr),right(rptr){};
void set_data(int item)
{
data=item;
}
int get_data()const
{
return data;
}
void set_left(BinTreeNode*l)
{
left=l;
}
BinTreeNode*get_left()const
{
return left;
}
void set_right(BinTreeNode*r)
{
right=r;
}
BinTreeNode*get_right()const
{
return right;
}
};
二叉树:BinTree
class BinTree
{
private:
BinTreeNode*root;
public:
BinTree(BinTreeNode*t=NULL):root(t){};
~BinTree()
{
destroytree(root);
}
void destroytree(BinTreeNode*r);
//设置根节点
void set_root(BinTreeNode*t)
{
root=t;
}
//获取根节点
BinTreeNode*get_root()const
{
return root;
}
//1.创建二叉树,返回根节点
BinTreeNode*create_tree();
//2.前序遍历
void pre_order(BinTreeNode*r)const;
//3.中序遍历
void in_order(BinTreeNode*r)const;
//4.后续遍历
void past_order(BinTreeNode*r)const;
//5.层次遍历
void level_order(BinTreeNode*r)const;
//6.获取叶子结点个数
int get_leaf_num(BinTreeNode*r)const;
//7.获得二叉树高度
int get_tree_height(BinTreeNode*r)const;
//8.交换二叉树的左右儿子
void swap_left_right(BinTreeNode*r);
//9.求两个节点pNode1和pNode2在以r为树根的树中的最近公共祖先
BinTreeNode* get_nearest_common_father(BinTreeNode *r,BinTreeNode *pNode1,BinTreeNode *pNode2)const;
//10.打印和为某一值的所有路径
void print_rout(BinTreeNode *r,int sum)const;
//11.判断一个节点t是否在以r为根的子树中
bool is_in_tree(BinTreeNode *r,BinTreeNode *t)const;
};
创建二叉树
我们以#代替空指针
3 7 3 9 # # # 6 # # 1 # 5 # 4 # #
我们一递归的方式来创建二叉树
//创建二叉树,这里不妨使用前序创建二叉树,遇到‘#’表示节点为空
BinTreeNode*BinTree::create_tree()
{
char item;
BinTreeNode*t,*t_l,*t_r;
cin>>item;
if(item!='#')
{
BinTreeNode*pTmpNode=new BinTreeNode(item-48);
t=pTmpNode;
t_l=create_tree();
t->set_left(t_l);
t_r=create_tree();
t->set_right(t_r);
return t;
}
else
{
t=NULL;
return NULL;
}
}
二叉树销毁
//销毁二叉树
void BinTree::destroytree(BinTreeNode*r)
{
if(r==NULL)
return;
else
{
destroytree(r->get_left());
destroytree(r->get_right());
delete(r);
}
}
先序/中序/后序遍历
遍历结果
先序遍历:3 7 3 9 6 1 5 4
中序遍历:9 3 7 6 3 1 5 4
后序遍历:9 3 6 7 4 5 1 3
void BinTree::pre_order(BinTreeNode*r)const
{
BinTreeNode*ptmpNode=r;
if(ptmpNode!=NULL)
{
cout<<ptmpNode->get_data()<<" ";
pre_order(ptmpNode->get_left());
pre_order(ptmpNode->get_right());
}
}
void BinTree::in_order(BinTreeNode*r)const
{
BinTreeNode*ptmpNode=r;
if(ptmpNode!=NULL)
{
in_order(ptmpNode->get_left());
cout<<ptmpNode->get_data()<<" ";
in_order(ptmpNode->get_right());
}
}
void BinTree::past_order(BinTreeNode*r)const
{
BinTreeNode*ptmpNode=r;
if(ptmpNode!=NULL)
{
past_order(ptmpNode->get_left());
past_order(ptmpNode->get_right());
cout<<ptmpNode->get_data()<<" ";
}
}
层序遍历
采用一个广度优先搜索的方法
层序遍历:3 7 1 3 6 5 9 4
void BinTree::level_order(BinTreeNode*r)const
{
if(r==NULL)
return ;
deque<BinTreeNode*>q;
q.push_back(r);
while(!q.empty())
{
BinTreeNode*pTmpNode=q.front();
cout<<pTmpNode->get_data()<<" ";
q.pop_front();
if(pTmpNode->get_left()!=NULL)
{
q.push_back(pTmpNode->get_left());
}
if(pTmpNode->get_right()!=NULL)
{
q.push_back(pTmpNode->get_right());
}
}
}
获得叶子节点个数
int BinTree::get_leaf_num(BinTreeNode*r)const
{
if(r==NULL)
{
return 0;
}
if(r->get_left()==NULL&&r->get_right()==NULL) //没有子结点
{
return 1;
}
return get_leaf_num(r->get_left())+get_leaf_num(r->get_right());
}
获取树的高度
int BinTree::get_tree_height(BinTreeNode*r)const
{
if(r==NULL)
return 0;
if(r->get_left()==NULL&&r->get_right()==NULL) //叶子节点
{
return 1;
}
int l_height=get_tree_height(r->get_left());
int r_height=get_tree_height(r->get_right());
return l_height>=r_height?l_height+1:r_height+1;
}
交换所有节点的左右孩子
void BinTree::swap_left_right(BinTreeNode*r)
{
if(r==NULL)
{
return ;
}
BinTreeNode*pTmpNode=r->get_left();
r->set_left(r->get_right());
r->set_right(pTmpNode);
swap_left_right(r->get_left());
swap_left_right(r->get_right());
}
判断某节点是否在树上
bool BinTree::is_in_tree(BinTreeNode*r,BinTreeNode*t)const
{
bool has=false;
if(r==NULL)
return false;
else if(r==t)
return true;
else
{
if(r->get_left()!=NULL)
{
has=is_in_tree(r->get_left(),t);
}
if(!has&&r->get_right()!=NULL)
{
has=is_in_tree(r->get_right(),t);
}
}
return has;
}
找最近的公共父节点
BinTreeNode* BinTree::get_nearest_common_father(BinTreeNode *r,BinTreeNode *pNode1,BinTreeNode *pNode2)const
{
if(is_in_tree(pNode1,pNode2))
{
return pNode1;
}
if(is_in_tree(pNode2,pNode1))
{
return pNode2;
}
bool one_in_left,one_in_right,another_in_left,another_in_right;
one_in_left=is_in_tree(r->get_left(),pNode1);
another_in_right=is_in_tree(r->get_right(),pNode2);
another_in_left=is_in_tree(r->get_left(),pNode2);
one_in_right=is_in_tree(r->get_right(),pNode1);
if((one_in_left&&another_in_right)||(one_in_right&&another_in_left))
{
return r;
}
else if(one_in_left&&another_in_left)
{
return get_nearest_common_father(r->get_left(),pNode1,pNode2);
}
else if(one_in_right&&another_in_right)
{
return get_nearest_common_father(r->get_right(),pNode1,pNode2);
}
else
{
return NULL;
}
}
打印和为某一值的所有路径
stack<BinTreeNode*>dfs_s;
stack<BinTreeNode*>print_s;
void BinTree ::print_rout(BinTreeNode*r,int sum)const
{
if(r==NULL)
return;
sum-=r->get_data();
dfs_s.push(r);
if(sum<=0)
{
if(sum==0)
{
while(!dfs_s.empty())
{
print_s.push(dfs_s.top());
dfs_s.pop();
}
while(!print_s.empty())
{
cout<<print_s.top()->get_data()<<" ";
dfs_s.push(print_s.top());
print_s.pop();
}
cout<<endl;
}
sum+=r->get_data();
dfs_s.pop();
return;
}
print_rout(r->get_left(),sum);
print_rout(r->get_right(),sum);
sum+=r->get_data();
dfs_s.pop();
}
测试代码
#include"bintree.hpp"
using namespace bintree;
int main()
{
BinTree tree;
/*--------------------------------------------------------------------------*/
cout<<"请输入二叉树前序序列进行建树,'#'代表空节点:"<<endl;
tree.set_root(tree.create_tree());
cout<<endl;
/*--------------------------------------------------------------------------*/
cout<<"前序遍历的结果:";
tree.pre_order(tree.get_root());
cout<<endl<<endl;
/*--------------------------------------------------------------------------*/
cout<<"中序遍历的结果:";
tree.in_order(tree.get_root());
cout<<endl<<endl;
/*--------------------------------------------------------------------------*/
cout<<"后序遍历的结果:";
tree.past_order(tree.get_root());
cout<<endl<<endl;
/*--------------------------------------------------------------------------*/
cout<<"层次遍历的结果:";
tree.level_order(tree.get_root());
cout<<endl<<endl;
/*--------------------------------------------------------------------------*/
cout<<"该二叉树叶子节点的个数:";
cout<<tree.get_leaf_num(tree.get_root())<<endl<<endl;
/*--------------------------------------------------------------------------*/
cout<<"该二叉树的高度是:";
cout<<tree.get_tree_height(tree.get_root())<<endl<<endl;
/*--------------------------------------------------------------------------*/
tree.swap_left_right(tree.get_root());
cout<<"交换左右子树之后的先序遍历结果为:";
tree.pre_order(tree.get_root());
cout<<endl<<endl;
/*--------------------------------------------------------------------------*/
BinTreeNode *p1 = tree.get_root()->get_right()->get_left();
BinTreeNode *p2 = tree.get_root()->get_left()->get_left();
BinTreeNode *p3 = tree.get_root()->get_right()->get_right()->get_right();
cout<<p1->get_data()<<" 和 "<<p2->get_data()<<"的最近公共祖先是:";
BinTreeNode *p = tree.get_nearest_common_father(tree.get_root(),p1,p2);
cout<<p->get_data()<<endl;
cout<<p1->get_data()<<" 和 "<<p3->get_data()<<"的最近公共祖先是:";
p = tree.get_nearest_common_father(tree.get_root(),p1,p3);
cout<<p->get_data()<<endl<<endl;
/*--------------------------------------------------------------------------*/
cout<<"路径如下:"<<endl;
tree.print_rout(tree.get_root(),13);
return 0;
}