心胸决定格局,眼界决定境界...

递归与非递归二叉树遍历

      前段时间意外收到MS的电面,因为现在做的工作基本上是与音频、音乐信号处理相关,外带互联网全能打杂型。本质上跟计算机纯软件不是太相关。我最后选择了自己比较感兴趣的IMML组面试了一下。

      面试基本上就是英语口语面试和二叉树相关的内容。所以想进微软的同学,这两项基本功要打好基础了。

     笔试的第一题是用非递归的方法遍历二叉树,这个再学校的时候也没有复习到,只用过递归的方法,工作中也没有用到,所以一时半刻也没写准确,回去学习了一下,补习了一下,不过估计过段时间,还是会忘记,呵呵。

     头文件

typedef struct BiNode
{
	int value;
	BiNode* pLeftChild;
	BiNode* pRightChild;
	int state;
};

typedef BiNode* BiTree;

void CreateBiTree1(BiNode **root);
void LayerPrint(BiNode *root);
void prePrint(BiNode* root);
void midPrint(BiNode* root);
void postPrint(BiNode* root);

void prePrint_nonRecusive(BiNode* root);
void midPrint_nonRecusive(BiNode* root);
void postPrint_nonRecusive(BiNode* root);

  源文件

#include "CreateBiTree.h"
#include <malloc.h>
#include <stdio.h>
#include <stack>
#include <queue>
using namespace std;

void CreateBiTree1(BiNode **root)//递归形式,先序生成树
{
	int   input;
	scanf("%d", &input);
	if(input == -1)
	{
		return ;
	}
	*root = (BiNode*) malloc(sizeof(BiNode));//根
	(*root)->pLeftChild = NULL;
	(*root)->pRightChild = NULL;
	(*root)->value = input; 
	//生成根节点
	CreateBiTree1( &(*root)->pLeftChild );//生成左子树
	CreateBiTree1( &(*root)->pRightChild );//生成右子树

}

//逐层遍历,从左到右, 打印出关系图
void LayerPrint(BiNode *root)
{

	if(root == NULL)
	{

	}	
	queue<BiNode *>  store;
	store.push(root);
	int cur_layer_num = store.size();

	while(!store.empty())
	{
		
		int next_layer_num = 0;
		for(int i = 1; i <= cur_layer_num; i++)
		{
			BiNode * temp = store.front();//取出最上层
			printf("%d ", temp->value);
			if(temp->pLeftChild != NULL)
			{
				store.push(temp->pLeftChild);//保存本节点的各个子节点
				next_layer_num++;
			}
			if(temp->pRightChild != NULL)
			{
				store.push(temp->pRightChild);
				next_layer_num++;
			}
			store.pop();//弹出最上层
		}//本层处理完,下层的子节点也保存了下来

		cur_layer_num = next_layer_num;
	}


}


//先序递归
void prePrint(BiNode* root)
{
	if(root == NULL)
		return;
	printf("%d ", root->value);
	prePrint(root->pLeftChild);
	prePrint(root->pRightChild);
}
/*非递归*/
void prePrint_nonRecusive(BiNode* root)
{
	if(root == NULL)
		return ;
	BiNode *cur = root;
	int     state = 0;
	stack<BiNode*>  store;
	while(1)
	{
		if(!cur)
		{	
			//if(cur == root) break;
			//或者
			if(store.empty())  break;
			cur = store.top();//如果当前节点为空,则返回上一层			 
			state = cur->state;//获取当前节点的状态
		    store.pop();//弹出该层
		}
		else if(state == 0)//打印当前节点,压入栈中
		{
			printf("%d ", cur->value);//打印根节点
			cur->state = 1;
			store.push(cur);//压入该层的节点
			cur = cur->pLeftChild;//指向左节点
			state = 0;//继续往左,打印,添加新的左边节点
		}
		else if(state == 1)//转向右边节点
		{
			cur->state = 2;//判断以当前节点为根节点,是否已经结束
			store.push(cur);
			cur = cur->pRightChild;
            state = 0;
		}
		else if(state == 2)//如果,返回上一层节点
		{			
			//if(cur == root) break;	
			//或者
			if(store.empty())  break;

			cur = store.top();
			state = cur->state;
			store.pop();//弹出
		}		

	}
}

//中序递归
void midPrint(BiNode* root)
{
	if(root == NULL)
		return;
	midPrint(root->pLeftChild);
    printf("%d ", root->value);
	midPrint(root->pRightChild);
}

/*非递归*/
void midPrint_nonRecusive(BiNode* root)//中序遍历
{
	if(root == NULL)
		return;
	int state =   0; //打印左子树,根,右子树	
	BiNode*  cur = root;
	stack<BiNode*>  store;
	while(1)
	{
		if(!cur)//如果为空,则返回上一层
		{
			if(cur == root)  break;
			cur = store.top();
			state = cur->state;
			store.pop();

		}
		if(state == 0)//表示保存本节点入栈, 指向左孩子
		{
			cur->state = 1;
			store.push(cur);//压入栈,表示下次进入时,已当前节点为根节点,完成左边子树状态
			cur = cur->pLeftChild;//第一次进入左孩子
			state = 0;
		}
		else if(state == 1)//表示已当前节点为根节点,完成左边子树状态
		{
			cur->state = 2;
			store.push(cur);//以其为根节点,右子树完成的状态
			cur = cur->pRightChild;//第一次进入右孩子
			state = 0;//添加新节点状态
		}
		else if(state == 2)//以当前节点为根节点的树,遍历完成 (完成右子树)
		{
			if(root == cur)  break;
			//打印本层的根节点  
			printf("%d ", cur->value);
			cur = store.top();//返回上一层
			state = cur->state;//恢复该节点的状态
			store.pop();
		}

	}

}


//后序递归
void postPrint(BiNode* root)
{
	if(root == NULL)
		return;
	postPrint(root->pLeftChild);
	postPrint(root->pRightChild);
	printf("%d ", root->value);
}
/*非递归*/
void postPrint_nonRecusive(BiNode* root)
{
	if(root == NULL)//左子树,右子树,根
		return;
	int state = 0;
	BiNode *cur = root;
	stack<BiNode*>  store;
	while(1)
	{
		if(!cur)//返回上一层
		{
			cur = store.top();
			state = cur->state;//恢复出栈
			store.pop();
		}
		else if(state == 0)//保存当前节点,进入左子树
		{
			cur->state = 1;
			store.push(cur);
			cur = cur->pLeftChild;
			state = 0;//继续往左遍历
		}
		else if(state == 1)//表示以当前节点为根节点,完成左子树,进入到右子树
		{
			cur->state = 2;
			store.push(cur);
			cur = cur->pRightChild;
			state = 0;
		}
		else if(state == 2)//表示已当前节点为根的树,遍历完成
		{
			//返回上一层
			printf("%d ", cur->value);
			if(cur == root)  break;			
			cur = store.top();	
			state = cur->state;
			store.pop();
		}



	}



}

  

测试文件:

// BiTree.cpp : 定义控制台应用程序的入口点。
//
#include"CreateBiTree.h"
#include<stdio.h>
/*
8
/ \
/ \
6 10
/ \ / \
5 7 9 11
*/

int main(int argc, char* argv[])
{
BiNode* root;
printf("输入数据:\n");
CreateBiTree1(&root);
//输入 8,6,5,(继续往左)-1(返回上一层状态),(向右)-1(返回上一层),7,(向左)-1(返回上一层状态),(向右)-1(返回上一层),10,9,(向左)-1(返回上一层),(向右)-1(返回上一层),11,-1,-1
printf("层次打印:\n");
LayerPrint(root);	
printf("\n先序打印:\n");
prePrint(root);
printf("\n中序打印:\n");
midPrint(root);
printf("\n后序打印:\n");
postPrint(root);

/*非递归版本*/
printf("\n非递归,先序打印:\n");
prePrint_nonRecusive(root);
printf("\n非递归,中序打印:\n");
midPrint_nonRecusive(root);
printf("\n非递归,后序打印:\n");
postPrint_nonRecusive(root);

return 0;
}

  

 

posted @ 2015-11-26 17:24  WELEN  阅读(277)  评论(0编辑  收藏  举报