您的位置:首页 > 职场人生

《剑指Offer》面试题:二叉树的镜像

2015-09-20 20:01 411 查看
题目:二叉树的镜像

在完成此题目时,具体的测试要求见下面。

先说下完成此题目的感受:刚开始在《剑指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){}
模块之后即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: