剑指offer面试题:求二叉树的镜像(递归、循环解法及测试用例)
来源:互联网 发布:淘宝保证金是什么 编辑:程序博客网 时间:2024/05/23 11:20
题目:给定二叉树,将其变换为源二叉树的镜像。
二叉树的定义如下:
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 11BinaryTreeNode* 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// 4void 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// 4void 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
请按任意键继续. . .
- 剑指offer面试题:求二叉树的镜像(递归、循环解法及测试用例)
- offer面试题------求二叉树的镜像
- 剑指Offer面试题18树的子结构(递归),面试题19二叉树的镜像(递归和非递归用栈)
- [剑指offer][面试题19]二叉树的镜像
- 【剑指offer】面试题19:二叉树的镜像
- 剑指offer 面试题19 二叉树的镜像
- 剑指Offer:面试题19 二叉树的镜像
- 《剑指Offer》面试题19:二叉树的镜像
- 《剑指Offer》面试题:二叉树的镜像
- 剑指offer-面试题19:二叉树的镜像
- 剑指offer-面试题19.二叉树的镜像
- 剑指offer面试题 二叉树的镜像
- 剑指Offer----面试题19:二叉树的镜像
- 剑指offer面试题19:二叉树的镜像
- 剑指offer面试题19:二叉树的镜像
- 剑指offer面试题19:二叉树的镜像
- 剑指offer--面试题19:二叉树的镜像
- 剑指offer-面试题19-二叉树的镜像
- JavaScript设计模式----策略模式
- 块元素和行内元素比较
- LintCode:整数排序
- 动态链接库的优缺点
- android测试类
- 剑指offer面试题:求二叉树的镜像(递归、循环解法及测试用例)
- 在 Cent OS 7 上搭建带着 PHP 7 和 Memcached 的 LAMP
- HDU4349->Lucas定理
- DPI和PPI区别
- Service的使用(四)前台服务与AIDL
- Chromium为视频标签<video>创建播放器的过程分析
- Android SQLiteDatabase的使用
- NodeJs——(16)用Nodejs 4.X版本,制作一个微博网站(多图,详细步骤)(已完成)
- POJ 2253 Frogger