第7章 PTA查找练习题

这道题与第7章查找有关,当时提前看到,翻到书里面的算法,然后打进去,虽然是正确的,但是那时候并不知道二叉排序树的基础知识,包括插入查找的来龙去脉,现在已经学到了,有了一定了解,发现题目只用到了其中部分性质,主要还是树那一章的知识。

 是否同一棵二叉搜索树

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。

输入格式:

输入包含若干组测试数据。每组数据的第1行给出两个正整数NN (\le 1010)和LL,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出NN个以空格分隔的正整数,作为初始插入序列。最后LL行,每行给出NN个插入的元素,属于LL个需要检查的序列。

简单起见,我们保证每个插入序列都是1到NN的一个排列。当读到NN为0时,标志输入结束,这组数据不要处理。

输出格式:

对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。

输入样例:

4 2
3 1 4 2 3 4 1 2 3 2 4 1 2 1 2 1 1 2 0 

输出样例:

Yes
No
No

我的做法很直接,就判断建立的二叉搜索树各结点是否一致
#include<iostream>
using namespace std;

typedef struct BSTnode
{
    int data;//数据域 
    struct BSTnode *l,*r;
}BSTnode,*BSTree;

void insert(BSTree &T,int e)//二叉搜索树的插入 
{
    if(!T)//插入第一个数 
    {    BSTnode *S; 
        S=new BSTnode;
        S->data=e;
        S->l=S->r=NULL;
        T=S;
    }
    else if(e<T->data)//将待插入的数按二叉搜索树定义进行插入 
    insert(T->l,e);
    else if(e>T->data)
    insert(T->r,e);
}

void create(BSTree &T,int m)//建立树 
{
    T=NULL;
    int e,i;
    for(i=0;i<m;i++)
        {
            cin>>e;
        insert(T,e);
        }
    
}

bool compare(BSTree T,BSTree t)//判断是否为同一棵树 
{
    
    if(T==NULL && t==NULL)
        return true;
    else if((T==NULL && t!=NULL)||(T!=NULL && t==NULL))
        return false;
    else if((T!=NULL && t!=NULL)&&(T->data != t->data))
            return false;
    return (compare(T->l,t->l)&&compare(T->r,t->r)); 
}

int main()
{
    BSTree t,t1;
    t=NULL;
    int m,n,j;
    cin>>m;
    while(m)//这里主要是根据题目要求进行比较和输出 
    {    cin>>n;
        create(t,m);
        for(j=0;j<n;j++)
        {
        create(t1,m);
        if(compare(t,t1)) cout<<"Yes\n";
        else cout<<"No\n";
        }
        cin>>m;
    }
    return 0;
}

在比较两棵树的compare函数中,运用了递归,这次我的递归思想算是有了进步,不去考虑下一层的情况了,只要保证本层所有情况都考虑到就行。

 

 

7-1 QQ帐户的申请与登陆 (30 分)
 

 

实现QQ新帐户申请和老帐户登陆的简化版功能。最大挑战是:据说现在的QQ号码已经有10位数了。

输入格式:

输入首先给出一个正整数N(≤),随后给出N行指令。每行指令的格式为:“命令符(空格)QQ号码(空格)密码”。其中命令符为“N”(代表New)时表示要新申请一个QQ号,后面是新帐户的号码和密码;命令符为“L”(代表Login)时表示是老帐户登陆,后面是登陆信息。QQ号码为一个不超过10位、但大于1000(据说QQ老总的号码是1001)的整数。密码为不小于6位、不超过16位、且不包含空格的字符串。

输出格式:

针对每条指令,给出相应的信息:

1)若新申请帐户成功,则输出“New: OK”;
2)若新申请的号码已经存在,则输出“ERROR: Exist”;
3)若老帐户登陆成功,则输出“Login: OK”;
4)若老帐户QQ号码不存在,则输出“ERROR: Not Exist”;
5)若老帐户密码错误,则输出“ERROR: Wrong PW”。

输入样例:

5
L 1234567890 myQQ@qq.com
N 1234567890 myQQ@qq.com
N 1234567890 myQQ@qq.com
L 1234567890 myQQ@qq
L 1234567890 myQQ@qq.com

输出样例:

ERROR: Not Exist
New: OK
ERROR: Exist
ERROR: Wrong PW
Login: OK

刚开始做这道题目的时候,并没有想到用map映射容器,原因一个是对于map用法不太了解,一个是想尝试用学过的知识解决问题。所以,我第一次用的是简单的结
构体,代码如下:
#include<iostream>
#include<cstring>
using namespace std;
typedef struct info
{
    int account;
    string password;
}info;

int main()
{
    int i,n,num;
    char x;
    string s;
    info I;
    I.account=0;I.password=" ";
    cin>>n;
    for(i=0;i<n;i++)
    {
        cin>>x>>num>>s;
        if(x=='L')
        {
            if(I.account==0)
            cout<<"ERROR: Not Exist\n";
            else 
            {
                if(I.account==num&&I.password==s)cout<<"Login: OK\n";
                else cout<<"ERROR: Wrong PW\n";
            }
            
        }
        if(x=='N')
        {
            if(I.account==0||I.account!=num)
            {
                I.account=num;I.password=s; cout<<"New: OK\n";
            }
            else
                cout<<"ERROR: Exist\n";
        }
    }
}
View Code

勉强通过2个测试点,第3个没能过原因是上面的程序只能解决申请账号问题,不能保存申请几个之后对应的账号密码,也就是没有保存功能,测试几组数据情况不正确,后来我尝试修改了一下,用了结构体数组,但是代码变得很复杂;这是我就想,这样不如学习一下map用法,参考了网上一些资料还有STL书籍,简单知道map的存储结构,然后发现只需要简单修改一下之前那个程序就好了。

#include<iostream>
#include<map> //map映射容器,它的元素数据由一个键值和一个映射数据组成一一映照的关系
#include<cstring>
using namespace std;

int main()
{
    int n,i;
    char x;
    string y,z;
    map<string,int>p; //map对象p作为判断,检查账号是否存在
    map<string,string>p1;//map对象p1作为存储申请的账号密码
    cin>>n;
    for(i=0;i<n;i++)
    {
        cin>>x>>y>>z;
        if(x=='L')
        {
            if(p[y]==0) cout<<"ERROR: Not Exist\n";//在创建map对象p时候,内部初始化int的映射数据为0,所以可作为判断条件
            else 
            {
                if(p1[y]!=z) cout<<"ERROR: Wrong PW\n";//检查账号密码是否正确
                else cout<<"Login: OK\n";
            }
        }
        if(x=='N')
        {
            if(p[y]==1) cout<<"ERROR: Exist\n";//申请的账号已经存在
            else 
            {
                p[y]=1;//新申请的账号如果未重复,则标记此账号现已申请
                p1[y]=z;//并将账号密码保存到p1中
                cout<<"New: OK\n";
            }
        }
    }
    return 0;
}
View Code

创建map<key,value> m; 但单映射map中 key和 value 是一对一的关系,不允许重复键值存在,而multimap多映射允许重复键值存在,可以是一对多的关系。map在这道题目上非常好用简单。其实还有解决题目的其他方法,比如用哈希查找法,不过限于目前的能力,还不能够写出来,还需多多学习!

 

转载于:https://www.cnblogs.com/chenzhenhong/p/10962825.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PTA_基础编程答案_整 包括但不限于如下 7-1 厘米换算英尺英寸 15 27785 103313 0.27 7-2 然后是几点 15 20063 78572 0.26 7-3 逆序的三位数 10 24732 62644 0.39 7-4 BCD解密 10 14066 23357 0.60 7-5 表格输出 5 15169 36439 0.42 7-6 混合类型数据格式化输入 5 15719 36076 0.44 7-7 12-24小时制 15 14687 51855 0.28 7-8 超速判断 10 15328 39238 0.39 7-9 用天平找小球 10 15145 33252 0.46 7-10 计算工资 15 14241 35238 0.40 7-11 分段计算居民水费 10 12907 35261 0.37 7-12 两个数的简单计算器 10 12912 33359 0.39 7-13 日K蜡烛图 15 9280 34024 0.27 7-14 求整数段和 15 11461 55664 0.21 7-15 计算圆周率 15 9826 33135 0.30 7-16 求符合给定条件的整数集 15 8986 21898 0.41 7-17 爬动的蠕虫 15 9739 24881 0.39 7-18 二分法求多项式单根 20 7282 31752 0.23 7-19 支票面额 15 7375 21837 0.34 7-20 打印九九口诀表 15 10325 35138 0.29 7-21 求特殊方程的正整数解 15 7799 22600 0.35 7-22 龟兔赛跑 20 7446 29142 0.26 7-23 币值转换 20 4333 18467 0.23 7-24 约分最简分式 15 6728 15335 0.44 7-25 念数字 15 6724 20180 0.33 7-26 单词长度 15 5648 37409 0.15 7-27 冒泡法排序 20 7255 24045 0.30 7-28 猴子选大王 20 6144 13327 0.46 7-29 删除字符串中的子串 20 4798 15074 0.32 7-30 字符串的冒泡排序 20 4752 14741 0.32 7-31 字符串循环左移 20 4527 13605 0.33 7-32 说反话-加强版 20 4030 25470 0.16 7-33 有理数加法 15 4476 10862 0.41 7-34 通讯录的录入与显示 10 4323 19524 0.22 7-35 有理数均值 20 3281 17202 0.19 7-36 复数四则运算 15 2530 10103 0.25 7-37 整数分解为若干项之和 20 2437 4673 0.52 7-38 数列求和-加强版 20 4692 35190 0.13 当前显示1 - 38项,共38项

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值