树的镜像
来源:互联网 发布:如何开通淘宝贷款吗 编辑:程序博客网 时间:2024/05/18 12:01
淘宝笔试的一个题目,在网上也没有找到正确的代码,自己写了一个,简单测试了下还行,但不保证完全正确。题目是这样的,一棵树,不一定是二叉树,是一棵很普通的屌丝树,把他镜像反转下。思路必须明确,首先用左孩子右兄弟的存储方法存储这棵树,然后对所有同级别的兄弟反转,也就是所有节点的右边链反转,其实也就是单链表反转的操作。代码中用到了递归,但是要注意的一点是单链表反转while中操作的次数为链表的长度减一的,这也就是说递归的时候是缺少了一次的,这就要求在while后面补上这次缺少的递归操作。树的图如下:
树的左孩子(child)右兄弟(sibling)的存储如下:
代码如下:代码中的数组为树的左孩子右兄弟存储的先序遍历顺序。
#include <iostream>#include <assert.h>using namespace std;typedef char ElemType;typedef struct CSNode{ ElemType data; struct CSNode *firstchild, *nextsibling;}CSNode, *CSTree;const char INVALID = '^';const int MAX_NODE_COUNT = 20;void createCSTree(CSTree &tree, char *a);void preOrder(const CSTree tree);void mirrorCSTree(CSTree tree);int main(){ char a[] = {'A', 'B', 'E', 'H', '^', 'I', '^', '^', '^', 'C', '^', 'D', 'F', 'J', '^', '^', 'G', '^', '^', '^', '^', '\0'}; CSTree tree = NULL; createCSTree(tree, a); printf("before mirror preOrder:\n"); preOrder(tree); mirrorCSTree(tree); printf("after mirror preOrder:\n"); preOrder(tree); return 0;}void createCSTree(CSTree &tree, char *a){ static int i = 0; if(a[i] == '\0') return; if(a[i] == INVALID) { tree = NULL; i++; return; } else { CSNode *pCSNode = (CSNode *)malloc(sizeof(CSNode)); pCSNode->data = a[i++]; tree = pCSNode; createCSTree(tree->firstchild, a); createCSTree(tree->nextsibling, a); }}void preOrder(const CSTree tree){ if(tree != NULL) { cout<<tree->data<<endl; preOrder(tree->firstchild); preOrder(tree->nextsibling); }}void mirrorCSTree (CSTree tree){ if (tree == NULL) return; if (tree->firstchild) { CSTree p1 = tree->firstchild; CSTree p2 = p1->nextsibling; p1->nextsibling = NULL; //注意一开始的要先指向NULL while (p2) { CSTree p3 = p2->nextsibling; p2->nextsibling = p1; mirrorCSTree (p1->firstchild); if(p3 == NULL) mirrorCSTree(p2); p1 = p2; p2 = p3; } tree->firstchild = p1; }}
其实树的镜像是非常难写正确的的. 下面是第二个版本,参数传进来的树的根节点。看起来比上面的顺眼些
树的结构和上面的一样,前序遍历为1, 2, 3, 4, 5, 6, 7, 8, 9, 10镜像后为1 7 10 8 9 6 2 3 5 4难的地方在当旋转右子树的最后一个节点的时候。当跳出while循环的时候,最后一个节点的left并没有调用mirror函数,就要想办法把它补上。最好的地方是加在while循环的里面也就是上面代码一样。如果加在while循环的后面,这个时候可能会出现重复的递归,递归不能返回的情况(非常可能出现)。我尝试了很多条件都没有使得递归停止。原因是如果在while后面加上一个mirrorTree(p1)的话,其实首先p1虽然变成p2了,但是p2的right已经改变了。这就非常麻烦了,最后的结果可能是在p1和p2之间来回递归。
void mirrorTree(BTree &rt){ if(rt == NULL) return; if(rt->right == NULL) { mirrorTree(rt->left); return; } BTree p1= rt; BTree p2= p1->right; p1->right = NULL; while(p2) { BTree p3 = p2->right; p2->right = p1; mirrorTree(p1->left); if(p3 == NULL) mirrorTree(p2->left); p1 = p2; p2 = p3; } rt = p1;}int main(){ int a[] = {1, 2, 3, 4, -1, 5, -1, -1,-1, 6, -1, 7, 8, 9, -1, -1, 10, -1, -1, -1, -1}; int i = 0; BTree rt = NULL; createTree(a, i, rt); preOrder(rt); cout<<endl; mirrorTree(rt); preOrder(rt); cout<<endl;}
- 树的镜像
- 树的镜像
- 树的镜像
- 树的镜像
- 树的镜像
- 树的镜像
- 树的镜像
- 树的镜像反转
- 树的镜像反转
- 二叉树的镜像
- 二叉树的镜像
- 二叉树的镜像
- 二叉树的镜像
- 二叉树的镜像
- 二叉树的镜像
- 二叉树的镜像
- 二叉树的镜像
- 二叉树的镜像
- 反转一个字节 和 判断32位整数二进制中1的个数 的算法
- C# 使用委托调用待待闪屏
- Java多线程——仿真生产汽车组装汽车过程
- c++设计与编程之包含关系(包容关系)
- 判断当前是否为锁屏界面(Keyguard)
- 树的镜像
- eclipse 插件hadoop点击没有反应解决方法
- 11款对开发者有帮助的Android应用
- destoon供应模块增加房产筛选功能
- 云计算的NIST定义
- CreateToolhelp32Snapshot
- mysql优化
- SCM系统之 SVN "VS" CVS
- 查询数据库中表使用的空间信息。