《剑指Offer》面试题:二叉树的镜像
2015-09-20 20:01
411 查看
题目:二叉树的镜像
在完成此题目时,具体的测试要求见下面。
先说下完成此题目的感受:刚开始在《剑指Offer》这本书上看到这个题目的时候,感觉这个题目比较简单:就是将二叉树中的非叶子节点的左节点和右节点进行交换即可,但是从编码实现来看,有如下几个问题需要我们额外注意
1)用什么样的数据结构来保存树的节点是需要我们考虑的:采用数组来作为保存二叉树节点的数据结构
2)算法的实现好写,但是测试代码不好写,真的
在调试的过程中,大概花了很长的时间才搞定,刚开始将将
放在
模块之后,发现,永远输出的是全零的结果,经过调试发现:当我们将
在完成此题目时,具体的测试要求见下面。
先说下完成此题目的感受:刚开始在《剑指Offer》这本书上看到这个题目的时候,感觉这个题目比较简单:就是将二叉树中的非叶子节点的左节点和右节点进行交换即可,但是从编码实现来看,有如下几个问题需要我们额外注意
1)用什么样的数据结构来保存树的节点是需要我们考虑的:采用数组来作为保存二叉树节点的数据结构
2)算法的实现好写,但是测试代码不好写,真的
/*二叉树的镜像 输入: 输入可能包含多个测试样例,输入以EOF结束。 对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000,n代表将要输入的二叉树节点的个数(节点从1开始编号)。接下来一行有n个数字,代表第i个二叉树节点的元素的值。接下来有n行,每行有一个字母Ci。 Ci=’d’表示第i个节点有两子孩子,紧接着是左孩子编号和右孩子编号。 Ci=’l’表示第i个节点有一个左孩子,紧接着是左孩子的编号。 Ci=’r’表示第i个节点有一个右孩子,紧接着是右孩子的编号。 Ci=’z’表示第i个节点没有子孩子。 输出: 对应每个测试案例, 按照前序输出其孩子节点的元素值。 若为空输出NULL。 样例输入: 7 8 6 10 5 7 9 11 d 2 3 d 4 5 d 6 7 z z z z 样例输出: 8 10 11 9 6 7 5 */ /* 思路:通过画图我们可以看到,二叉树的镜像就是将非叶子节点的左节点和右节点进行交换即可 注意:采用数组来作为保存二叉树节点的数据结构 测试样例: 1)一般的二叉树(完成树) 2)非完全树(包含两种情况:一种是有的节点只有左子树、有的节点只有右子数) 3)只有一个节点的树 4)特殊的输入 */ #include<stdio.h> #include<stdlib.h> #include<string.h> //树的节点 //由于节点是保存在数组中,因此,每个节点的pLeftChild、pRightChild为左右两个节点在节点数组中的下标 typedef int ElementType; typedef struct TreeNode{ ElementType mValue; int pLeftChild; int pRightChild; }TreeNode; /* 参数的说明 @param pNode:树节点的头指针 @param index:节点在节点数组中的下标 */ void mirrorBinaryTree(TreeNode *pNode,int index){ if(pNode==NULL){ return; } if(index==-1){ return; } if(pNode[index].pLeftChild==-1&&pNode[index].pRightChild==-1){//只有一个节点 return; } //交换此节点的左右节点 int temp=pNode[index].pLeftChild; pNode[index].pLeftChild=pNode[index].pRightChild; pNode[index].pRightChild=temp; if(pNode[index].pLeftChild!=-1){ mirrorBinaryTree(pNode,pNode[index].pLeftChild); } if(pNode[index].pRightChild!=-1){ mirrorBinaryTree(pNode,pNode[index].pRightChild); } } int j=0; void saveValueByPreTraversal(TreeNode *pNode,int index,int *preTraversal,int len){ if(pNode==NULL){ printf("return!!"); return; } if(index!=-1&&j<len){ preTraversal[j++]=pNode[index].mValue; //printf("%d",pNode[index].mValue); if(pNode[index].pLeftChild!=-1){ saveValueByPreTraversal(pNode,pNode[index].pLeftChild,preTraversal,len); } if(pNode[index].pRightChild!=-1){ saveValueByPreTraversal(pNode,pNode[index].pRightChild,preTraversal,len); } } } int main(void){ //在得到二叉树的镜像的之前,我们需要创建一个树 int n; while(scanf("%d",&n)!=EOF){ TreeNode *pNode=NULL; if(n>0){ TreeNode *pNode=(TreeNode*)malloc(n*sizeof(TreeNode)); if(pNode==NULL){ exit(EXIT_FAILURE); } //接下来开始接受每个节点的value int i,val; for( i=0;i<n;i++){//这里节点下标是从0开始的 scanf("%d",&val); pNode[i].mValue=val; pNode[i].pLeftChild=-1;//-1表示无子节点 pNode[i].pRightChild=-1; } //接下来开始接受每个节点的左右节点 for( i=0;i<n;i++){ //下面的while循环是跳过缓冲区得换行符 while(getchar()!='\n'){ continue; } char ch; scanf("%c",&ch); if(ch=='d'){//此节点有左右两个节点 int leftIndex; int rightIndex; //scanf("%d %d",&leftIndex,&rightIndex);//leftIndex为第leftIndex个节点 ,从1开始,因此为存储在数组中,需要减 1 scanf("%d",&leftIndex); scanf("%d",&rightIndex); pNode[i].pLeftChild=leftIndex-1; pNode[i].pRightChild=rightIndex-1; } else if(ch=='l'){ int leftIndex; scanf("%d",&leftIndex);//leftIndex为第leftIndex个节点 ,从1开始,因此为存储在数组中,需要减 1 pNode[i].pLeftChild=leftIndex-1; } else if(ch=='r'){ int rightIndex; scanf("%d",&rightIndex); pNode[i].pRightChild=rightIndex-1; } else if(ch=='z'){ continue; } else{ // exit(EXIT_FAILURE); } } //以上创建好一个二叉树 mirrorBinaryTree(pNode,0); //得到镜像二叉树 //按前序遍历将节点中的value保存在一个数组中 int * preTraversal; preTraversal=(int *)malloc(n*sizeof(int)); if(preTraversal==NULL){ exit(EXIT_FAILURE); } memset(preTraversal,0,n*sizeof(int)); saveValueByPreTraversal(pNode,0,preTraversal,n); for(int i=0;i<n;i++){ printf("%d ",preTraversal[i]); } free(preTraversal); preTraversal = NULL; free(pNode); pNode = NULL; } if(n<=0){ printf("NULL\n"); continue; } } return 0; }
在调试的过程中,大概花了很长的时间才搞定,刚开始将将
mirrorBinaryTree(pNode,0); //得到镜像二叉树
放在
if(n>0){ }
模块之后,发现,永远输出的是全零的结果,经过调试发现:当我们将
mirrorBinaryTree(pNode,0);这行代码放在
if(n>0){}模块之后
pNode这个指针为NULL。解决方法就是将后面的代码放在
if(n>0){}模块之后即可。
相关文章推荐
- 最全前端面试问题及答案总结[目录]
- 网上看到的一道腾讯面试题
- 第4本:程序员修炼之道-从小工到专家(第七、八章)
- 第4本:程序员修炼之道-从小工到专家(第七、八章)
- 第3本:Visual Studio程序员箴言
- 第3本:Visual Studio程序员箴言
- 测试职业思考
- java面试题1
- 黑马程序员——Java语言基础
- 黑马程序员——多线程
- 黑马程序员——Java基础——同步
- 黑马程序员——Java基础——多线程
- 一个fork的面试题
- 黑马程序员——Java基础——反射
- 两道有趣的面试题
- 黑马程序员_java基础_反射
- 判定一棵二叉树是否是二叉搜索树
- 单链表及相关面试题
- java面试遇到问题三 -----final关键字和static关键字
- 做个有职业道德的程序员