09.设树B是一棵采用链式结构存储的二叉树,编写一个把树B中所有结点的左右子树进行交换的函数。
- 算法思想:采用递归算法实现交换二叉树的左右子树,首先交换b结点的左孩子的左右子树,然后交换右孩子的左右子树,最后交换b结点的左右孩子,当结点为空时递归结束(后序遍历思想)。
void swap(BiTree b) {
if(b) {
swap(b->lchild);
swap(b->rchild);
temp=b->lchild;
b->lchild=b->rchild;
b->rchild=temp;
}
}
10.求先序遍历序列中第k个结点的值。
- 算法思想:设置一个全局变量i(初值为1)来表示先序遍历时,当前访问的第几个结点。先序遍历二叉树,当二叉树为空时,返回#;当k==i时,返回b->data;当k不为i时,递归地依次在左、右子树查找。
int i=1;
ElemType preNode(BiTree b,int k) {
if(b==NULL)
return '#';
if(i==k)
return b->data;
i++;
ch=preNode(b->lchild,k);
if(ch!='#')
return ch;
ch=preNode(b->rchild,k);
return ch;
}
11.对于树中每个元素值为x的结点,删除以它为根的子树,并释放相应的空间。
- 算法思想:删除值为x的结点,意味着将其父结点的左(右)子女指针置空,用层次遍历易找到其父结点。要删除每个元素值为x的结点,因此需要遍历整棵树。而想要释放相应的空间,首先需要删除其左右子树,再释放值为x的根结点的空间,可采用后序遍历。
- 后序遍历,删除结点的左右子树。
- 层次遍历,查找x的父结点,释放空间。
- 遍历整棵树,找到所有元素值为x的结点·。
void deleteXTree(BiTree &b) {
if(b) {
deleteXTree(b->lchild);
deleteXTree(b->rchild);
free(b);
}
}
void search(BiTree b,ElemType x) {
BiTree Q[];
if(b) {
if(b->data==x) {
deleteXTree(b);
exit(0);
}
InitQueue(Q);
EnQueue(Q,b);
while(!IsEmpty(Q)) {
DeQueue(Q,p);
if(p->lchild) {
if(p->lchild->data==x) {
deleteXTree(p->lchild);
} else
EnQueue(Q,p->lchild);
} else
EnQueue(Q,p->rchild);
}
}
}
12.在二叉树中查找值为x的结点,打印值为x的结点的所有祖先。
- 采用非递归后序遍历(先出栈再访问),最后访问根结点,访问到x的结点时,栈中所有元素均为该结点的祖先,依次打印即可。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/2bbb6b48720bc9944d43f00320dd598e.png)
typedef struct {
BiTree t;
int tag;
} stack;
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!=NULL&&bt->data==x) {
printf("所查结点的所有祖先结点的值为:\n");
for(i=1; i<=top; i++)
printf("%d",s[i].t->data);
exit(1);
}
while(top!=0&&s[top].tag=1)
top--;
if(top!=0) {
s[top].tag=1;
bt=s[top].t->rchild;
}
}
}
13.设一棵二叉树的结点结构为(LLINK,INFO,RLINK),ROOT为指向该二叉树根结点的指针,p和q分别指向该二叉树中任意两个结点的指针,编写算法ANCESTOR(ROOT,p,q,r),找到p和q的最近公共祖先结点r。
14.求非空二叉树的宽度。
- 采用层次遍历求出所有结点的层次,并将所有结点和对应的层次放在一个队列中。然后通过扫描队列求出各层的结点数,最大的层结点数即为二叉树的宽度。
typedef struct {
BiTree data[MaxSize];
int level[MaxSize];
int front,rear;
} Qu;
int BTWidth(BiTree b) {
BiTree p;
int k,max,i,n;
Qu.front=Qu.rear=-1;
Qu.data[++Qu.rear]=b;
Qu.level[Qu.rear]=1;
while(Qu.front<Qu.rear) {
Qu.front++;
p=Qu.data[Qu.front];
k=Qu.level[Qu.front];
if(p->lchild!=NULL) {
Qu.data[++Qu.rear]=p->lchild;
Qu.level[Qu.rear]=k+1;
}
if(p->rchild!=NULL) {
Qu.data[++Qu.rear]=p->rchild;
Qu.level[Qu.rear]=k+1;
}
}
k=1;max=0;i=0;
while(i<=Qu.rear) {
n=0;
while(i<=Qu.rear&&Qu.level[i]==k) {
n++;
i++;
}
k=Qu.level[i];
if(n>max)
max=n;
}
return max;
}
- 按照层次遍历的思路,我们将根结点入队,然后出队,temp表示二叉树每层的结点个数,每次出队一个元素temp++,然后把根节点的左右孩子入队,判断front指针是否大于last(每层结点最后元素的位置),即判断这一层的元素是否全部出队(全部出队则front与上一次的rear相等,即大于last(rear-1)),如果全部出队则更新last,max(最大宽度)和temp,最后递归所有元素然后返回最大宽度max。
int WidthBiTree(BiTree T) {
if(!T) return 0;
Queue Q;
int temp=0,last=0,max=0;
InitQueue(Q);
EnQueue(Q,T);
while(Q.front <= last) {
DeQueue(Q, T);
temp++;
if (e->lchild != NULL)
EnQueue(Q, T->lchild);
if (e->rchild != NULL)
EnQueue(Q, T->rchild);
if (Q.front > last) {
last = Q.rear-1;
max = max > temp ? max : temp;
temp = 0;
}
}
return max;
}
15.一棵满二叉树,已知先序序列为pre,求其后序序列post。
- 相对于满二叉树而言,任意一个结点的左右子树均含有相等的结点数。同时,先序序列的第一个结点作为后序序列的最后一个结点。
void PreToPost (ElemType pre[],int l1,int h1,ElemType post[],int l2,int h2) {
int half;
if(h1>=l1) {
post[h2]=pre[l1];
half=(h1-l1)/2;
PreToPost (pre,l1+1,l1+half,post,l2,l2+half-1);
PreToPost (pre,l1+1+half,h1,post,l2+half,h2-1);
}
}
16.设计一个算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为head。二叉树按二叉链表的方式存储,链接时用叶结点的右指针域来存放单链表的指针。
- 采用中序递归遍历的思想。设置前驱结点指针pre,初始为空。第一个叶结点由指针head指向,遍历到叶结点时,将前驱的rchild指针指向它,最后一个叶结点的rchild为空。
- 算法的时间复杂度为O(n),空间复杂度为O(n)。
LinkedList head,pre=NULL;
LinkedList InOrder(BiTree b) {
if(b) {
InOrder(b->lchild);
if(b->lchild==NULL&&b->rchild==NULL) {
if(pre==NULL) {
head=b;
pre=b;
} else {
pre->rchild=b;
pre=b;
}
}
InOrder(b->rchild);
pre->rchild=NULL;
}
return head;
}
18.写出在中序线索二叉树里查找指定结点在后序的前驱结点的算法。
- 在后序序列中,若结点p有右子女,则右子女是其前驱,若无有子女而有左子女,则左子女是其前驱。若结点p左右子女均无,设其中序左线索指向某祖先结点f(p是f右子树中按中序遍历的第一个结点),若f有左子女,则左子女是其前驱;若f无左子女,则顺其前驱找双亲的双亲,一直找到双亲有左子女(这时左子女是其前驱)。若p是中序遍历的第一个结点,则结点p在中序和后序下均无前驱。
BiThrTree InPostPre(BiThrTree t,BiThrTree p) {
BiThrTree q;
if(p->rtag==0)
q=p->rchild;
else if(p->ltag==0)
q=p->lchild;
else if(p->lchild==NULL)
q=NULL;
else {
while(p->ltag==1&&p->lchild!=NULL)
q=p->lchild;
if(p->ltag==0)
q=p->lchild;
else
q=NULL;
}
return q;
}