实验一 后序非递归遍历
top=-1
typedef struct satck
{
bintree data[100];
int tag[100];
int top;
}seqstack;
void preorder1(bintreet)
{
seqsatck s;
init(&t);
while(t||s.top!=-1)
{
if(t){
push(&s,t);
s.tag[s.top]=0;
t=t->lchild;
}
else{
if(s.tag[s.top]==1)
{
t=pop(&s);
printf("%c",t->data);
t->NULL;
}
else{
t=s.data[s.top];
s.tag[s.top]=1;
t=t->rchild;
}
}
}
}
top=0
void preorder1(bintreet)
{
seqsatck s;
s.top=0;
while(t||s.top!=-1)
{
if(t){
s.data[s.top]=t
s.tag[s.top]=0;
s.top++;
t=t->lchild;
}
else{
if(s.tag[s.top-1]==1)
{
s.top--;
t=s.data[s.top];
printf("%c",t->data);
t->NULL;
}
else{
t=s.data[s.top-1];
s.tag[s.top-1]=1;
t=t->rchild;
}
}
}
}
总结
定义一个栈并初始化,在指针不为空或栈顶不为空的情况下,分为子树不为空和子树为空。如果子树不为空,先进栈使top=0,然后将栈顶标识改为0,最后指向左子树。如果子树为空也要分两种情况。如果右子树访问完就出栈在打印,最后将指针赋值为空,否则将栈顶标识改为1,并指向右子树
实验二 前序非递归遍历
void preorder1(bintreet)
{
seqsatck s;
init(&s);
while(t||s.top!=-1)
{
if(t){
printf("%c",t->data);
push(&s,t);
t=t->lchild;
}
else{
t=pop(&s);
t=t->rchild;
}
}
}
总结
定义栈并初始化,在指针不为空或栈顶不为空的情况下,若子树不为空,先打印,再进栈,接着指向左子树,否则出栈指向右子树
实验三 中序非递归遍历
void preorder1(bintreet)
{
seqsatck s;
init(&s);
while(t||s.top!=-1)
{
if(t){
push(&s,t);
t=t->lchild;
}
else{
t=pop(&s);
printf("%c",t->data);
t=t->rchild;
}
}
}
总结
与前序区别在于进入栈前不打印,出栈才打印
实验四 二叉树的层次遍历
#include "bintree.h"
char *a="ABC##D#E##F##";
void levelbintree(bintree t)
{
bintree quene[100];
int f=0,r=1;
if(t)
{
quene[0]=t;
while(f<r)
{
t=quene[f++];
printf("%c",t->data);
if(t->lchild)
{
quene[r++]=t->lchild;
}
if(t->rchild)
{
quene[r++]=t->rchild;
}
}
}
}
int main()
{ bintree t;
t=creatbintree();
printf("二叉树的层次序列为:\n");
levelbintree(t);
return 0;
}
总结
当树不为空,前面数组小标小于后面时循环,r记录叶子结点,最后遍历可以分别遍历每一层的左右结点
实验五 返回前序遍历下的最后一个结点地址和后序遍历下的第一个结点地址
#include "bintree.h"
char *a="ABC##D##EF#G###";
bintree prelast(bintree t)
{
if(!t)
{
return t;
}
else if(t->lchild==NULL&&t->rchild==NULL)
{
return t;
}
else
{
if(t->rchild)
{
prelast(t->rchild);
}
else
{
prelast(t->lchild);
}
}
}
bintree postfirst(bintree t)
{
bintree p;
p=t;
if(p)
{
while(p->rchild||p->lchild)
{
if(p->lchild)
{
p=p->lchild;
}
else if(p->rchild)
{
p=p->rchild;
}
}
}
return p;
}
int main()
{ bintree t,p,q;
t=creatbintree();
p=prelast(t);
q=postfirst(t);
if (t!=NULL)
{ printf("前序遍历最后一个结点为:%c\n",p->data);
printf("后序遍历第一个结点为:%c\n",q->data);
}
else printf("二叉树为空!");
return 0;
}
总结
- 递归遍历先判断树是否为空,是否为叶子结点,因为找最后一个结点地址,所以 先看是否有左结点,否则再去找右结点
- 非递归遍历在树不空的基础上看左右子树是否都存在,因为是后序第一个结点,所以先往左找,没有再往右找。当都不存在就是找到了
实验六 链式存储二叉树,求值为x的结点在二叉树中的层次
递归算法
#include "bintree.h"
char *a="ABC##D##EF#G###";
int Depth1(bintree t,char x)
{
if(!t) return -1;
if(t->data==x) return 1;
int hl=Depth1(t->lchild,x);
int hr=Depth1(t->rchild,x);
if(hl!=-1) return hl+1;
if(hr!=-1) return hr+1;
return -1;
}
int main()
{ bintree root;
char x;
int k=0;
root=creatbintree();
printf("请输入树中的1个结点值:\n");
scanf("%c",&x);
k=Depth1(root,x);
printf("%c结点的层次为%d\n",x,k);
}
总结
只要为空就返回-1,然后在左右子树递归寻找,若找到返回的就不是-1,那么这个时候不停+1得到最终层数
非递归算法
#include "bintree.h"
char *a="ABC##D##EF#G###";
int Depth2(bintree t,char x)
{
seqstack s;
int tag[100];
while(t||s.top!=-1)
{
if(t)
{
push(&s,t);
s.tag[s.top]=0;
t=t->lchild;
}
else
{
if(s.tag[s.top]==1)
{
t=pop(&s);
if(t->data==x)
{
return s.top+2;
}
t=NULL;
}
else
{
t=s.data[s.top];
s.tag[s.top]=1;
t=t->rchild;
}
}
}
}
int main()
{ bintree root;
char x;
int k=0;
root=creatbintree();
printf("请输入树中的1个结点值:\n");
scanf("%c",&x);
k=Depth2(root,x);
printf("%c结点的层次为%d\n",x,k);
}
总结
后序非递归遍历中,在出栈的时候判断是否为选的结点,如果是,将栈顶+2就是层数。 出栈后本来应该是栈减了一位,所以先+1,又因为top一开始定义-1,所以+2
实验七-输出叶子结点
void leaf(bintreet)
{
seqsatck s;
init(&t);
while(t||s.top!=-1)
{
if(t){
if(!t->lchild&&!t->rchild)
{
printf("%c",t->data);
}
push(&s,t);
s.tag[s.top]=0;
t=t->lchild;
}
else{
if(s.tag[s.top]==1)
{
t=pop(&s);
printf("%c",t->data);
t->NULL;
}
else{
t=s.data[s.top];
s.tag[s.top]=1;
t=t->rchild;
}
}
}
}
总结
在后序非递归遍历中只用在入栈前加个条件判断是否左右指针都为空,然后输出,则为叶子结点
实验八-穿线二叉树
创建并进行线索化
typedef char datatype;
typedef struct node{
datatype data;
int ltag,rlag;
struct node *lchild,*rchild;
}bintnode;
typedef bintnode *binthrtree;
binthrtree pre=NULL;
binthrtree createbinthrtree()
{
char ch;
binthrtree t;
if((ch=getchar())=='#')
t=NULL;
else{
t=(bintnode *)malloc(sizeof(bintnode));
t->data=ch;
t->lchild=createbinthrtree();
t->rchild=createbinthrtree();
}
return t;
}
void inthreading(binthrtree *p)
{
if(*p)
{
inthreading(&((*p)->lchild));
(*p)->ltag=((*p)->lchild)?0:1;
(*p)->rtag=((*p)->rchild)?0:1;
if(pre)
{
if(pre->rtag==1) pre->rchild=*p;
if((*p)->ltag==1) (*p)->lchild=pre;
}
inthreading(&((*p)->rchild));
}
}
找中序首点
void inthrtree(binthtree p)
{
if(p)
{
while(p->ltag==0)
p=p->lchild;
}
}
总结
从根结点出发,沿着左指针不断往下走,直到左指针为空,到达“”最左下“的结点即可
找中序后继结点
binthtree insuccnode(binthrtree p)
{
binthrtree q;
if(p->rtag==1) return p->rchild;
else{
q=p->rchild;
while(q->ltag==0)
{
q=q->lchild;
}
return q;
}
}
总结
找后继结点分两种情况,一种是右标识为1,后面结点就是后继结点,另一种是右标识不为0,说明还有右子树,那就遍历右子树找到其首点,这个点才是后继结点
-
图1 -
图2
中序遍历中序穿线二叉树
void inthrtree(binthtree p)
{
if(p)
{
while(p->ltag==0)
p=p->lchild;
do
{
printf("%c",p->data);
p=insuccnode(p);
}while(p)
}
}
总结
先找到首点,打印后递归输出后继结点,实现遍历
穿线二叉树完整过程
typedef char datatype;
typedef struct node{
datatype data;
int ltag,rlag;
struct node *lchild,*rchild;
}bintnode;
typedef bintnode *binthrtree;
binthrtree pre=NULL;
binthrtree createbinthrtree()
{
char ch;
binthrtree t;
if((ch=getchar())=='#')
t=NULL;
else{
t=(bintnode *)malloc(sizeof(bintnode));
t->data=ch;
t->lchild=createbinthrtree();
t->rchild=createbinthrtree();
}
return t;
}
void inthreading(binthrtree *p)
{
if(*p)
{
inthreading(&((*p)->lchild));
(*p)->ltag=((*p)->lchild)?0:1;
(*p)->rtag=((*p)->rchild)?0:1;
if(pre)
{
if(pre->rtag==1) pre->rchild=*p;
if((*p)->ltag==1) (*p)->lchild=pre;
}
inthreading(&((*p)->rchild));
}
}
binthtree insuccnode(binthrtree p)
{
binthrtree q;
if(p->rtag==1) return p->rchild;
else{
q=p->rchild;
while(q->ltag==0)
{
q=q->lchild;
}
return q;
}
}
void inthrtree(binthtree p)
{
if(p)
{
while(p->ltag==0)
p=p->lchild;
do
{
printf("%c",p->data);
p=insuccnode(p);
}while(p)
}
}
int main()
{
bintree t;
t=creatbintree();
printf("穿线二叉树的中序遍历为:\n");
inthrtree(t);
return 0
}
实验九 所有结点的左、右子女互换
#include "bintree.h"
char *a="ABC##D##EF#G###";
void change(bintree t)
{
bintree tmp;
if(t)
{
tmp=t->lchild;
t->lchild=t->rchild;
t->rchild=tmp;
change(t->lchild);
change(t->rchild);
}
}
int main()
{ bintree root;
root=creatbintree();
change(root);
preorder(root);
}
总结
在树存在的情况下先将左右结点互换,然后再递归遍历左右子树
实验十 层次遍历寻找树的最大宽度
#include "bintree.h"
char *a="ABD##EH##I##CF##G##";
typedef struct{
bintree qu[N];
int level[N];
int f,r;
}seqQuene;
void push1(seqQuene* q,bintree x)
{
q->qu[q->r++]=x;
}
bintree pop1(seqQuene* q)
{
return q->qu[q->f];
}
int wepth(bintree t)
{
int max=0;
seqQuene q;
q.f=q.r=NULL;
if(t)
{
push1(&q,t);
}
while(q.f<q.r)
{
int tm=q.r;
int stmax=0;
for(q.f;q.f<tm;q.f++)
{
bintree tmp=pop1(&q);
if(tmp->lchild)
{
push1(&q,tmp->rchild);
}
stmax++;
}
if(stmax>max)
{
max=stmax;
}
q.f=tm;
}
return max;
}
int main()
{ bintree t;
t=creatbintree();
printf("二叉树的度数为:\n");
wedth(t);
return 0;
}
bintree.h
#include <stdio.h>
#include <stdlib.h>
#define N 100
extern char *a;
typedef struct node
{
char data;
struct node *lchild,*rchild;
}binnode;
typedef binnode *bintree;
bintree creatbintree()
{
char ch=*a++;
bintree t;
if (ch=='#') t=NULL;
else
{ t=(bintree)malloc(sizeof(binnode));
t->data=ch;
t->lchild=creatbintree();
t->rchild=creatbintree();
}
return t;
}
void preorder(bintree t)
{
if (t)
{
printf("%c",t->data);
preorder(t->lchild);
preorder(t->rchild);
}
}
void postorder(bintree t)
{
if (t)
{
postorder(t->lchild);
postorder(t->rchild);
printf("%c",t->data);
}
}
typedef struct
{
bintree data[N];
int top;
int tag[N];
}seqstack;
void init(seqstack *s)
{
s->top=-1;
}
int empty(seqstack *s)
{
if (s->top>-1) return 0;
else return 1;
}
int full(seqstack *s)
{
if (s->top==N-1) return 1;
else return 0;
}
void push(seqstack *s ,bintree x)
{
if (!full(s))
s->data[++s->top]=x;
}
bintree pop(seqstack *s)
{
if (!empty(s))
return s->data[s->top--];
}
|