6.4二叉树的遍历-非递归

6.4二叉树的遍历-非递归

一.了解递归

了解了递归中操作系统做了什么,非递归的实现也就不难理解了。

在系统调用函数时,需完成三件事:

(1)将实参、返回地址传递给被调用函数保存。

(2)为被调用函数等分配存储区。

(3)控制转移到被调用函数入口。

被调用函数返回主调函数,系统也需完成三件事:

(1)保存被调函数返回值。

(2)释放被调函数数据区。

(3)依照被调函数保存的地址控制转移到主调函数

二.二叉树遍历的非递归实现

(0)二叉树的创建 见6.1二叉树的创建

  二叉树的递归遍历 见6.2二叉树的遍历 

 

(1)用栈模拟递归,二叉树的非递归遍历依然分三种。

A.LDR中序遍历

void inorder(Stack &S, BiTree &t)
{
	BiTree p = t;
	while( p || S.top != S.bottom)
	{
		if(p)
		{
			push(S,p);
			p = p -> lchild;
		}
		else
		{
			pop(S,p);
			printf("%c ",p -> data);
			p = p -> rchild;
		}
	}
}


B.DLR先序遍历

 

void preorder(Stack &S, BiTree &t)
{
	BiTree p = t;
	while( p || S.top != S.bottom)
	{
		if(p)
		{
			printf("%c ",p -> data);
			push(S,p);
			p = p -> lchild;
		}
		else
		{
			pop(S,p);		
			p = p -> rchild;
		}
	}
}


C.LRD后序遍历(较复杂)

<span style="font-size:18px;">void postorder(Stack &S, BiTree &t)
{
	BiTree p = t;
	BiTree cur;
	BiTree pre = p;

	push(S,p);
	while(S.top != S.bottom)
	{
		cur = *(S.top-1);
        if((cur->lchild==NULL&&cur->rchild==NULL)||
           (pre!=NULL&&(pre==cur->lchild || pre==cur->rchild)))
        {
            printf("%c ",cur -> data);  //如果当前结点没有孩子结点或者孩子节点都已被访问过 
            pop(S,cur);
            pre = cur; 
        }
        else
        {
            if(cur->rchild != NULL)
                push(S,cur -> rchild);
            if(cur->lchild != NULL)    
                push(S,cur -> lchild);
        }
	}
}</span>

 

三.完整程序源代码

						/* 样例输入:abc##de#g##f### */

#include<iostream>
#include<stdlib.h>
#define len (sizeof(BiNode))
#define OK 1
typedef struct bintree
{
	struct bintree *lchild, *rchild;
	char data;
} BiNode, *BiTree;
BiTree t;//头结点指针

typedef struct stack
{
	BiTree *top;
	BiTree *bottom;
	int stacksize;
}Stack;
Stack S;

int bintree_creat(BiTree &q);
void InitStack(Stack &S);
void visit(BiTree t);

void preorder(Stack &S, BiTree &t);
void inorder(Stack &S, BiTree &t);
void postorder(Stack &S, BiTree &t);

void push(Stack &S, BiTree &p);
void pop(Stack &S, BiTree &p);
int main()
{
	printf("input node data :");
	bintree_creat(t);

	InitStack(S);

	visit(t);

	return 0;
}

int bintree_creat(BiTree &q)
{
	char n;
	n = getchar();

	if(n == '#')
		q = NULL;
	else
	{
		q = (BiTree )malloc(len);
		q->data = n;
		bintree_creat(q -> lchild);
		bintree_creat(q -> rchild);
	}

	return OK;
}

void InitStack(Stack &S)
{
	printf("input stacksize :");
	scanf("%d",&S.stacksize);
	S.bottom = S.top = (BiTree *)malloc(S.stacksize*sizeof(BiTree ));
}

void visit(BiTree t)
{
	int i;

	while(1)
	{
		printf("\n\ninput 1 : preorder the tree !\ninput 2 : inorder the tree !\ninput 3 : postorder the tree !\ninput 0 to exit\n\n");
		scanf("%d",&i);

		switch (i)
		{
			case 1 :preorder(S,t);  break;
			case 2 :inorder(S,t);   break;
			case 3 :postorder(S,t); break;
			case 0 :exit(0);
			default:printf("input error !");break;
		}
	}
}

void preorder(Stack &S, BiTree &t)
{
	BiTree p = t;
	while( p || S.top != S.bottom)
	{
		if(p)
		{
			printf("%c ",p -> data);
			push(S,p);
			p = p -> lchild;
		}
		else
		{
			pop(S,p);		
			p = p -> rchild;
		}
	}
}

void inorder(Stack &S, BiTree &t)
{
	BiTree p = t;
	while( p || S.top != S.bottom)
	{
		if(p)
		{
			push(S,p);
			p = p -> lchild;
		}
		else
		{
			pop(S,p);
			printf("%c ",p -> data);
			p = p -> rchild;
		}
	}
}

void postorder(Stack &S, BiTree &t)
{
	BiTree p = t;
	BiTree cur;
	BiTree pre = p;

	push(S,p);
	while(S.top != S.bottom)
	{
		cur = *(S.top-1);
        if((cur->lchild==NULL&&cur->rchild==NULL)||
           (pre!=NULL&&(pre==cur->lchild || pre==cur->rchild)))
        {
            printf("%c ",cur -> data);  //如果当前结点没有孩子结点或者孩子节点都已被访问过 
            pop(S,cur);
            pre = cur; 
        }
        else
        {
            if(cur->rchild != NULL)
                push(S,cur -> rchild);
            if(cur->lchild != NULL)    
                push(S,cur -> lchild);
        }
	}
}

void push(Stack &S, BiTree &p)
{
	*S.top++ = p;
}

void pop(Stack &S, BiTree &p)
{
	p = * --S.top;
}


 

参考:http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树遍历有三种方式:前序遍历、中序遍历和后序遍历。其非递归算法如下: 1. 前序遍历非递归算法 使用栈来模拟前序遍历的递归过程,先将根节点压入栈中,然后循环执行以下步骤: - 弹出栈顶节点,并打印该节点的值。 - 如果该节点有右子树,则将右子树压入栈中。 - 如果该节点有左子树,则将左子树压入栈中。 代码实现: void PreOrderTraversal(BinTree BT) { if (!BT) return; // 空树直接返回 Stack S = CreateStack(MaxSize); // 创建栈 BinTree T = BT; while (T || !IsEmpty(S)) { while (T) { printf("%d ", T->Data); // 访问节点 Push(S, T); T = T->Left; } if (!IsEmpty(S)) { T = Pop(S); T = T->Right; } } } 2. 中序遍历非递归算法 使用栈来模拟中序遍历的递归过程,先将根节点入栈,然后循环执行以下步骤: - 如果当前节点不为空,将其左子树入栈。 - 如果当前节点为空,弹出栈顶节点,并打印该节点的值,然后将其右子树入栈。 代码实现: void InOrderTraversal(BinTree BT) { if (!BT) return; // 空树直接返回 Stack S = CreateStack(MaxSize); // 创建栈 BinTree T = BT; while (T || !IsEmpty(S)) { while (T) { Push(S, T); T = T->Left; } if (!IsEmpty(S)) { T = Pop(S); printf("%d ", T->Data); // 访问节点 T = T->Right; } } } 3. 后序遍历非递归算法 使用栈来模拟后序遍历的递归过程,需要记录上一个访问的节点 LastVisit。先将根节点入栈,然后循环执行以下步骤: - 如果栈顶节点的左右子树都为空,弹出栈顶节点,并打印该节点的值,然后将 LastVisit 指向该节点。 - 如果栈顶节点的右子树不为空且未被访问过,则将右子树入栈。 - 如果栈顶节点的左子树不为空且未被访问过,则将左子树入栈。 代码实现: void PostOrderTraversal(BinTree BT) { if (!BT) return; // 空树直接返回 Stack S = CreateStack(MaxSize); // 创建栈 BinTree T = BT, LastVisit = NULL; while (T || !IsEmpty(S)) { while (T) { Push(S, T); T = T->Left; } T = Top(S); if (T->Right == NULL || T->Right == LastVisit) { Pop(S); printf("%d ", T->Data); // 访问节点 LastVisit = T; T = NULL; } else { T = T->Right; } } }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值