题目:给定二叉树,将其变换为源二叉树的镜像。
二叉树的定义如下:
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
};
输入描述:
二叉树的镜像定义:
源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
思路:
观察上面两个二叉树,很容易就可以得出下面求一棵树镜像的过程:
先序遍历这棵树的每个结点,如果遍历到的结点有子结点,则交换它的两个子结点。当交换完所有非叶子结点的左右子结点之后,就得到了树的镜像。
图制作的有点丑,但是基本可以表达清楚原理了,咳咳,若喷,请轻喷。
方法一:递归遍历法:
//递归实现二叉树的镜像,按照先序遍历,如果遇到空的节点或者叶子节点就返回,否则交换两个子树后再改变左右子树 void MirrorBinaryTree1(BinaryTreeNode* root) { if (root == NULL || (root->leftchild == NULL && root->rightchild == NULL)) { return; } BinaryTreeNode * tmp = root->leftchild; root->leftchild = root->rightchild; root->rightchild = tmp; if (root->leftchild) { MirrorBinaryTree1(root->leftchild); } if (root->rightchild) { MirrorBinaryTree1(root->rightchild); } }
方法二:循环压栈实现二叉树镜像
循环压栈示意图:
//循环实现二叉树的镜像,利用栈的“后进先出”特性打印 void MirrorBinaryTree2(BinaryTreeNode* root) { if (root == NULL) { return; } stack<BinaryTreeNode*> stackTreeNode; stackTreeNode.push(root); while (stackTreeNode.size() > 0) { BinaryTreeNode *parent = stackTreeNode.top(); stackTreeNode.pop(); BinaryTreeNode *Temp = parent->leftchild; parent->leftchild = parent->rightchild; parent->rightchild = Temp; if (parent->leftchild) { stackTreeNode.push(parent->leftchild); } if (parent->rightchild) { stackTreeNode.push(parent->rightchild); } } }
进行功能测试的时候分五种情况:
(1)测试完全二叉树:除了叶子节点,其他节点都有两个子节点
8
/ \
6 10
/ \ / \
5 7 9 11
(2) 测试二叉树:出叶子结点之外,左右的结点都有且只有一个左子结点
8
/
7
/
6
/
5
/
4
(3) 测试二叉树:出叶子结点之外,左右的结点都有且只有一个右子结点
8
\
7
\
6
\
5
\
4
(4) 测试空二叉树:根结点为空指针
(5) 测试只有一个结点的二叉树
完整代码及五种测试用例:
#include<iostream> #include<stack> using namespace std; struct BinaryTreeNode { int data; BinaryTreeNode* leftchild; BinaryTreeNode* rightchild; BinaryTreeNode(int t) { data = t; leftchild = NULL; rightchild = NULL; } }; void PreorderTravel(BinaryTreeNode* root) { if (root == NULL) { return; } cout <<root->data << " "; PreorderTravel(root->leftchild); PreorderTravel(root->rightchild); } //递归实现二叉树的镜像,按照先序遍历,如果遇到空的节点或者叶子节点就返回,否则交换两个子树后再改变左右子树 void MirrorBinaryTree1(BinaryTreeNode* root) { if (root == NULL || (root->leftchild == NULL && root->rightchild == NULL)) { return; } BinaryTreeNode * tmp = root->leftchild; root->leftchild = root->rightchild; root->rightchild = tmp; if (root->leftchild) { MirrorBinaryTree1(root->leftchild); } if (root->rightchild) { MirrorBinaryTree1(root->rightchild); } } //循环实现二叉树的镜像,利用栈的“后进先出”特性打印 void MirrorBinaryTree2(BinaryTreeNode* root) { if (root == NULL) { return; } stack<BinaryTreeNode*> stackTreeNode; stackTreeNode.push(root); while (stackTreeNode.size() > 0) { BinaryTreeNode *parent = stackTreeNode.top(); stackTreeNode.pop(); BinaryTreeNode *Temp = parent->leftchild; parent->leftchild = parent->rightchild; parent->rightchild = Temp; if (parent->leftchild) { stackTreeNode.push(parent->leftchild); } if (parent->rightchild) { stackTreeNode.push(parent->rightchild); } } } // ====================测试代码==================== // 测试完全二叉树:除了叶子节点,其他节点都有两个子节点 // 8 // 6 10 // 5 7 9 11 BinaryTreeNode* root; void Test1() { root = new BinaryTreeNode(8); root->leftchild = new BinaryTreeNode(6); root->rightchild = new BinaryTreeNode(10); BinaryTreeNode* tmp = root->leftchild; tmp->leftchild = new BinaryTreeNode(5); tmp->rightchild = new BinaryTreeNode(7); tmp = root->rightchild; tmp->leftchild = new BinaryTreeNode(9); tmp->rightchild = new BinaryTreeNode(11); cout << "Test1:测试完全二叉树,除了叶子节点,其他节点都有两个子节点" << endl; cout << "原二叉树的先序遍历" << endl; PreorderTravel(root); cout << endl; MirrorBinaryTree1(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl; /*MirrorBinaryTree2(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl;*/ } // 测试二叉树:出叶子结点之外,左右的结点都有且只有一个左子结点 // 8 // 7 // 6 // 5 // 4 void Test2() { root = new BinaryTreeNode(8); root->leftchild = new BinaryTreeNode(7); root->rightchild = NULL; BinaryTreeNode* tmp = root->leftchild; tmp->leftchild = new BinaryTreeNode(6); tmp->rightchild = NULL; tmp = tmp->leftchild; tmp->leftchild = new BinaryTreeNode(5); tmp->rightchild = NULL; tmp = tmp->leftchild; tmp->leftchild = new BinaryTreeNode(4); tmp->rightchild = NULL; cout << "Test2: 测试二叉树,出叶子结点之外,左右的结点都有且只有一个左子结点" << endl; cout << "原二叉树的先序遍历" << endl; PreorderTravel(root); cout << endl; MirrorBinaryTree1(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl; /*MirrorBinaryTree2(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl;*/ } // 测试二叉树:出叶子结点之外,左右的结点都有且只有一个右子结点 // 8 // 7 // 6 // 5 // 4 void Test3() { root = new BinaryTreeNode(8); root->leftchild = NULL; root->rightchild = new BinaryTreeNode(7); BinaryTreeNode* tmp = root->rightchild; tmp->leftchild = NULL; tmp->rightchild = new BinaryTreeNode(6); tmp = tmp->rightchild; tmp->leftchild = NULL; tmp->rightchild = new BinaryTreeNode(5); tmp = tmp->rightchild; tmp->leftchild = NULL; tmp->rightchild = new BinaryTreeNode(4); cout << "Test3:测试二叉树出叶子结点之外,左右的结点都有且只有一个右子结点" << endl; cout << "原二叉树的先序遍历" << endl; PreorderTravel(root); cout << endl; MirrorBinaryTree1(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl; /*MirrorBinaryTree2(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl;*/ } // 测试空二叉树:根结点为空指针 void Test4() { root = NULL; cout << "Test4:测试空二叉树,根结点为空指针" << endl; cout << "原二叉树的先序遍历" << endl; PreorderTravel(root); cout << endl; MirrorBinaryTree1(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl; /*MirrorBinaryTree2(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl;*/ } // 测试只有一个结点的二叉树 void Test5() { root = new BinaryTreeNode(8); root->leftchild = NULL; root->rightchild = NULL; cout << "Test5:测试只有一个结点8的二叉树" << endl; cout << "原二叉树的先序遍历" << endl; PreorderTravel(root); cout << endl; MirrorBinaryTree1(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl; /*MirrorBinaryTree2(root); cout << "二叉树镜像后的先序遍历" << endl; PreorderTravel(root); cout << endl;*/ } int main() { Test1(); Test2(); Test3(); Test4(); Test5(); system("pause"); return 0; }
运行结果:
Test1:测试完全二叉树,除了叶子节点,其他节点都有两个子节点
原二叉树的先序遍历
8 6 5 7 10 9 11
二叉树镜像后的先序遍历
8 10 11 9 6 7 5
Test2: 测试二叉树,出叶子结点之外,左右的结点都有且只有一个左子结点
原二叉树的先序遍历
8 7 6 5 4
二叉树镜像后的先序遍历
8 7 6 5 4
Test3:测试二叉树出叶子结点之外,左右的结点都有且只有一个右子结点
原二叉树的先序遍历
8 7 6 5 4
二叉树镜像后的先序遍历
8 7 6 5 4
Test4:测试空二叉树,根结点为空指针
原二叉树的先序遍历
二叉树镜像后的先序遍历
Test5:测试只有一个结点8的二叉树
原二叉树的先序遍历
8
二叉树镜像后的先序遍历
8
请按任意键继续. . .