递归与非递归二叉树遍历
前段时间意外收到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; }