您的位置:首页 > 理论基础 > 数据结构算法

【数据结构——树】二叉树面试相关知识点总结(一)

2014-07-21 12:12 656 查看
【1】二叉树节点定义【2】前序创建二叉树递归算法【3】二叉树的前中后序遍历递归和非递归解法(属于深度搜索)【4】层序遍历二叉树(按层次从上往下,从左往右)(属于广度搜索)【5】求二叉树中的节点个数【6】求二叉树的深度(剑指0ffer39)【7】求二叉树的镜像:递归交换左右子女【8】判断两棵二叉树是否结构相同【9】判断二叉树是不是平衡二叉树【10】判断二叉树是不是完全二叉树【1】二叉树节点定义
struct BiTreeNode
{
	char data;
	BiTreeNode *lchild;
	BiTreeNode *rchild;
}; BiTreeNode *T;
【2】前序创建二叉树
/*************构建二叉树**************/

void CreateBiTree(BiTreeNode* &T)//按先序输入二叉树的节点,#代表空树
{
	char num;
	cin >> num;
	if('#' == num)
		T = NULL;
	else
	{
		T = new BiTreeNode;//产生新的子树
		T->data = num;
		CreateBiTree(T->lchild);//递归创建左子树
		CreateBiTree(T->rchild);//递归创建右子树
	}			
}
【3】二叉树的前中后序遍历递归解法①前序遍历:如果二叉树不为空,访问根节点,前序遍历左子树,前序遍历右子树;否则,空操作
/*************先序递归遍历二叉树**************/
void PreOrderTraverse(BiTreeNode* &T){
	if(T)//节点不为空
	{
		cout << T->data;
		PreOrderTraverse(T->lchild);//递归遍历左子树
		PreOrderTraverse(T->rchild);//递归遍历右子树
	}
	else cout<<""; 
}
②中序遍历:如果二叉树不为空,中序遍历左子树,访问根节点,中序遍历右子树;否则,空操作
/*************中序递归遍历二叉树**************/
void InOrderTraverse(BiTreeNode* &T){
	if(T)
	{
		InOrderTraverse(T->lchild);//中序遍历左子树
		cout << T->data; //访问参数
		InOrderTraverse(T->lchild);//中序遍历右子树
	}
	else cout<<""; 
}
③后序遍历:如果二叉树不为空,后序遍历左子树,后序遍历右子树,访问根节点;否则,空操作
/*****************后序递归遍历二叉树***************/  
void PosorderTraverse(BiTreeNode* &T){  
 if(T){  
  PosorderTraverse(T->lchild);//后序递归遍历左子树  
  PosorderTraverse(T->rchild);//后序递归遍历右子树  
  cout<<T->data;//访问根结点  
 }  
 else cout<<"";  
}
<span style="font-size:12px;">遍历的非递归实现struct BiTreeNode{	char data;	BiTreeNode* lchild;	BiTreeNode* rchild;};void CreateBiTree(BiTreeNode* &T)//按先序输入二叉树的节点,#代表空树  {      char num;      cin >> num;      if('#' == num)          T = NULL;      else      {          T = new BiTreeNode;//产生新的子树          T->data = num;          CreateBiTree(T->lchild);//递归创建左子树          CreateBiTree(T->rchild);//递归创建右子树      }             }/*************【1】二叉树的前中后序遍历递归和非递归实现**************/  /********************先序递归遍历二叉树********************递归:节点为空就是递归出口,输出节点,遍历左孩子,遍历右孩子非递归:1.把根节点压栈,while循环栈不为空,设置指针,输出+弹出栈顶2.若右孩子存在,压入右孩子3.若左孩子存在,压入左孩子************************************************************/ void preOrder(BiTreeNode* root)//递归{	if(root == NULL)return;	cout << root->data <<endl;	preOrder(root->lchild);	preOrder(root->rchild);}void preOrder(BiTreeNode* root)//非递归,根左右,所以用栈,只要栈不空,就弹出{	if(!root)return;	stack<BiTreeNode> s;	s.push(root);	while(!s.empty())//如果根节点存在	{		BiTreeNode* p = s.top();	//设一个指针用于遍历		cout << p->data << endl;//先输出根节点		s.pop();		if(p->rchild)//先压入右孩子,再压入左孩子			s.push(p->rchild);		if(p->lchild)			s.push(p->lchild);	}}/********************中序递归遍历二叉树********************递归:节点为空就是递归出口,遍历左孩子,输出节点,遍历右孩子非递归:设置指针1.while循环栈不为空或者节点不为空,2.while节点存在,左孩子入栈3.if栈不为空,输出栈顶元素,弹出,指针指向右孩子************************************************************/ void InOrder(BiTreeNode* root)//递归{	if(root == NULL)return;	InOrder(root->lchild);	cout << root->data << endl;	InOrder(root->rchild);}void InOrder(BiTreeNode* root){	if(root == NULL)return;	stack<BiTreeNode*>s;	BiTreeNode* p = root;	while(p!=NULL || !s.empty())	{		while(p!=NULL)		{			s.push(p);			p=p->lchild;		}		if(!s.empty())		{			p = s.top();			cout << p->data << endl;			s.pop();			p = p->rchild;		}	}}/********************后序递归遍历二叉树********************递归:节点为空就是递归出口,遍历左孩子,遍历右孩子,输出节点非递归:设置当前指针和前指针1.while栈不为空,if为叶子节点,抑或前一节点是左孩子或右孩子,输出节点,变pre2.否则 如果分别压入右节点、左节点************************************************************/ void posOrder(BiTreeNode* root){	if(root == NULL)return;	posOrder(root->lchild);	posOrder(root->rchild);	cout << root->data << endl;}void posOrder(BiTreeNode* root){	if(root == NULL)return;	stack<BiTreeNode* > s;	BiTreeNode* pre =NULL,*cur;	s.push(root);	while(!s.empty())	{		cur = s.top();		if((cur->lchild ==NULL&&cur->rchild ==NULL)			|| pre != NULL&&(pre == cur->lchild || pre ==cur->rchild) )		{			cout <<cur->data << endl;			s.pop();			pre =cur;		}		else		{			if(cur->rchild != NULL)				s.push(cur->rchild);			if(cur->lchild != NULL)				s.push(cur->lchild);		}	}}int _tmain(int argc, _TCHAR* argv[]){	BiTreeNode* T = NULL;	cout << "创建一颗树T,#表示空树" << endl;      CreateBiTree(T); 	cout<<"中序递归遍历:"<<endl;       posOrder(T);      cout<<endl;  	return 0;}</span>
【4】二叉树的层序遍历每一层从左向右输出,因为元素需要存储有先进先出的特性,所以选用队列。二叉树的层次遍历更像是一种广度优先搜索BFS遍历的过程中将该层节点的孩子节点压入一个队列,这样就可以实现从上到下一层一层地遍历该二叉树。每次将根节点入队列,当队列非空,则将front赋给临时指针pNode,继而输出根节点,接下来判断根节点左右孩子是否为空,非空则入队列,上述工作以后,再度从队列中取元素,队列空,则循环结束。
/******************层序遍历******************/void LevelTraverse(BiTreeNode* &T){	if(T==NULL)return;	queue<BiTreeNode*> q;//创建队列来存储节点	q.push(T);//	while(!q.empty())//如果队列不为空	{		BiTreeNode* pNode = q.front();		q.pop();		cout << pNode->data;//访问节点		if (pNode->lchild != NULL)			q.push(pNode->lchild);		if(pNode->rchild != NULL)			q.push(pNode->rchild);		}	return;}
【5】求二叉树中叶子节点的个数递归解法:(1)如果二叉树为空,返回0(2)如果二叉树不为空且左右子树为空,返回1(3)如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数
<span style="font-size:12px;">/*****************求二叉树中叶子节点的个数*****************************/int LeavesCount(BiTreeNode* &T){	if(T==NULL)return 0;	if(T->lchild == NULL && T->rchild == NULL)return 1;	int numLeft = LeavesCount(T->lchild);//左子树中叶子节点个数	int numRight = LeavesCount(T->rchild);//右子树中叶子节点个数	return(numLeft + numRight);}</span><span style="font-size: 14px;"></span>
【6】求二叉树的深度深度即为递归左右子树的最大深度,如果节点为空则返回0,否则返回左右子树深度+1的最大值。
<span style="font-size:12px;">/**************求二叉树的深度**************/int DepthOfBiTree(BiTreeNode* &T){	if(T==NULL)return 0;//空树	int ldepth = DepthOfBiTree(T->lchild);//左子树的深度	int rdepth = DepthOfBiTree(T->rchild);//左子树的深度	return (ldepth>rdepth)?(ldepth+1):(rdepth+1);}</span>
【7】求二叉树镜像:递归交换左右子女若有节点存在,且其左右子树有节点存在,就交换,然后递归交换~
/*****************递归交换左右子女*******************/void exchangeChild(BiTreeNode* &T){	if(T==NULL)return;	BiTreeNode *temp = NULL;	cout << T->data << " ";	if(T->lchild||T->rchild)	{		temp = T->lchild;		T->lchild = T->rchild;		T->rchild = temp;		exchangeChild(T->lchild);		exchangeChild(T->rchild);	}	return;}
【8】判断两棵二叉树是否结构相同
/******************判断两棵二叉树是否结构相同**********************/bool equalBiTree(BiTreeNode* &T1,BiTreeNode* &T){ 	if(T1 == NULL && T == NULL )return true;//都为空则相同	else if(T1 == NULL || T == NULL )//一个为空一个不空,则不同		return false;	bool resultLeft = equalBiTree(T1->lchild,T->lchild);//比较左子树	bool resultRight = equalBiTree(T1->rchild,T->rchild);//比较右子树	return (resultLeft && resultRight); }
【9】判断是不是***L平衡树如果为空,则是如果不为空,左右子树都是***L且左右相差不大于1,则是注意:主函数,传递参数时高度设置变量
	cout<<"T是否***L平衡树:"<<endl;         int height=0;	if(IsAvl(T,height))		cout << "是***L平衡树";	else		cout << "不是***L平衡树";	cout<<endl;	
/**************************判断是不是***L平衡树****************************/bool IsAvl(BiTreeNode* &T,int &height)//还要判断左右子树高度是否差1{	if(T == NULL)	{		height = 0;		return true;	}	int heightLeft;	bool resultLeft = IsAvl(T->lchild,heightLeft);	int heightRight;	bool resultRight = IsAvl(T->rchild,heightRight);	if(resultLeft && resultRight && abs(heightLeft - heightRight)<=1)//如果左右子树都为平衡树且高度差不大于1	{		height = max(heightLeft, heightRight)+1;		return true;	}	else	{		height = max(heightLeft, heightRight) + 1;          return false;  	}}
【10】判断是否完全二叉树首先,完全二叉树是指若二叉树深度为h,第h-1层节点数都是最大个数,第h层所有节点都集中再最左边。算法原理:按层次遍历二叉树,建立队列来保存节点。如果队列不为空,从第一个根节点开始遍历。1.如果节点没有子树,则判断左右子树节点是否为空,有则不是。2.如果有子树,左右子树都不为空,则继续遍历。左不空,右空,左子树压入队列,继续若左空右不空,不是。若左右都空,则是。
/**************************判断是不是完全二叉树****************************/bool IsCompleteBinaryTree(BiTreeNode* &T){	if(T == NULL)return false;	queue<BiTreeNode*> q;//创建队列来存储节点	q.push(T);	bool mustHaveNoChild = false;	bool result = true;	while(!q.empty())//如果队列不为空	{		BiTreeNode* pNode = q.front();//队列头结点为指针		q.pop();//把头结点出列		if(mustHaveNoChild)//如果该节点没有子树		{			if(pNode->lchild != NULL || pNode->rchild != NULL)			{				result = false;//如果左子树或右子树不为空,则不是完全二叉树				break;			}		}		else//如果该节点有子树		{			if(pNode->lchild != NULL && pNode->rchild != NULL)//左右子树都不为空			{				q.push(pNode->lchild);				q.push(pNode->rchild);			}			else if(pNode->lchild != NULL && pNode->rchild == NULL)//左子树不为空,右子树为空			{				mustHaveNoChild = true;				q.push(pNode->lchild);			}			else if(pNode->lchild == NULL && pNode->rchild != NULL)//左子树为空,右子树不为空			{				 result = false;  				 break;  			}			else//左右子树都为空			{  					   mustHaveNoChild = true;  			} 		}	}	return result;}
cout<<"T是否完全二叉树:"<<endl; 	if(IsCompleteBinaryTree(T))		cout << "是完全二叉树";	else		cout << "不是完全二叉树";	cout<<endl;
#include<iostream>#include<queue>using namespace std;/***************定义二叉树****************/struct BiTreeNode{	char data;	BiTreeNode *lchild;	BiTreeNode *rchild;}; BiTreeNode *T; BiTreeNode *T1,*T2;/*************构建二叉树**************/

void CreateBiTree(BiTreeNode* &T)//按先序输入二叉树的节点,#代表空树
{
	char num;
	cin >> num;
	if('#' == num)
		T = NULL;
	else
	{
		T = new BiTreeNode;//产生新的子树
		T->data = num;
		CreateBiTree(T->lchild);//递归创建左子树
		CreateBiTree(T->rchild);//递归创建右子树
	}			
}/*************先序递归遍历二叉树**************/
void PreOrderTraverse(BiTreeNode* &T){
	if(T)//节点不为空
	{
		cout << T->data;
		PreOrderTraverse(T->lchild);//递归遍历左子树
		PreOrderTraverse(T->rchild);//递归遍历右子树
	}
	else cout<<""; 
}/*************中序递归遍历二叉树**************/void InOrderTraverse(BiTreeNode* &T){	if(T!=NULL)	{		InOrderTraverse(T->lchild);//中序遍历左子树		cout << T->data; //访问参数		InOrderTraverse(T->lchild);//中序遍历右子树	}	else cout<<""; }/*****************后序递归遍历二叉树***************/  
void PosorderTraverse(BiTreeNode* &T){  
 if(T){  
  PosorderTraverse(T->lchild);//后序递归遍历左子树  
  PosorderTraverse(T->rchild);//后序递归遍历右子树  
  cout<<T->data;//访问根结点  
 }  
 else cout<<"";  
}/******************层序遍历******************/void LevelTraverse(BiTreeNode* &T){	if(T==NULL)return;	queue<BiTreeNode*> q;//创建队列来存储节点	q.push(T);//	while(!q.empty())//如果队列不为空	{		BiTreeNode* pNode = q.front();		q.pop();		cout << pNode->data;//访问节点		if (pNode->lchild != NULL)			q.push(pNode->lchild);		if(pNode->rchild != NULL)			q.push(pNode->rchild);		}	return;}/**************************判断是不是完全二叉树****************************/bool IsCompleteBinaryTree(BiTreeNode* &T){	if(T == NULL)return false;	queue<BiTreeNode*> q;//创建队列来存储节点	q.push(T);	bool mustHaveNoChild = false;	bool result = true;	while(!q.empty())//如果队列不为空	{		BiTreeNode* pNode = q.front();//队列头结点为指针		q.pop();//把头结点出列		if(mustHaveNoChild)//如果该节点没有子树		{			if(pNode->lchild != NULL || pNode->rchild != NULL)			{				result = false;//如果左子树或右子树不为空,则不是完全二叉树				break;			}		}		else//如果该节点有子树		{			if(pNode->lchild != NULL && pNode->rchild != NULL)//左右子树都不为空			{				q.push(pNode->lchild);				q.push(pNode->rchild);			}			else if(pNode->lchild != NULL && pNode->rchild == NULL)//左子树不为空,右子树为空			{				mustHaveNoChild = true;				q.push(pNode->lchild);			}			else if(pNode->lchild == NULL && pNode->rchild != NULL)//左子树为空,右子树不为空			{				 result = false;  				 break;  			}			else//左右子树都为空			{  					   mustHaveNoChild = true;  			} 		}	}	return result;}/*****************求二叉树中叶子节点的个数*****************************/int LeavesCount(BiTreeNode* &T){	if(T==NULL)return 0;	if(T->lchild == NULL && T->rchild == NULL)return 1;	int numLeft = LeavesCount(T->lchild);//左子树中叶子节点个数	int numRight = LeavesCount(T->rchild);//右子树中叶子节点个数	return(numLeft + numRight);}/**************求二叉树的深度**************/int DepthOfBiTree(BiTreeNode* &T){	if(T==NULL)return 0;//空树	int ldepth = DepthOfBiTree(T->lchild);//左子树的深度	int rdepth = DepthOfBiTree(T->rchild);//左子树的深度	return (ldepth>rdepth)?(ldepth+1):(rdepth+1);}/*****************递归交换左右子女*******************/void exchangeChild(BiTreeNode* &T){	if(T==NULL)return;	BiTreeNode *temp = NULL;	cout << T->data << " ";	if(T->lchild||T->rchild)	{		temp = T->lchild;		T->lchild = T->rchild;		T->rchild = temp;		exchangeChild(T->lchild);		exchangeChild(T->rchild);	}	return;}/******************判断两棵二叉树是否结构相同**********************/bool equalBiTree(BiTreeNode* &T1,BiTreeNode* &T){ 	if(T1 == NULL && T == NULL )return true;//都为空则相同	else if(T1 == NULL || T == NULL )//一个为空一个不空,则不同		return false;	bool resultLeft = equalBiTree(T1->lchild,T->lchild);//比较左子树	bool resultRight = equalBiTree(T1->rchild,T->rchild);//比较右子树	return (resultLeft && resultRight); }/**************************判断是不是***L平衡树****************************/bool IsAvl(BiTreeNode* &T,int &height)//还要判断左右子树高度是否差1{	if(T == NULL)	{		height = 0;		return true;	}	int heightLeft;	bool resultLeft = IsAvl(T->lchild,heightLeft);	int heightRight;	bool resultRight = IsAvl(T->rchild,heightRight);	if(resultLeft && resultRight && abs(heightLeft - heightRight)<=1)//如果左右子树都为平衡树且高度差不大于1	{		height = max(heightLeft, heightRight)+1;		return true;	}	else	{		height = max(heightLeft, heightRight) + 1;          return false;  	}}int main(){	cout << "创建一颗树T,#表示空树" << endl;	CreateBiTree(T);	cout << "创建一颗树T1,#表示空树" << endl;	CreateBiTree(T1);	cout<<"先序递归遍历:"<<endl;  	PreOrderTraverse(T);  	cout<<endl; 	cout<<"中序递归遍历:"<<endl; 	InOrderTraverse(T);  	cout<<endl;  	cout<<"后序递归遍历:"<<endl;  	PosorderTraverse(T);  	cout<<endl;	cout<<"层序递归遍历:"<<endl;  	LevelTraverse(T);  	cout<<endl;	cout<<"叶子节点个数:"<<endl;  	cout << LeavesCount(T);  	cout<<endl;	cout<<"二叉树深度:"<<endl;  	cout << DepthOfBiTree(T);  	cout<<endl;	cout<<"递归交换左右子女:"<<endl;  	exchangeChild(T);  	cout<<endl;	cout<<"T和T1是否结构相同?"<<endl;  	if(equalBiTree(T1,T))		cout << "两者相同";	else		cout << "两棵树结构不同";	cout<<endl;	cout<<"T是否***L平衡树:"<<endl;    int	height=0;	if(IsAvl(T,height))		cout << "是***L平衡树";	else		cout << "不是***L平衡树";	cout<<endl;		cout<<"T是否完全二叉树:"<<endl; 	if(IsCompleteBinaryTree(T))		cout << "是完全二叉树";	else		cout << "不是完全二叉树";	cout<<endl;	system("pause");	return 0;} 

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: