树的非递归操作

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);
		}
	}
}
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值