数据结构--非递归实现二叉树的先序,中序,后序遍历

     

如上图所示 : 二叉树的先序遍历顺序为: A B D C E F

                                   中序遍历顺序为 : D B A E C F
                                   后序遍历顺序为 : D B E F C A

先序遍历(非递归) :

方法一 : 先将元素左边全部入栈 , 入栈同时打印入栈元素 , 然后用临时指针记录栈顶元素 , 出栈再将临时指针的右边元素入栈 , 如果临时指针为空 , 那么继续出栈 , 如果不为空就将临时指针的左边继续入栈 , 不断重复上述操作 , 直到栈空且临时指针指向NULL

顺序可以理解为 : 左先一直入栈 , 右不为空时 , ( 再入右 , 再一直入左 ) , 当右为空时 , 将栈顶元素Pop , 再继续找入右 , 直到循环结束 

按照例题顺序为 : 想将A B D 依次入栈 , 在判断 D 右是否有元素 , 没有就出 D ,再依次出B A , 然后再入C , 再入 E , 再入F

每次入栈前打印元素 , 打印顺序就为 : A B D C E F  

代码如下 :

void BinaryTreePrevOrderNon_RWayOne(BTNode* root)
{
	BTNode * cur;
	BTNode * top;
	Stack s;
	StackInit(&s);
	cur = root;
	while (cur || StackEmpty(&s))
	{
		while (cur)
		{
			printf("%c ", cur->_data);
			StackPush(&s, cur);
			cur = cur->_left;
		}
		top = StackTop(&s);
		StackPop(&s);
		cur = top->_right;
	}
}

方法二 : 利用栈的性质每次出栈顶元, 遵循后入先出原则, 先将右边入栈再将左边入栈, 那么当出栈时, 就先用临时指针记录栈顶, 再出栈再判断临时指针的左右是否为空, 若不为空则相继入栈, 最后当栈为空时, 循环结束

扫描二维码关注公众号,回复: 2984504 查看本文章

按照上述操作 遍历所给例题中二叉树;
A入栈,临时指针记录A,打印栈顶元素A,A出栈,CB相继入栈
临时指针记录栈顶元素,打印B,B出栈,D入栈
临时指针记录栈顶元素,打印D,D出栈,临时指针左右指向空,不进行操作
临时指针指向栈顶元素,打印C,C出栈,FE相继入栈
临时指针指向栈顶元素,打印E,E出栈,临时指针左右指向空,不进行操作
临时指针指向栈顶元素,打印F,F出栈,临时指针左右指向空,不进行操作
栈为空循环结束  打印顺序依次为 : A B D C E F

代码如下:

void BinaryTreePrevOrderNon_RWayTwo(BTNode* root)
{
	Stack s;
	BTNode * cur;
	if (root == NULL)
		return;
	StackInit(&s);
	StackPush(&s, root);
	while (StackEmpty(&s))
	{
		cur = StackTop(&s);
		printf("%c ", cur->_data);
		StackPop(&s);
		if ( cur->_right != NULL)
			StackPush(&s, cur->_right);
		if (cur->_left != NULL)
		    StackPush(&s, cur->_left);
	
	}
	StackDestroy(&s);
}

中序遍历(非递归) : 就是将先序遍历中打印元素的顺序改变 , 只有当元素出栈时才将元素打印

                            先将左边元素全部入栈 , 然后判断当栈不为空且栈顶元素右边为空时 , 一直出栈 , 出栈时打印出栈元素 , 否则将栈顶元素右边入栈, 然后循环 , 直到栈空循环结束 , 

每次出栈前打印元素 , 打印顺序就为 : D B A E C F

代码如下:

void BinaryTreeInOrderNonR(BTNode* root)
{
	BTNode * cur;
	BTNode * top;
	Stack s;
	StackInit(&s);
	cur = root;
	while (cur || StackEmpty(&s))
	{
		while (cur)
		{
		        StackPush(&s, cur);
			cur = cur->_left;
		}
		top = StackTop(&s);
		printf("%c ", top->_data);
		StackPop(&s);
		cur = top->_right;
	}
}

后序遍历(非递归) :

方法一 : 按照后序遍历的顺序 , 先将数的左边元素全部入栈 , 再将入栈顶右边元素 , 然后再继续入左边元素 , 当栈顶元素的右边为空时或当栈定元素的右边等于prev(记录的是上一个出栈元素 , 防止出现重复入栈 , 出现死循环) , 使用一个临时指针prev去记录 , 即将要出栈的元素 , 然后元素出栈 , 再继续循环判断 , 

代码如下 : 

void BinaryTreePostOrderNonR(BTNode* root)
{
	BTNode * prev;
	BTNode * cur;
	BTNode * top;
	Stack s;
	StackInit(&s);
	prev = NULL;
	cur = root;
	//使用一个临时prev指针去记录出栈前的栈顶元素,只有当当栈顶元素为空,或者栈顶元素等于prev(
	//prev是之前刚出栈的元素)
	while (cur || StackEmpty(&s))
	{
		while (cur)
		{
			StackPush(&s, cur);
			cur = cur->_left;
		}
		top = StackTop(&s);
		if (top->_right == NULL || top->_right == prev)
		{
			prev = StackTop(&s);
			StackPop(&s);
			printf("%c ", prev->_data);
		}
		else
			cur = top->_right;
	}
}

方法二 : 寻找后序与先序的关系,就拿题中所示先序顺序为 : ABDCEF

                                                                         后序顺序为 : DBEFCA

当我们将先序中的左右顺序调换则                   顺序就变成 : ACFEBD
这样我们就可以发现后序的顺序其实就时上面序列的倒序,所以我们可以
将先序排列的算法改一下,将左右颠倒,当我们每次,出栈之前可以用一个
辅助栈将要出栈的元素入栈,最后打印这个辅助栈即可

代码如下:

void BinaryTreePostOrderNonR(BTNode* root)
{
	Stack s;
	Stack sp;
	BTNode * cur;
	if (root == NULL)
		return;
	StackInit(&s);
	StackInit(&sp);
	StackPush(&s, root);
	while (StackEmpty(&s))
	{
		cur = StackTop(&s);
		StackPush(&sp, StackTop(&s));
		StackPop(&s);
		if (cur->_left != NULL)
			StackPush(&s, cur->_left);
		if (cur->_right != NULL)
			StackPush(&s, cur->_right);
	}
	while (StackEmpty(&sp))
	{
		printf("%c ", StackTop(&sp)->_data);
		StackPop(&sp);
	}
	StackDestroy(&s);
	StackDestroy(&sp);
}

猜你喜欢

转载自blog.csdn.net/ds19980228/article/details/81874801
今日推荐