多年之前笔者刚毕业的时候去百度面试,要求当场写出非递归方式的二叉树遍历。(当场懵逼了。)
其实当时自己可能由于紧张,并且对不同数据结构之间的理解还不够深刻。
本质上递归遍历也是利用栈来控制遍历的先后顺序,只是递归算法由于子程序的使用代码会简介许多。
而非递归需要自己对进栈和出栈有一定的理解。而且还需要构建额外的数据结构(C语言没有线程的栈结构,c++的std::stack可以方便不少)。所以实现上会难于递归。
销毁二叉树采用递归方式。
遍历二叉树采用栈的方式。
大概讲一下思路。(采用中序遍历为例子)
1)首先将头结点进栈,然后进入一个主循环
2)主循环判断栈是否为空,若空则退出若非空则进入
3)取出栈中的第一个结点称为pTail
4)由于栈是先进后出,因此右结点在左结点之后遍历。所以先判断是否存在右结点,若存在则入栈
5)接着判断是否存在左结点,若存在则入栈
6)可以输出当前结点的一些信息或者进行一些操作表明“遍历”
7)当前循环结束,跳转至步骤2)循环
代码如下。
#define _CRT_SECURE_NO_WARNINGS
#include <tchar.h>
#include <windows.h>
#include <stdio.h>
#include <process.h>
#define MAX_NODE 256
typedef struct TreeNode{
int id;
TreeNode * left;
TreeNode * right;
}TreeNode;
//
TreeNode *g_data[MAX_NODE] = { 0 };
int g_p = 0;
void stackPush(TreeNode* pNode) {
// stack overflow!
if (g_p >= MAX_NODE)
return;
g_data[g_p++] = pNode;
}
TreeNode *stackPop() {
// stack overflow
if (g_p == 0)
return NULL;
return g_data[--g_p];
}
bool isStackEmpty() {
return g_p == 0;
}
//
//Travesal without recursive.
void TravesalTree(TreeNode *phead) {
TreeNode *pTail = phead;
if (pTail)
stackPush(pTail);
while (!isStackEmpty()) {
pTail = stackPop();
if (pTail) {
printf("%d ", pTail->id);
if (pTail->right)
stackPush(pTail->right);
if (pTail->left)
stackPush(pTail->left);
}
}
printf("\n");
}
// Travesal tree with recursive.
void DestroyTree(TreeNode *phead) {
if (phead->left)
DestroyTree(phead->left);
if (phead->right)
DestroyTree(phead->right);
//
printf("destroy node id:%d\n", phead->id);
free(phead);
}
int _tmain(int argc, TCHAR* argv[], TCHAR * env[])
{
int id = 0;
TreeNode * phead = (TreeNode *)malloc(sizeof(TreeNode));
phead->id = id++;
phead->left = NULL;
phead->right = NULL;
TreeNode *pTail = phead;
TreeNode * p = (TreeNode *)malloc(sizeof(TreeNode));
p->id = id++;
p->left = NULL;
p->right = NULL;
pTail->left = p;
p = (TreeNode *)malloc(sizeof(TreeNode));
p->id = id++;
p->left = NULL;
p->right = NULL;
pTail->right = p;
pTail = pTail->left;
p = (TreeNode *)malloc(sizeof(TreeNode));
p->id = id++;
p->left = NULL;
p->right = NULL;
pTail->left = p;
TravesalTree(phead);
DestroyTree(phead);
return 0;
}