二叉树的经典算法题
以二叉链表作为二叉树的存储结构,编写以下算法:
1.二叉树的先序遍历,中序遍历,后序遍历的非递归算法。
//先序遍历
void PreOrder2(BiTree T)
{
InitStack(S);
BiTree p=T;
while(p||!IsEmpty(S))
{
if(p)
{
visit(p);
Push(S,p);
p=p->lchild;
}
else
{
Pop(S,p);
p=p->rchild;
}
}
}
//中序遍历
void InOrder2(BiTree T)
{
InitStack(S);
BiTree p=T;
while(p||!IsEmpty(S))
{
if(p)
{
Push(S,p);
p=p->lchild;
}
else
{
Pop(S,p);
visit(p);
p=p->rchild;
}
}
}
//后序遍历
void PostOrder2(BiTree T)
{
InitStack(S);
BiNode *p=T;
BiNode *r=NULL;
while(p||!IsEmpty(S))
{
if(p)
{
Push(S,p);
p=p->lchild;
}
else
{
GetPop(S,p);
if(p->rchild&&p->rchild!=r)
{
p=p->rchild;
}
else
{
Pop(S,p);
visit(p);
r=p;
p=NULL;
}
}
}
}
2.二叉树的层次遍历(从上到下,从左到右)。
//层次遍历(从上到下,从左到右)
void LevelOrder(BiTree T)
{
InitQueue(Q);
BiTree p;
EnQueue(Q,T);
while(!IsEmpty(Q))
{
DeQueue(Q,p);
visit(p);
if(p->lchild!=NULL)
{
EnQueue(Q,p->lchild);
}
if(p->rchild!=NULL)
{
EnQueue(Q,p->rchild);
}
}
}
3.给出二叉树的自下而上,从右到左的层次遍历。
//层次遍历(自下而上,从右到左)
//算法思想:利用原有的层次遍历算法,出队的同时将各结点指针入栈,
//在所有结点入栈后再从栈顶开始依次访问。
void InvertOrder(BiTree T)
{
Stack S;
Queue Q;
if(T!=NULL)
{
InitStack(S);
InitQueue(Q);
EnQueue(Q,T);
while(!IsEmpty(Q))
{
DeQueue(Q,p);
Push(A,p);
if(p->lchild!=NULL)
{
EnQueue(Q,p->lchild);
}
if(p->rchild!=NULL)
{
EnQueue(Q,p->rchild);
}
}
while(!IsEmpty(S))
{
Pop(S,p);
visit(p);
}
}
}
4.编写一个把树B中所有的结点的左、右子树进行交换的函数。
//编写一个把树B中所有的结点的左、右子树进行交换的函数。
void Swap(BiTree T)
{
if(T)
{
Swap(T->lchild);
Swap(T->rchild);
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
}
}
5.编写一个判定二叉树是否是完全二叉树的算法。
//编写一个判定二叉树是否是完全二叉树的算法。
//算法思想:采用层次遍历,将所有结点加入队列(包括空结点)。
//遇到空结点时,查看其后是否有非空结点。若有,则不是完全二叉树。
bool IsComplete(BiTree T)
{
InitQueue(Q);
if(!T)
{
return true;
}
EnQueue(Q,p);
while(!IsEmpty(Q))
{
DeQueue(Q,p);
if(p)
{
EnQueue(Q,p->lchild);
EnQueue(Q,p->rchild);
}
else
{
while(!IsEmpty(Q))
{
DeQueue(Q,p);
if(p)
{
return false;
}
}
}
}
return false;
}
6.计算一棵给定二叉树的所有双分支结点个数。
//计算一棵给定二叉树的所有双分支结点个数
int DsonNodes(BiTree T)
{
if(T==NULL)
return 0;
else if(b->lchild!=NULL&&b->rchild!=NULL)
return DSonNodes(b->lchild)+DSonNodes(b->rchild)+1;
else
return DSonNodes(b->lchild)+DSonNodes(b->rchild);
}
7.统计二叉树的叶结点个数。
//统计二叉树的叶结点个数。
int LeafNode(BiTree T)
{
if(T==NULL)
return 0;
else if(T->lchild==NULL&&T->rchild==NULL)
return 1;
else
return LeafNode(T->lchild) + LeafNode(T->rchild);
}
8.判别两棵树是否相等。
//判别两棵树是否相等。
int CmpTree(BiTree T1,BiTree T2)
{
if(T1==NULL&&T2==NULL)
return 1;
else if(T1==NULL||T2==NULL)
return 0;
if(T1->data!=T2->data)
return 0;
left=right=0;
left=CmpTree(T1->lchild,T2->lchild);
right=CmpTree(T1->rchild,T2->rchild);
return left&&right;
}
9.交换二叉树每个结点的左孩子和右孩子。
//交换二叉树每个结点的左孩子和右孩子。
void ChangeLR(BiTree &T)
{
if(T==NULL) return;
else if(T->lchild==NULL&&T->rchild==NULL)
return;
else
{
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
}
ChangeLR(T->lchild);
ChangeLR(T->rchild);
}
10.设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树)。
//设计二叉树的双序遍历算法
void DoubleTraverse(BiTree T)
{
if(T)
{
cout<data;//访问根结点
DoubleTraverse(T->lchild);//双序遍历左子树
cout<data;//访问根结点
DoubleTraverse(T->rchild);//双序遍历右子树
}
}
11.计算二叉树最大的宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)。
//计算二叉树最大的宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)。
int Width(BiTree T)
{
if(T==NULL)
return 0;
else
{
BiTree Q[];//Q是队列,元素为二叉树结点指针,容量足够大
front=1;//队头指针
rear=1;//队尾指针
last=1;//同层最右结点在队列中的位置
temp=0;//局部宽度
maxw=0;//最大宽度
Q[rear]=T;//根结点入队
while(front<=last)
{
p=Q[front+1];
temp++;//同层元素数加1
if(p->lchild!=NULL)
Q[++rear]=p->lchild;//左子女入队
if(p->rchild!=NULL)
Q[++rear]=p->rchild;//右子女入队
if(front>last)//一层结束
{
last=rear;//last指向下层最右元素
if(temp>maxw) maxw=temp;//更新当前最大宽度
temp=0;
}
}
return maxw;
}
}
12.用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目。
//用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目。
int Level(BiTree T)
{
num=0;
if(T)
{
InitQueue(Q);
EnQueue(Q,T);
while(!QueueEmpty(Q))
{
DeQueue(Q,p);
cout<data;
if(p->lchild&&!p->rchild)||(!p->lchild&&p->rchild)
num++;
if(p->lchild) EnQueue(Q,p->lchild);
if(p->rchild) EnQueue(Q,p->rchild);
}
}
return num;
}
13.求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值。
//求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值。
void LongestPath(BiTree T)
{
BiTree p=T,l[],s[];
top=0;longest=0;
while(p||top>0)
{
while(p)
{
s[++top]=p;
tag[top]=0;
p=p->Lc;
}
if(tag[top]==1)
{
if(!s[top]->Lc&&!s[top]->Rc)
if(top>longest)
{
for(i=1;i<=top;i++) l[i]=s[i];
longest=top;
}
top--;
}
else if(top>0)
{
tag[top]=1;
p=s[top]->Rc;
}
}
}
14.输出二叉树中从每个叶子结点到根结点的路径。
//输出二叉树中从每个叶子结点到根结点的路径。
void AllPath(BiTree T,ElemType path[],int pathlen)
{
if(T!=NULL)
{
if(T->lchild==NULL&&T->rchild==NULL)
{
cout<<" "<data<<"到根结点路径:"<data;
for(i=pathlen-1;i>=0;i--)
cout<data;
pathlen++;
AllPath(T->lchild,path,T->rchild);
AllPath(T->rchild,path,T->rchild);
pathlen--;
}
}
}
15.二叉树高度的三种计算方法。
计算二叉树的高度可以采用几种不同的算法。
算法一:采用后序遍历二叉树,结点最大栈长即为二叉树的高度;
算法二:层次遍历二叉树,最大层次即为二叉树的高度;
算法三:采用递归算法,求二叉树的高度。
//法1:后序遍历,结点最大栈长即为树的高度
int BT_high(BiTree T)
{
BiTree p=T,r=NULL;
int max=0; //树高
stack s;
while(p||!s.empty())
{
if(p!=NULL)
{
s.push(p);
p=p->lchild;
}
else
{
p=s.top();
if(p->rchild!=NULL && p->rchild!=r)
p=p->rchild;
else
{
if(s.size()>max) max=s.size();//最大层次即为高度
r=p;
s.pop();
p=NULL;
}
}
}
return max;
}
//法2:层次遍历,层次即为高度
int BT_level_depth(BiTree T)
{
if(!T) return 0;
BiTree p=T,Q[100];
int front=-1,rear=-1,last=0,level=0;
Q[++rear]=p;
while(frontlchild)
Q[++rear]=p->lchild;
if(p->rchild)
Q[++rear]=p->rchild;
if(front==last)
{
last=rear;
level++; //层次+1
}
}
return level;
}
//法3:递归求树高1
int max1=0;//树高
int BT_depth1(BiTree T,int depth)
{
if(T)
{
if(T->lchild)
BT_depth1(T->lchild,depth+1);
if(T->rchild)
BT_depth1(T->rchild,depth+1);
}
if(depth>max1)
max1=depth;
return depth;
}
//法3:递归求树高2
int Height (BiTree T)
{
if(T==NULL) return 0;
else
{
int m = Height ( T->lchild );
int n = Height(T->rchild);
return (m > n) ? (m+1) : (n+1);
}
}