二叉树 非递归遍历
以下图二叉树为例:
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY 1
#define NONEMPTY 0
typedef struct TreeNode
{
char data;
struct TreeNode *leftChild;
struct TreeNode *rightChild;
int flag; // 检查在 后续遍历 时,节点是否被访问
} TreeNode;
typedef struct StackNode
{
TreeNode *TreeData;
struct StackNode *next;
} StackNode;
int isEmpty(StackNode *stack)
{
if (stack->next == NULL)
{
return EMPTY;
}
else
{
return NONEMPTY;
}
}
void createTree(TreeNode **T, const char *data, int *index) // 以先序遍历创建
{
char ch;
ch = data[*index];
(*index)++;
if (ch == '#') // 此时为空节点
{
*T = NULL;
}
else // 此时不为空
{
*T = (TreeNode *)malloc(sizeof(TreeNode));
(*T)->data = ch;
(*T)->flag = 0;
createTree(&((*T)->leftChild), data, index);
createTree(&((*T)->rightChild), data, index);
}
}
StackNode *initStack()
{
StackNode *stack = (StackNode *)malloc(sizeof(StackNode));
if (stack == NULL)
{
printf("malloc stack error\n");
}
stack->TreeData = NULL;
stack->next = NULL;
return stack;
}
void push(TreeNode *treedata, StackNode *stack)
{
StackNode *newNode = (StackNode *)malloc(sizeof(StackNode));
if (newNode == NULL)
{
printf("malloc newNode error\n");
}
newNode->TreeData = treedata;
newNode->next = stack->next;
stack->next = newNode;
}
StackNode *pop(StackNode *stack)
{
if (isEmpty(stack) == EMPTY)
{
return NULL;
}
else
{
StackNode *node = stack->next;
stack->next = node->next;
return node;
}
}
StackNode *getTop(StackNode *stack)
{
if (isEmpty(stack) == EMPTY)
{
return NULL;
}
else
{
StackNode *node = stack->next;
return node;
}
}
void preQrder(TreeNode *T)
{
TreeNode *node = T;
StackNode *stack = initStack();
while (node != NULL || isEmpty(stack) == NONEMPTY)
{
if (node != NULL)
{
// 前序遍历 -> 先访问,在进栈
printf("%c ", node->data);
push(node, stack);
node = node->leftChild; // 循环,直到左孩子为空
}
else // node == NUll --> 出栈
{
node = pop(stack)->TreeData;
node = node->rightChild;
}
}
}
void inQrder(TreeNode *T)
{
TreeNode *node = T;
StackNode *stack = initStack();
while (node != NULL || isEmpty(stack) == NONEMPTY)
{
if (node != NULL)
{
push(node, stack);
node = node->leftChild; // 循环,直到左孩子为空
}
else // node == NUll --> 出栈
{
node = pop(stack)->TreeData;
printf("%c ", node->data);
node = node->rightChild;
}
}
}
/**
* 后序遍历
* 1、从根节点开始,寻找最左边的节点,并一次入栈
* 2、出栈前,判断栈顶元素是否有右子树,还要判断右子树是否已经访问过了,如果有则将右子树入栈
*/
void postOrder(TreeNode *T)
{
TreeNode *node = T;
StackNode *stack = initStack();
while (node != NULL || isEmpty(stack) == NONEMPTY)
{
if (node != NULL)
{
push(node, stack);
node = node->leftChild;
}
else
{
TreeNode *top = getTop(stack)->TreeData;
if (top->rightChild != NULL && top->rightChild->flag == 0)
{
top = top->rightChild;
push(top, stack);
node = top->leftChild;
}
else
{
top = pop(stack)->TreeData;
printf("%c ", top->data);
top->flag = 1;
}
}
}
}
int main(int argc, char const *argv[])
{
TreeNode *T;
int index = 0;
createTree(&T, argv[1], &index);
printf("非递归的前序遍历 > ");
preQrder(T);
putchar(10);
printf("----------------------------------------------------------\n");
printf("非递归的中序遍历 > ");
inQrder(T);
putchar(10);
printf("----------------------------------------------------------\n");
printf("非递归的后序遍历 > ");
postOrder(T);
putchar(10);
printf("----------------------------------------------------------\n");
return 0;
}
运行结果如下:
superlan@GodFather:~/C_Language/data_structure$ ./a.out ABD#F##E##C##
非递归的前序遍历 > A B D F E C
----------------------------------------------------------
非递归的中序遍历 > D F B E A C
----------------------------------------------------------
非递归的后序遍历 > F D E B C A
----------------------------------------------------------