二叉树的非递归遍历

能递归实现的一般都可以用栈来实现,因此可以用栈来实现二叉树的非递归遍历。以下图的二叉树为例:

1、先序遍历:首先把根结点入栈,然后根结点出栈(访问结点),在出栈的同时将其右左孩子进栈,再把栈顶元素出栈(访问结点),同时将其右左孩子入栈,如此反复知道栈为空。

typedef struct node
{    
	int data;
	struct node *lchild,*rchild;
}BTree;

void PreOrderUnrec(BTree *root)
{
	if (NULL == root)
	{
		return;
	}

	stack<BTree*> s;
	BTree *p;
	s.push(root);
	while (!s.empty())
	{
		p = s.top();
		Visit(p->data);
		s.pop();
		if (p->rchild != NULL)
		{
			s.push(p->rchild);
		}
		if (p->lchild != NULL)
		{
			s.push(p->lchild);
		}
	}
}


还有另外一种方法:

(1)将二叉树的根结点作为当前结点;

(2)若当前结点非空,先访问该结点,并将该结点进栈,再将其左孩子结点作为当前结点,重复步骤(2),直到当前结点为空;

(3)若栈非空,则栈顶结点出栈,并将当前结点的右孩子在哦为当前结点;

(4)重复步骤(2)(3),直到栈为空且当前结点为空。

void PreOrderUnrec1(BTree *root)
{
	if (NULL == root)
	{
		return;
	}

	stack<BTree*> s;
	BTree *p;
	p = root;

	while (p != NULL && !s.empty())
	{
		while (p != NULL)
		{
			Visit(p->data);
			s.push(p);
			p = p->lchild;
		}

		if (!s.empty())
		{
			p = s.pop();
			p = p->rchild;
		}
	}
}


 

2、中序遍历:

(1)将二叉树的根结点作为当前结点;

(2)如果当前结点非空,则该结点进栈并将其左孩子作为当前结点,重复步骤(2)直到当前结点为空;

(3)若栈非空,将栈顶结点出栈并访问,再将其右孩子作为当前结点;

(4)重复步骤(2)(3),直到栈为空且当前结点为空。

void MidOrderUnrec(BTree *root)
{
	if (NULL == root)
	{
		return;
	}

	stack<BTree*> s;
	BTree *p;
	p = root;

	while (p != NULL || !s.empty())
	{
		while (p != NULL)
		{
			s.push(p);
			p = p->lchild;
		}

		if (!s.empty())
		{
			p = s.pop();
			Visit(p->data);
			p = p->rchild;
		}
		
	}
}


3、后序遍历:

后续遍历的非递归实现可以仿照先序遍历的第一种实现方法,和先序遍历不同的是,后序遍历不应该在出栈时才右左孩子进栈,而是应该在根父结点进栈的同时就把右左孩子入栈。在父结点出栈的时候,需要判断左右孩子是否已经遍历过,如果遍历过了才能遍历父结点。因此需要增加一个标志位来判断右左孩子是否遍历过,定义一个新的结构体

typedef struct STreeNode
{
	BTree *treeNode;
	int flag;
}*pSTree;

其中flag=0表示右左孩子没有遍历过,flag=2表示右左孩子已经遍历完。

void PostOrderUnrec(BTree *root)
{
	stack<pSTree> s;

	//根结点先入栈
	pSTree sTree = (pSTree)malloc(sizeof(struct STreeNode));
	sTree->treeNode = root;
	sTree->flag = 0;
	s.push(sTree);

	while (!s.empty())
	{
		pSTree p = s.pop;
		if (p->flag == 2)//如果栈顶结点标志位是2
		{
			Visit(p->treeNode->data);//则访问
			s.pop();
		}
		else
		{
			//如果右孩子存在,则进栈并将标志位加1
			if (p->treeNode->rchild)
			{
				pSTree sTree = (pSTree)malloc(sizeof(struct STreeNode));
				sTree->treeNode = p->treeNode->rchild;
				sTree->flag = 0;
				s.push(sTree);
			}
			p->flag++;

			//如果左孩子存在,则进栈并将标志位加1
			if (p->treeNode->lchild)
			{
				pSTree sTree = (pSTree)malloc(sizeof(struct STreeNode));
				sTree->treeNode = p->treeNode->lchild;
				sTree->flag = 0;
				s.push(sTree);
			}
			p->flag++;
		}
	}
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值