二叉树的一些笔试面试常见题目

本文详细介绍了二叉树的各种遍历方法,包括递归和非递归的前序、中序、后序遍历,以及层次遍历。此外,还涉及到了二叉树的创建、深度计算、节点计数以及判断是否为平衡二叉树等操作。通过这些内容,可以帮助读者深入理解二叉树的基本操作。
摘要由CSDN通过智能技术生成
//树的一些常见编程题目
#include<iostream>    
#include<queue>    
#include<stack>    
using namespace std;    
    
//二叉树结点的描述    
typedef struct BiTNode  
{    
    char data;    
    struct BiTNode *lchild, *rchild;      //左右孩子    
}BiTNode,*BiTree;    
    
//按先序遍历创建二叉树    
//BiTree *CreateBiTree()     //返回结点指针类型    
//void CreateBiTree(BiTree &root)      //引用类型的参数    
void CreateBiTree(BiTNode **root)    //二级指针作为函数参数    
{    
    char ch; //要插入的数据    
    scanf("\n%c", &ch);  
    //cin>>ch;    
    if(ch=='#')  
        *root = NULL;  
    else  
    {  
        *root = (BiTNode *)malloc(sizeof(BiTNode));  
        (*root)->data = ch;  
        printf("请输入%c的左孩子:",ch);  
        CreateBiTree(&((*root)->lchild));  
        printf("请输入%c的右孩子:",ch);  
        CreateBiTree(&((*root)->rchild));  
    }  
}  
    
//前序遍历的算法程序    
void PreOrder(BiTNode *root)  
{    
    if(root==NULL)    
        return ;    
    printf("%c ", root->data); //输出数据    
    PreOrder(root->lchild); //递归调用,前序遍历左子树    
    PreOrder(root->rchild); //递归调用,前序遍历右子树    
}    
    
//中序遍历的算法程序    
void InOrder(BiTNode *root)    
{    
    if(root==NULL)  
        return ;  
    InOrder(root->lchild); //递归调用,前序遍历左子树    
    printf("%c ", root->data); //输出数据    
    InOrder(root->rchild); //递归调用,前序遍历右子树    
}    
    
//后序遍历的算法程序    
void PostOrder(BiTNode *root)  
{  
    if(root==NULL)  
        return ;  
    PostOrder(root->lchild);      //递归调用,前序遍历左子树    
    PostOrder(root->rchild);      //递归调用,前序遍历右子树    
    printf("%c ", root->data);    //输出数据      
}    
    
/*  
二叉树的非递归前序遍历,前序遍历思想:先让根进栈,只要栈不为空,就可以做弹出操作,  
每次弹出一个结点,记得把它的左右结点都进栈,记得右子树先进栈,这样可以保证右子树在栈中总处于左子树的下面。  
*/ 
#if 1
void PreOrder_Nonrecursive(BiTree T)     //先序遍历的非递归      
{    
    if(!T)      
        return ;      
      
    stack<BiTree> s;    
    s.push(T);    
    
    while(!s.empty())    
    {    
        BiTree temp = s.top();    
        cout<<temp->data<<" ";    
        s.pop();    
        if(temp->rchild)    
            s.push(temp->rchild);    
        if(temp->lchild)    
            s.push(temp->lchild);    
    }    
}      
#endif

/*  
二叉树的非递归中序遍历*/
void InOrder_Nonrecursive1(BiTree T)
{
	if(T == NULL)
		return;

	stack<BiTree> s;
	BiTree curr = T;
	
	while(curr != NULL)
	{
		s.push(curr);
		curr = curr->lchild;
	}

	while(!s.empty())
	{
		curr = s.top();
		s.pop();
		cout<<curr->data<<" ";
		if(curr->rchild)
		{
			curr = curr->rchild;
			while(curr != NULL)
			{
				s.push(curr);
				curr = curr->lchild;
			}
		}
	}
}

void PostOrder_Nonrecursive1(BiTree T)  // 后序遍历的非递归      
{      
	if(T == NULL)
		return;
    stack<BiTree> s;      
    BiTree curr = T ;           // 指向当前要检查的节点    
    BiTree previsited = NULL;    // 指向前一个被访问的节点    
	while(curr != NULL)
	{
		s.push(curr);
		curr = curr->lchild;
	}

	while(!s.empty())
	{
		curr = s.top();
		//如果右子树为空或者已经被访问过,则输出当前结点
		if(curr->rchild == NULL || curr->rchild == previsited)
		{
			cout<<curr->data<<" ";
			previsited = curr;
			s.pop();
		} 
		else if(curr->lchild == previsited) //如果左子树已经被访问,则访问右子树
		{
			curr = curr->rchild;
			while(curr != NULL)
			{
				s.push(curr);
				curr = curr->lchild;
			}
		}
	}
}     
    
void PostOrder_Nonrecursive(BiTree T)  // 后序遍历的非递归     双栈法    
{      
    stack<BiTree> s1 , s2;      
    BiTree curr ;           // 指向当前要检查的节点    
    s1.push(T);    
  
	while(!s1.empty())  // 栈空时结束      
    {    
        curr = s1.top();    
        s1.pop();    
        s2.push(curr);    
        if(curr->lchild)    
            s1.push(curr->lchild);    
        if(curr->rchild)    
            s1.push(curr->rchild);    
    }    
    
	while(!s2.empty())    
    {    
        printf("%c ", s2.top()->data);    
        s2.pop();    
    }    
}  
    
int visit(BiTree T)    
{    
    if(T)    
    {    
        printf("%c ",T->data);    
        return 1;    
    }    
    else    
        return 0;    
}    
    
// 使用递归求二叉树的深度
int getDepth(BiTree T)
{
	if(T == NULL)
		return 0;
	int d1 = getDepth(T->lchild);
	int d2 = getDepth(T->rchild);
	return (d1 > d2 ? d1 : d2) + 1;
}

// 使用非递归算法求二叉树的深度,根据层次遍历来求解
#define MARK ((BiTree) -1)
int visit2(BiTree T,int &depth)
{ 
	if(T == NULL)
		return -1;
	
	if(T == MARK)
		++depth;
	
	return 1;

}

int getDepth_Nonrecursive(BiTree T)
{
	if(T == NULL)
		return 0;
	queue<BiTree> Q;
	Q.push(T);
	Q.push(MARK);
	int depth = 0;
	
	while(!Q.empty())
	{
		int flag = 0;
		BiTree curr = Q.front();
		Q.pop();
		visit2(curr,depth);
		if(curr != MARK && curr->lchild)
		{
			Q.push(curr->lchild);
			flag = 1;
		}

		if(curr != MARK && curr->rchild)
		{
			Q.push(curr->rchild);
			flag = 1;
		}
		if(flag)
			Q.push(MARK);
	}
	return depth;
}

//使用递归求出二叉树的结点个数
int getNodeCount(BiTree T)
{
	if(T == NULL)
		return 0;
	return 1 + getNodeCount(T->lchild) + getNodeCount(T->rchild);
}

//递归判断二叉树是否相等
bool cmpTree(BiTree T1,BiTree T2)
{
	if(T1 == NULL && T2 == NULL)
		return true;
	if(T1 == NULL || T2 == NULL)
		return false;

	if(T1 && T2)
	{
		if(T1->data == T2->data)
		{
			if(cmpTree(T1->lchild,T2->lchild))
				return cmpTree(T1->rchild,T2->rchild);
			else if(cmpTree(T1->lchild,T2->rchild))
				return cmpTree(T1->rchild,T2->lchild);
		}
	}
}

//使用队列层次遍历二叉树
void LeverTraverse(BiTree T) 
{
	queue<BiTree> Q;
	BiTree p = T;
	if(p != NULL)
		Q.push(p);
	
	while(!Q.empty())
	{	
		BiTree curr = Q.front();
		Q.pop();
		visit(curr);
		if(curr->lchild)
		{
			Q.push(curr->lchild);
		}

		if(curr->rchild)
		{
			Q.push(curr->rchild);
		}
	}
}

//如何判断二叉树是否是平衡二叉树
void IsBalance()
{

}

//判断B是否是A的子树
bool DoesTree1HaveTree2(BiTree T1,BiTree T2)
{
	if(T1 == NULL)
		return false;
	if(T2 == NULL)
		return true;
	if(T1->data != T2->data)
		return false;

	if(DoesTree1HaveTree2(T1->lchild,T2->lchild))
		return DoesTree1HaveTree2(T1->rchild,T2->rchild);
	else
		return false;
}
bool HasSubtree(BiTree T1,BiTree T2)
{
	bool result = false;
	
	if(T1 != NULL && T2 != NULL)
	{
		if(T1->data == T2->data)
			result = DoesTree1HaveTree2(T1,T2);
		if(!result)
			result = HasSubtree(T1->lchild,T2);
		if(!result)
			result = HasSubtree(T2->rchild,T2);
	}

	return result;
}


#if 0
int main(void)    
{    
    BiTNode *root = NULL; //定义一个根结点    
    int flag=1,k;    
    printf("                     本程序实现二叉树的基本操作。\n");    
    printf("可以进行建立二叉树,递归先序、中序、后序遍历,非递归先序、中序遍历及非递归层序遍历等操作。\n");    
    
    while(flag)    
    {    
        printf("\n");    
        printf("|--------------------------------------------------------------|\n");    
        printf("|                    二叉树的基本操作如下:                     |\n");    
        printf("|                        0.创建二叉树                          |\n");    
        printf("|                        1.递归先序遍历                        |\n");    
        printf("|                        2.递归中序遍历                        |\n");    
        printf("|                        3.递归后序遍历                        |\n");    
        printf("|                        4.非递归先序遍历                      |\n");    
        printf("|                        5.非递归中序遍历                      |\n");    
        printf("|                        6.非递归后序遍历                      |\n");    
        printf("|                        7.非递归层序遍历                      |\n");    
        printf("|                        8.二叉树的深度                        |\n");    
        printf("|                        9.二叉树的结点个数                    |\n");    
        printf("|                        10.退出程序                            |\n");    
        printf("|--------------------------------------------------------------|\n");    
        printf("                        请选择功能:");    
        scanf("%d",&k);    
        switch(k)    
        {    
        case 0:    
            printf("请建立二叉树并输入二叉树的根节点:");    
            CreateBiTree(&root);    
            break;    
        case 1:    
            if(root)    
            {    
                printf("递归先序遍历二叉树的结果为:");    
                PreOrder(root);    
                printf("\n");    
            }    
            else    
                printf("          二叉树为空!\n");    
            break;    
        case 2:    
            if(root)    
            {    
                printf("递归中序遍历二叉树的结果为:");    
                InOrder(root);    
                printf("\n");    
            }    
            else    
                printf("          二叉树为空!\n");    
            break;    
        case 3:    
            if(root)    
            {    
                printf("递归后序遍历二叉树的结果为:");    
                PostOrder(root);    
                printf("\n");    
            }    
            else    
                printf("          二叉树为空!\n");    
            break;    
        case 4:    
            if(root)    
            {    
                printf("非递归先序遍历二叉树:");    
                PreOrder_Nonrecursive(root);    
                printf("\n");    
            }    
            else    
                printf("          二叉树为空!\n");    
            break;    
        case 5:    
            if(root)    
            {    
                printf("非递归中序遍历二叉树:");    
                //InOrderTraverse1(root);    
				InOrder_Nonrecursive1(root);
                printf("\n");    
            }    
            else    
                printf("          二叉树为空!\n");    
            break;    
        case 6:    
            if(root)    
            {    
                printf("非递归后序遍历二叉树:");    
                PostOrder_Nonrecursive(root);   
				//PostOrder_Nonrecursive1(root);
                printf("\n");    
            }    
            else    
                printf("          二叉树为空!\n");    
            break;    
        case 7:    
            if(root)    
            {    
                printf("非递归层序遍历二叉树:");    
                //LeverTraverse(root);    
                LevelOrder(root);    
                printf("\n");    
            }    
            else    
                printf("          二叉树为空!\n");    
            break;    
        case 8:    
            if(root)    
                printf("这棵二叉树的深度为:%d\n",depth(root));    
            else    
                printf("          二叉树为空!\n");    
            break;    
        case 9:    
            if(root)    
                printf("这棵二叉树的结点个数为:%d\n",CountNode(root));    
            else    
                printf("          二叉树为空!\n");    
            break;    
        default:    
            flag=0;    
            printf("程序运行结束,按任意键退出!\n");    
        }    
    }    
    system("pause");    
    return 0;    
}
#endif

//根据前序和中序遍历来构建二叉树
int CreateBiTreeWithPreAndIn(char *pPre,char *pIn,int num,BiTNode *T)
{
	if(pPre == NULL || pIn == NULL || T == NULL)
		return -1;
	
	if(num == 0)
		return 0;
	T->data = pPre[0];
	int i = 0;
	for(i = 0;i < num;++i)
	{
		if(pIn[i] == T->data)
			break;
	}
	
	if(i == num)
	{
		printf("--\n");
		return -2;
	}

	if(i > 0) // 有左子树
	{
		T->lchild = new BiTNode();
		CreateBiTreeWithPreAndIn(pPre+1,pIn,i,T->lchild);
	}

	if(num - i - 1 > 0) // 有右子树
	{	
		T->rchild = new BiTNode();
		CreateBiTreeWithPreAndIn(pPre+i+1,pIn+i+1,num - i - 1,T->rchild);
	}
	
}

//输入一个数组,判断是否是一个二叉搜索树的后序遍历
bool IsBiTreePostOrder(int a[],int n)
{
	if(a == NULL)
		return false;
	if(n == 1)
		return true;
   
	if(n > 1)
	{
		int root = a[n-1];
		int leftLen = 0;
		for(int i = 0;i < n-1;++i)
		{
			if(a[i] < root)
				leftLen = i+1;
			else
				break;
		}

		for(int i = leftLen + 1;i<n-1;++i)
		{
			if(a[i] < root)
				return false;
		}

		if(IsBiTreePostOrder(a,leftLen))
			return IsBiTreePostOrder(a+leftLen,n-leftLen-1);
	}	
}

//计算出从根节点到叶节点路径和等于expectedSum的路径
void printPath(vector<char> &path)
{
	for(auto it = path.cbegin();it != path.cend();++it)
	{
		printf("%d ",*it);
	}
	printf("\n");
}

void FindPath(BiTree T,char expectedSum,char currSum,vector<char> &path)
{
	path.push_back(T->data);
	currSum += T->data;
	bool isLeaf = (T->lchild == NULL && T->rchild == NULL);
	if(isLeaf && currSum == expectedSum)
		printPath(path);
	if(T->lchild)
		FindPath(T->lchild,expectedSum,currSum,path);
	if(T->rchild)
		FindPath(T->rchild,expectedSum,currSum,path);
	path.pop_back();
}

void  FindPath(BiTree T,char expectedSum)
{
	if(T == NULL)
		return ;
	char currSum = 0 ;
	vector<char> path;
	FindPath(T,expectedSum,currSum,path);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值