void InThread(ThreadTree &P,ThreadTree &pre)
{
if(p!=null)
{
InThread(p->lchild,pre);
if(lchild==null)
{
p->lchild=pre;
p->ltag=1;
}
if(pre!=null&&pre->rchild==null)
{
pre->rchild=p;
pre->rtag=1;
}
pre=p;
InThread(p->rchild,pre);
}
}
void CreatInTread(ThreadTree T)
{
ThreadTree pre=null;
if(T!=null)
{
InThread(T,pre);
pre->rchild=null;
pre->rtag=1;
}
}
ElemType Comm_Ancestor(SqTree T,int i,int j)
{
if(T[i]!='#'&&T[j]!='#')
{
while(i!=j)
{
if(i>j)
i=i/2;
else
j=j/2;
}
return T[i];
}
}
int Btdepth(BiTree T)
{
if(!T)
return 0;
int front=-1,rear=-1;
int last=0,level=0;
BiTree Q[MaxSize];
Q[++rear]=T;
BiTree P;
while(frontlchild)
Q[++rear]=p->lchild;
if(p->rchild)
Q[++rear]=p->rchild;
if(front==last)
{
level++;
last=rear;
}
return level;
}
}
解题思想:
根据完全二叉树的定义,具有n个结点的完全二叉树与满二叉树中编号1–n的结点一一对应。
采用层次遍历的算法,将所有结点加入队列(包括空结点),当遇到空结点时,查看其后是否有非空结点,若有,则二叉树不是完全二叉树。
bool IsComplete(BiTree &T)
{
InitQueue(Q);
if(!T) 空树为满二叉树
return 1;
EnQueue(Q,T);
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 0;
}
}
return 1;
}
}
int DsonNodes(BiTree &T)
{
if(T==null)
return 0;
else if(T->lchild!=null&&T->rchild!=null)
return DsonNodes(T->lchild)+DsonNodes(T->rchild)+1;
else
return DsonNodes(T->lchild)+DsonNodes(T->rchild);
}
解题思路:
设置一个全局变量i记录已访问过的结点序号,其初值是根结点在先序序列中的序号,即为1,。
当二叉树为空时返回特殊字符‘#’。
当i=k时,小时豪到满足条件的结点。返回b->data;
当i!=k时,则递归地在左子树中查找,若找到了则返回该值,否则继续递归地在右子树中查找,并返回其结果
int i=1;
ElemType PreNode(BiTree b,int k)
{
if(b==null)
return '#';
if(i==k)
return b->data;
ch=PreNode(b->lchild,k);
if(ch!='#')
return ch;
ch=PreNode(b->rchild,k);
return ch;
}
算法思想:采用非递归后序遍历,最后访问根节点,当访问之为x的结点时,栈中所有元素均为该结点的祖先,依次出栈打印即可
typedef struct
{
BiTree t;
int tag;
}stack tag=0表示左子树被访问,tag=1时表示右子女被访问
void search(BiTree bt,ElemType x)
{
stack s[];
top=0;
while(bt!=null||top>0)
{
while(bt!=null&&bt->data!=x)
{
s[++top].t=bt;
s[top].tag=0;
bt=bt->lchild;
}
if(bt->data==x)
{
printf("所查结点的所有祖先结点的值为:");
for(int i=1;i<=top;i++)
printf("%d",s[i].t->data);
exit(0);
}
while(top!=0&&s[top].tag==1)
top--;
if(top!=0)
{
s[top].tag=1;
bt=s[top].t->rchild;
}
}
}
算法思想:
采用后续非递归遍历算法,栈中存放二叉树结点的指针,当访问到某结点时,栈中所有元素均为该结点的祖先,后续遍历必然先遍历到结点p,栈中元素均为p的忑结点,先将栈复制到另一块辅助栈中去,继续遍历到结点q时,将栈中元素从栈顶开始逐个到辅助栈中去匹配,第一个匹配到的元素即结点p与q的公共最近祖先。
typedef struct
{
BiTree t;
int tag; tag=0左子女被访问过,tag=1时,右子女被访问过
}srack;
stack s1[],s2[];
BiTree Ancestor(BiTree ROOT,BiTNode *p,BiTNode *q)
{
top=0;
bt=ROOT;
while(bt!=null&&bt!=p&&bt!=q)
{
while(bt!=null)
{
s[++top].t=bt;
s[top].tag=0;
bt=bt->lchild;
}
while(top!=0&&s[top].tag==1)
{
if(s[top].t==p)
{
for(i=1;i<=top;i++)
{
s1[i]=s[i];
top1=top;
}
if(s[top].t==q)
{
for(i=top;i>0;i--)
for(j=top1;j>0;j--)
if(s1[j].t==s[i].t)
return s[i].t;
}
top--;
}
if(top!=0)
{
s[top].tag=1;
bt=s[top].t->rchild;
}
}
}
}
采用层次遍历,求出所有结点的层次,并将所有结点与对应的层次放在一个队列中,然后通过扫描队列求出各层的结点总数即二叉树的宽度
typedef struct
{
BiTree data[MaxSize]; 结点
int level[MaxSize]; 保存data中相同下表的结点层
int front,rear;
}Qu;
int BTWidth(BiTree b)
{
BiTree p;
int i,k,max,n;
Qu.front=Qu.rear=-1;
Qu.rear++;
Qu.data[Qu.rear]=b;
Qu.level[Qu.rear]=1;
while(QU.frontlchild!=null)
{
Qu.rear++;
Qu.data[Qu.rear]=p->lchild;
Qu.level[Qu.rear]=k+1;
}
if(p->rchild!=null)
{
Qu.rear++;
Qu.data[Qu.rear]=p->rchild;
Qu.level[Qu.rear]=k+1;
}
max=0;
i=0;k=1;
while(i<=Qu.rear)
{
n=0;
while(i<=Qu.rear&&Qu.level[i]==k)
{
i++;n++;
}
k=Qu.level[i];
if(n>max)
max=n;
}
return max;
}
}
算法思想:
通常我们所使用的先序,中序和后续遍历对于叶结点的访问都从左到右排序,这里我们采用中序遍历递归算法。
设前驱结点指针pre,初始为空,第一个叶结点由指针head指向,遍历到叶结点时,就将它的前驱rchild指向它,最后一个叶结点rchild为空
LinkList head,pre=null;
LinkList InOrder(BiTree bt)
{
if(bt)
{
InOrder(br->lchild);
if(bt->lchild==null&&bt->rchild==null)
{
if(pre==null)
{
head=bt;
pre=bt;
}
else
{
pre->rchild=bt;
pre=bt;
}
InOrder(bt->rchild);
pre->rchild=null;
}
return head;
}
}
int similar(BiTree T1,BiTree T2)
{
int lefts,rights;
if(T1==NULL&&t2==NULL)
return 1;
else if(T1==NULL||T2==NULL)
return 0;
else
{
lefts=similar(T1->lchild,T2->lchild)
rights=similar(T1->rchild,T2->rchild);
return lefts&&rights;
}
}