递归与非递归二叉树遍历

来源:互联网 发布:淘宝福利群真的假的 编辑:程序博客网 时间:2024/05/19 02:04

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

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

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

     头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);

  源文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#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();
        }
 
 
 
    }
 
 
 
}

  

测试文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 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;
}

0 0