九度online judge-二叉搜索树

题目来源:http://ac.jobdu.com/problem.php?pid=1008

我的代码:已ac

 //  二叉搜索树

//scanf每遇到(空格  回车 跳格键 非法输入)时作为一个数据的输入结束,

//而不是scanf函数的结束,scanf函数    只有在每一个数据域均有数据 回车后才结束

//也就是说,比如 scanf("%s",str) 输入 i love you 回车   输出时只输出 i   %s接收了i作为其数据,并在回车后结束函数scanf   但注意!!!love you 字符串还在缓冲区

//对于%c   把空格和转义字符也都作为一个字符


#include <iostream>

#include <stdio.h>

#include <string>

#include <stdlib.h>   //int atoi(const char* nptr)将字符转换为整数

using namespace std;

int p[21][1024];


void erchasort(int i,int array[][1024],int a,int current){

    if(a<array[current][i]){

        if(array[current][2*i]==-1)

            array[current][2*i]=a;

            else

                erchasort(2*i,array,a,current);

    }

    else if(a>array[current][i]){

        if(array[current][2*i+1]==-1)

            array[current][2*i+1]=a;

        else

            erchasort(2*i+1,array,a,current);

    }

}


int main(){

    int n=0;

    while(scanf("%d",&n)!=EOF){

        if (n==0) break;

        for(int i=0;i<21;i++)        //要时刻注意这种初始化问题!!!

            for(int j=0;j<1024;j++)

                p[i][j]=-1;

        for(int j=0;j<=n;j++){

                            //输入一个序列p[0][],随后输入n个序列p[i][](i>0)

                            //对于一个序列,如果第t个数据后面第数小于这个数据,就存在array[2*t-1]中,如果大于它就存在array[2*t]中,如果相等就忽略

            char tem[10];   //用于存储每次输入的待比较序列

            int tep[10];

            int tag=0;//上一个数据所在位置

            scanf("%s",tem);

                for(int i=0;i<10&&tem[i]!=0;i++){

                   // tep[i]=atoi(&tem[i]);  //atoi的用法

                    tep[i]=(int)(tem[i])-48;

                  //  cout<<"tep["<<i<<"]="<<tep[i]<<endl;

                    if(tag==0){

                        tag=1;

                        p[j][1]=tep[i];

                    //    cout<<p[i][1];

                    }

                    else

                        erchasort(1,p,tep[i],j);

                   }

                

           }

        for(int i=1;i<=n;i++){

            int j=1;

            for(;j<=1024;j++)

                if(p[i][j]!=p[0][j]){

                    cout<<"NO"<<endl;                //cout<<"p[0]["<<j<<"]="<<p[0][j];cout<<"p["<<i<<"]["<<j<<"]="<<p[i][j];

                    break;}

            if (j==1025) cout<<"YES"<<endl;

            //   else cout<<"NO"<<endl;

        }

    }

    

    

    return 0;

}


首先,这是数据结构中非常典型的二叉排序树,它的存储方式即为当来到一个数据时,

1.首先查看根节点是否有数据,若没有,该数据即为根节点;

2.若根节点已存在,比较该数据与根节点数据的大小,若相等,忽略,不做任何操作,若比根小,插入到左子树,若比根大,插入到右子树;

3.要注意二叉树的存储方式    若节点下标为i, 其左孩子坐标为2*i,右孩子坐标为2*i+1   根节点下标为1.    二维数组 p[n][m]用来存储各个二叉树,所以n=21,考虑到特殊情况二叉树如果十个节点都是右孩子的情况,则需要存储单元为 1+2+2^2+...+2^9=1023 因根节点下标从1开始,所以m=1024  ( 这里可以发现二叉树的顺序存储方式是比较浪费空间的,但是查找速度比较快)。

按照上述方法,可以看出用递归可以很容易实现void  erchasort (int i,int array[][1024],int a,int current);



我自己遇到的问题是处理输入数据:scanf函数

scanf函数经常困惑我的是如何判断输入结束,因为它常会被用到这种形式  while(scanf(...)!=EOF){...}  可能有多组输入,而每运行一次scanf ()作为一组输入 。回车并不代表一次输入的结束!!  scanf每遇到空格/回车/跳格键以及非法输入时作为一个输入数据的结束,如果它的数据域中还有每接收到数据的情况,它会等到再次收到数据时作为下一个数据域的数据,只有在每一个数据域均收到数据时,回车,本次scanf函数才算结束。

另外,还要特别注意键盘盘缓冲区中的数据。比如 scanf("%s",str) 输入 i love you 回车   输出时只输出 i   %s接收了i作为其数据,并在回车后结束函数scanf   但注意!!!love you 字符串还在缓冲区。

当在括号参数中固定输入的格式时,我们可以很容易判断输入完成(这种情况一般是我们肯定地知道一组输入数据的数目),但是,当一组输入数据的个数是不确定时,我们最好把输入当作字符串处理。注意,scanf接收的是没有空格的字符串,若希望把带有空格的输入均作为一次输入,可以使用gets()函数。

本题中的情况是输入多个一位的数字,我们可以接收后转化为数字(之前是想利用atoi函数,但是发现它将当前指针指向的字符到结尾的一次全部转化,然后作为一个int整数,这不是我们本题中所希望的),所以手动的利用ascii进行转换。

写程序的时候逻辑关系一定要清楚,比如一些初始条件的设定(下标从0还是1开始)、一些条件的判断、代码片段之间的关系(比如本题中for循环是放到while循环的里面还是外面),一些逻辑错误可能会导致无限循环,很多错误其实都是很简单的。

还有特别注意每次的初始化问题!!不注意的话很容易将上次处理的结果遗留到本次处理中来,从而影响结果的正确性。实现所需要的功能是目的,利用技巧节省时间或空间是次要的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值