二叉树非递归遍历

二叉树非递归遍历:

#include"btree.cpp"文件链接:https://blog.csdn.net/qq_16261421/article/details/105920539

总体代码如下:

#include "btree.cpp"

//先序非递归遍历算法
void PreOrder1(BTNode *b)	
{
	BTNode *St[MaxSize],*p;
	int top=-1;
	if (b!=NULL) { 
		//根结点进栈  
		top++;						
		St[top]=b;
		//栈不为空时循环
		while (top>-1){
			p=St[top];
			//退栈并访问该结点			
			top--;
			printf("%c ",p->data);
			if (p->rchild!=NULL){
				top++;
               	St[top]=p->rchild;
			}
			if (p->lchild!=NULL){
				top++;
               	St[top]=p->lchild;
			}
		}
		printf("\n");
	}
}

//中序非递归遍历算法
void InOrder1(BTNode *b)	
{
	BTNode *St[MaxSize],*p;
	int top=-1;
	if (b!=NULL){
		p=b;
		//处理*b结点的左子树
		while (top>-1 || p!=NULL){
			//扫描*p的所有左结点并进栈
			while (p!=NULL){
				top++;
				St[top]=p;
				p=p->lchild;
			}
			//执行到此处时,栈顶元素没有左孩子或左子树均已访问过
			if (top>-1){	
				p=St[top];				//出栈*p结点
				top--;
				printf("%c ",p->data);	
				p=p->rchild;			//扫描*p的右孩子结点
			}
		}
		printf("\n");
	}
}

//后序非递归遍历算法
void PostOrder1(BTNode *b)	
{
	BTNode *St[MaxSize];
	BTNode *p;
	int flag,top=-1;				//栈指针置初值
	if (b!=NULL){
		do{
			while (b!=NULL)		{
				//将*b的所有左结点进栈
				top++;
				St[top]=b;
				b=b->lchild;
			}
			//执行到此处时,栈顶元素没有左孩子或左子树均已访问过
			p=NULL;					//p指向栈顶结点的前一个已访问的结点
			flag=1;					//设置b的访问标记为已访问过
			while (top!=-1 && flag){
				b=St[top];			//取出当前的栈顶元素
				if (b->rchild==p)	{	
					printf("%c ",b->data);	//访问*b结点
					top--;
					p=b;			//p指向刚访问过的结点
				}
				else{	
					b=b->rchild;	//b指向右孩子结点
					flag=0;			//设置未被访问的标记
				}
			}
		} while (top!=-1);
		printf("\n");
	} 
}

int main()
{
	BTNode *b;
	CreateBTNode(b,"A(B(D(,G)),C(E,F))");
	printf("b:");
	DispBTNode(b);
	printf("\n");
	printf("先序遍历序列:");
	PreOrder1(b);
	printf("中序遍历序列:");
	InOrder1(b);
	printf("后序遍历序列:");
	PostOrder1(b);
	return 0;
}

 

先序遍历非递归算法:

算法思想:

      用栈来消除递归,先将根节点进栈,在栈不空时候循环:出栈p,访问*p节点,若其右孩子节点不空,将右孩子节点进入堆栈,若其左孩子节点不空,将其左孩子节点进入堆栈。算法如下:

void PreOrder1(BTNode *b)	
{
	BTNode *St[MaxSize],*p;
	int top=-1;
	if (b!=NULL) { 
		//根结点进栈  
		top++;						
		St[top]=b;
		//栈不为空时循环
		while (top>-1){
			p=St[top];
			//退栈并访问该结点			
			top--;
			printf("%c ",p->data);
			if (p->rchild!=NULL){
				top++;
               	St[top]=p->rchild;
			}
			if (p->lchild!=NULL){
				top++;
               	St[top]=p->lchild;
			}
		}
		printf("\n");
	}
}

 

中序遍历非递归算法:

算法思想:

      由中序遍历的过程可知,中序序列的开始节点是一颗二叉树的最左下节点。因此,我们的基本思路是,先找到二叉树的开始节点,并且访问它,再处理右子树。

     用指针指向当前要处理的节点,先扫描(并非访问)根节点的所有左节点,并且将它们一一进栈,当无左节点时,表示栈顶节点无左子树,然后出栈这个节点,并访问它,将p指向刚出栈节点的右孩子,对右子树进行同样的处理。 

     需要特别注意的是,当节点*p的所有左节点进栈后,这时的栈顶节点要么没有左子树,要么左子树已经被访问过,就可以访问这个栈顶节点,如此重复操作,直到栈空为止。算法如下:

//中序非递归遍历算法
void InOrder1(BTNode *b)	
{
	BTNode *St[MaxSize],*p;
	int top=-1;
	if (b!=NULL){
		p=b;
		//处理*b结点的左子树
		while (top>-1 || p!=NULL){
			//扫描*p的所有左结点并进栈
			while (p!=NULL){
				top++;
				St[top]=p;
				p=p->lchild;
			}
			//执行到此处时,栈顶元素没有左孩子或左子树均已访问过
			if (top>-1){	
				p=St[top];				//出栈*p结点
				top--;
				printf("%c ",p->data);	
				p=p->rchild;			//扫描*p的右孩子结点
			}
		}
		printf("\n");
	}
}

 

后续遍历非递归算法:

算法思路:

    后续遍历中第一个访问的节点是二叉树的最左下节点。由于首先访问节点的左右子树,然后才访问节点本身,所以对于任意节点,必须直到其左右子树是否被访问过。

    使用栈来保存需要返回的节点的指针,先扫描根节点的所有左孩子节点,并且一一进栈,出栈一个节点*p作为当前节点,然后扫描该节点的右子树,当一个节点的左右孩子节点均被访问后再访问该节点,如此重复,直到栈空为止。

    Q:如何判断一个节点*b的右子树已经访问过?

    A:如果右孩子节点已经访问过,则其右子树就已经访问过。 

    用p指针保存刚访问过得节点,若b->rchild==p成立,则b的左右子树均已访问,现在应该访问*b。所以栈中保存的是当前节点*b的所有祖先节点。这些祖先节点均未被访问过。

算法如下:

//后序非递归遍历算法
void PostOrder1(BTNode *b)	
{
	BTNode *St[MaxSize];
	BTNode *p;
	int flag,top=-1;				//栈指针置初值
	if (b!=NULL){
		do{
			while (b!=NULL){
				//将*b的所有左结点进栈
				top++;
				St[top]=b;
				b=b->lchild;
			}
			//执行到此处时,栈顶元素没有左孩子或左子树均已访问过
			p=NULL;					//p指向栈顶结点的前一个已访问的结点
			flag=1;					//设置b的访问标记为已访问过
			while (top!=-1 && flag){
				b=St[top];			//取出当前的栈顶元素
				if (b->rchild==p)	{	
					printf("%c ",b->data);	//访问*b结点
					top--;
					p=b;			//p指向刚访问过的结点
				}
				else{	
					b=b->rchild;	//b指向右孩子结点
					flag=0;			//设置未被访问的标记
				}
			}
		} while (top!=-1);
		printf("\n");
	} 
}

后序非递归遍历算法特点:当访问某个节点时,堆栈中保存的正好是该节点的所有祖先节点,从栈顶到栈底正好是该节点的双亲  节点到根节点路径上的节点序列。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java二叉树归遍可以通过使用栈数据结构来实现。首先,我们创建一个空的栈,将根节点入栈。然后,我们进入一个循环,直到栈为空为止。在每一次循环中,我们弹出栈顶元素,并将其访问。接下来,如果该节点有右子节点,则将右子节点入栈。如果该节点有左子节点,则将左子节点入栈。由于栈是先进后出的数据结构,所以我们先入栈右子节点,再入栈左子节点,以确保在遍过程中先访问左子树节点。这样就能够实现二叉树归遍。 以下是一个示例代码实现二叉树归中序遍: ```java public void inorderTraversal(Node root) { if (root == null) { return; } Stack<Node> stack = new Stack<>(); Node current = root; while (current != null || !stack.isEmpty()) { while (current != null) { stack.push(current); current = current.leftChild; } current = stack.pop(); System.out.print(current.data + " "); // 访问节点 current = current.rightChild; } } ``` 在这个示例代码中,我们首先判断当前节点是否为空或者栈是否为空,如果不满足则进入循环。在循环内部,我们首先将当前节点及其所有左子节点入栈,直到当前节点为空。然后,我们弹出栈顶节点并访问该节点。最后,将当前节点更新为其右子节点,并继续下一次循环。 通过这种方式,我们可以实现二叉树归中序遍。你可以根据需要修改代码实现其他类型的归遍,比如前序遍和后序遍。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [用Python实现二叉树、二叉树归遍及绘制的例子](https://download.csdn.net/download/weixin_38618784/14869891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [java实现二叉树树的归遍](https://blog.csdn.net/weixin_41826973/article/details/105555647)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值