typedef struct tree{ //定义树(包含线索二叉树)
struct tree *lchild,*rchild;
char data;
int flat;
int ltag,rtag;
}tree,*tree1;
typedef tree1 type;
#include"栈基本操作.cpp"
#include"链队列的基本操作.cpp" //包含文件
void initree(tree1 &t)//初始化树(不带头节点)
{
t=NULL;
}
void recreatetree(tree1 &t)//先序输入递归建立树(ltag和rtag全部赋值为0)
{
char a;
scanf("%c",&a);
if(a=='#')
t=NULL;
else
{
if(!(t=(tree1)malloc(sizeof(tree))))
exit(0);
t->data=a;
t->rtag=0;
t->ltag=0;
recreatetree(t->lchild);
recreatetree(t->rchild);
}
}
//有错
/*
void createtree(tree1 &t,char *a)//利用栈(非递归)建树 (利用二叉树的先序序列输入数字,“#”代表空节点)在递归创建二叉树时,每次创建完当前结点就转向该结点的左子树继续执行,当该
//结点的左子树创建完后,再转向该结点的右子树继续执行
{
tree1 q;
int i=0,j;
int flat=0;
stack s;
initstack(s);//初始化栈
j=strlen(a)-1;
t=(type)malloc(sizeof(tree));//先建立好根节点(不带头节点)
t->data=a[i];
t->ltag=0;
t->rtag=0;
push(t,s);//根节点入栈
i++;
while(j)//循环构成整个树
{
if(flat==0)//如果flat为0,则该接上当前节点的左孩子
{
if(a[i]!='#')//如果有左孩子,则开辟空间,接上左孩子,并且父节点和左孩子依次入栈。(由于父节点还没接右孩子,所以不能出栈)
{
pop(q,s);
q->lchild=(type)malloc(sizeof(tree));
q->lchild->data=a[i];
q->lchild->ltag=0;
q->lchild->rtag=0;
push(q,s);
push(q->lchild,s);
}
else //如果没有左孩子,就该接右孩子,flat置为1
{
pop(q,s);
q->lchild=NULL;
push(q,s);
flat=1;
}
}
else if(flat==1)//flat为1,说明该接右孩子
{
pop(q,s);
if(a[i]!='#')//如果有右孩子,则开辟空间接上右孩子,新的右孩子入栈
{
q->rchild=(type)malloc(sizeof(tree));
q->rchild->data=a[i];
q->lchild->ltag=0;
q->lchild->rtag=0;
push(q->rchild,s);
flat=0; //对新的右孩子下次该接左孩子,flat置为0
}
else //如果没有右孩子,说明该返回至上一节点接右孩子,所以flat置为1
{
q->rchild=NULL;
flat=1;
}
}
j--;
i++;//处理下一个输入的数字
}
}
*/
void midthreading(tree1 &head,tree1 &t)//中序线索化二叉树(带头节点)(已经建立好的树,为他建立头节点,并且线索化)
{
stack s;
initstack(s);
tree1 pre;
if(t==NULL)
exit(0);
head=(tree1)malloc(sizeof(tree));//建立头节点
head->lchild=t;//规定左孩子指向根节点
head->ltag=0;
head->rtag=1; //规定
pre=head;
pre->rchild=head;//右孩子回指
while(t||!empty(s))
{
if(t)
{
push(t,s);
t=t->lchild;
}
else
{
pop(t,s);
//访问操作
if(!t->lchild)//左孩子前驱线索化
{
t->lchild=pre;
t->ltag=1;
}
if(!pre->rchild)//上一个访问节点的后继线索化
{
pre->rchild=t;
pre->rtag=1;
}
pre=t;
t=t->rchild;
}
}
pre->rchild=head;
pre->rtag=1;
head->rchild=pre;//最后头尾相连
}
//有错(先序遍历必须先序线索化二叉树啊啊啊)
/*
void threadorderpre(tree1 head)//双向线索链表遍历(先序遍历)
{
tree1 t;
t=head->lchild; //t指向头节点
while(t!=head)
{
printf("%c ",t->data);
while(t->ltag==0)//访问左子树
{
printf("%c ",t->lchild->data);
t=t->lchild;
}
if(t->rtag==1)
{
while(t->rtag==1&&t->rchild!=head)//访问右线索
{
printf("%c ",t->rchild->data);
t=t->rchild;
}
if(t->ltag==0)
t=t->lchild;
else
t=t->rchild;
}
else
t=t->rchild;
}
}
*/
void threadordermid(tree1 head)//双向线索链表遍历(中序遍历)
{
tree1 p;
p=head->lchild;
while(p!=head)
{
while(p->ltag==0)
p=p->lchild;
printf("%c ",p->data);
while(p->rtag==1&&p->rchild!=head)
{
p=p->rchild;
printf("%c ",p->data);
}
p=p->rchild;
}
}
void preorder(tree1 &t)//先序遍历树
{
stack s;
initstack(s);//初始化栈
if(t==NULL)
exit(0);
while(t||!empty(s))
{
if(t)
{
printf("%c ",t->data);
push(t,s);
t=t->lchild;
}
else
{
pop(t,s);
t=t->rchild;
}
}
}
void midorder(tree1 &t)//中序遍历树
{
stack s;
initstack(s);//初始化树
if(t==NULL)
exit(0);
while(t||!empty(s))
{
if(t)
{
push(t,s);
t=t->lchild;
}
else
{
pop(t,s);
printf("%c ",t->data);
t=t->rchild;
}
}
}
void behorder(tree1 &t)//后序遍历树
{
stack s;
initstack(s);//初始化树
if(t==NULL)
exit(0);
while(t||!empty(s))
{
if(t)
{
t->flat=1;
push(t,s);
t=t->lchild;
}
else
{
pop(t,s);
if(t->flat==0||t->rchild==NULL)
{
printf("%c ",t->data);
t=NULL;
}
else
{
t->flat=0;
push(t,s);
t=t->rchild;
}
}
}
}
void deeptree(tree1 t)//给每一个节点写入层序号
{
stack s;
initstack(s);
tree1 l=t;
int i=0;
while(l||!empty(s))
{
if(l)
{
push(l,s);
l->data=i;
l=l->lchild;
}
else
{
pop(l,s);
i=l->data+1;
l=l->rchild;
l->data=i;
}
i++;
}
}
void floororder(tree1 t)//借助队列实现层序遍历
{
qu q;
initqueue(q);
tree1 p;
if(t==NULL)
exit(0);
enqueue(t,q);
while(!emptyqu(q))
{
dequeue(p,q);
printf("%c ",p->data);
if(p->lchild)
enqueue(p->lchild,q);
if(p->rchild)
enqueue(p->rchild,q);
}
}
/*
void preorder(tree1 t)//先序遍历树(非递归)
{
stack s;
initstack(s);//初始化树
if(t==NULL)
exit(0);
tree1 l;
l=t;
printf("%c ",l->data);//先输出根节点
while(!emtpy(s))
{
l=gettop(s); //每次先取栈顶元素出栈
if(l->lchild!=NULL)//如果左孩子非空,则左孩子入栈,打印左孩子
{
push(l,s);
push(l->lchild,s);
printf("%c ",l->lchild->data);
}
else if(l->rchild!=NULL)//如果左孩子为空,右孩子非空。则右孩子入栈,打印右孩子。说明父节点的两个孩子已遍历,则父节点不再入栈
{
push(l->rchild,s);
printf("%c ",l->rchild->data);
}
else //如果两个孩子都为空,则父节点的父节点的左孩子置空,便于下一次遍历的时候,直接访问父节点的父节点的右孩子
{
if(!empty(s)) //这里处理特殊情况,即如果此节点为全树遍历后的最后节点则取出后不再处理。
{
l=gettop(s);
l->lchild=NULL;
push((l,s);
}
}
}
void midorder(tree1 &t)//中序遍历树(非递归)
{
stack s;
initstack(s);
if(t==NULL)
exit(0);
tree1 l;
l=t;
push(l,s);
while(!empty(s))
{
while(l->lchild)
{
push(l->lchild,s);
=l->lchild;
}
l=gettop(s);
printf("%c ",l->data);
if(l->rchild)
push(l->rchild,s);
else
{
l=gettop(s);
l->lchild==NULL;
push(l,s);
}
}
}
void behorder(tree1 &t)//后序遍历树(非递归)
{
stack s;
initstack(s);
int flat=0;
if(t==NULL)
exit(0);
tree1 l;
l=t;
while(!emtpy(s))
{
while(l->lchild!=NULL)
{
push(l->lchild,s);
flat=0;
}
if(l->rchild!=NULL)
{
push(l->lchild,s)
l=l->rchild;
flat=1;
}
else
{
l=gettop(s);
printf("%c ",l->data);
l=gettop(s);
if(flat==0)
{
l->lchild=NULL;
push(l,s);
}
else
printf("%c ",l->data);
push(l,s);
}
}
}
*/
树的非递归操作
最新推荐文章于 2022-05-09 11:40:33 发布