//树的一些常见编程题目
#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);
}
二叉树的一些笔试面试常见题目
最新推荐文章于 2024-09-17 20:47:29 发布
本文详细介绍了二叉树的各种遍历方法,包括递归和非递归的前序、中序、后序遍历,以及层次遍历。此外,还涉及到了二叉树的创建、深度计算、节点计数以及判断是否为平衡二叉树等操作。通过这些内容,可以帮助读者深入理解二叉树的基本操作。
摘要由CSDN通过智能技术生成