剑指OFFER里有一道题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。
二叉树节点的定义如下:
struct BinaryTreeNode
{
int value;
BinaryTreeNode * left;
BinaryTreeNode * right;
};
求二叉树的镜像,,即遍历该树的每个节点,如果遍历到的节点有子节点,则交换其子节点,当交换完成所有非叶子子节点的左右子节点后,就得到了树的镜像。
递归的解法很简单,代码如下:
void mirror_recursively(BinaryTreeNode * head)
{
if(head == NULL)
return ;
if(head->left == NULL && head->right == NULL)
return;
BinaryTreeNode * temp = head->left;
head->left = head->right;
head->right = temp;
if(head->left)
mirror_recursively(head->left);
if(head->right)
mirror_recursively(head->right);
}
作者在后面给了一个扩展问题,让要求实现一个非递归的函数。
一般涉及到二叉树树的遍历问题,非递归的实现大部分情况下要用到栈来实现。
思路:对于一个节点,如果存在子节点,则入栈,同时交换其左右节点,然后让自己出栈,左右节点入栈,依此循环,直到栈为空。
非递归的函数代码如下:
void mirror_non_recurse(BinaryTreeNode * head)
{
//用一个数组模拟栈
BinaryTreeNode * stack[100] = {0};
int base = 0, top = 0;
if(head == NULL)
return ;
if(head->left == NULL && head->right == NULL)
return ;
//头结点入栈
stack[top ++] = head;
while(top > base)
{
//栈不空,则交换栈顶元素的左右节点
BinaryTreeNode * temp = stack[top-1]->left;
stack[top-1]->left = stack[top-1]->right;
stack[top-1]->right = temp;
//先保存一下栈顶元素,因为栈顶元素的左右节点入栈时还要用到其
temp = stack[top-1];
//栈顶元素出栈
top --;
//如果栈顶元素的友节点不空,则让其入栈
//因为栈有后入先出的特征,遍历树的时候是从左子树开始的,所以这里先让右子树进栈
if(temp->right != NULL)
stack[top++] = temp->right;
if(temp->left!= NULL)
stack[top++] = temp->left;
}
}
总结:碰到有涉及二叉树的遍历问题而不能使用递归实现时,考虑用栈来实现。