钟海清

导航

DS博客作业07-----查找

1.本周学习总结

1.思维导图

2.对查找运算的认识及学习体会

查找的PTA题目集比前面树和图的更好做,他对编程的要求不是那么高,只要掌握几种查找的思想,然后利用递归一直找下去就好,代码量上面减少很多。而且,越学习到后面,发现容器越好用,比如编程第一题,就利用map容器来解决账号存在问题,非常方便。通过PTA练习,我对map容器的了解也越来越多,这次在账号与密码配对上又运用到了。map中的find函数定位数据出现的位置,它返回一个迭代器,当数据出现时,它返回数据所在位置的迭代器;如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器,这样就实现查找目的。还有就是map<int, int>的元素是key-value对,而first和second分别对应key和value,it->first返回当前元素的关键字,it->second返回当前元素的值,查找密码对不对就用到了这个知识点。

2.PTA实验作业

2.1.题目1:二叉搜索树的操作集

  • 函数Insert将X插入二叉搜索树BST并返回结果树的根结点指针;
  • 函数Delete将X从二叉搜索树BST中删除,并返回结果树的根结点指针;如果X不在树中,则打印一行Not Found并返回原树的根结点指针;
  • 函数Find在二叉搜索树BST中找到X,返回该结点的指针;如果找不到则返回空指针;
  • 函数FindMin返回二叉搜索树BST中最小元结点的指针;
  • 函数FindMax返回二叉搜索树BST中最大元结点的指针。
输入样例:
10
5 8 6 2 4 1 0 10 9 7
5
6 3 10 0 5
5
5 7 0 10 3

输出样例:
Preorder: 5 2 1 0 4 8 6 7 10 9
6 is found
3 is not found
10 is found
10 is the largest key
0 is found
0 is the smallest key
5 is found
Not Found
Inorder: 1 2 4 6 8 9

2.1.1设计思路

  • 插入函数

if(空树)
    新建叶子节点,并将X的值存入
else
    if(X<当前遍历节点的值)
        递归遍历左子树
    else
        递归遍历右子树
  • 删除函数

- if(空树或者遍历完都没找到)
    输出Not Found
- else if(X<当前节点的值)
    递归遍历左子树
- else if(X>当前节点的值)
    递归遍历右子树
- else(相等也就是找到了要删除的节点)
    - if(该节点有两个子树)
        定义变量tmp接收查找最大值函数返回的值
        将左子树的最大节点作为新的父亲节点
        调整左子树孩子间关系
    - else(有一个或没有子树)
        tmp暂存该节点的值
        - if(左孩子为空)
            将右孩子作为父亲节点
        - else
            将左孩子作为父亲节点
        free(tmp)释放该节点
return 根节点
  • 查找函数

- if(空树或找到节点)return 根节点BST
- else
    - if(节点值>X)递归遍历左子树
    - else 递归遍历右子树
  • 找最大值函数

- if(树不空)
    while循环遍历找到最右边节点
    根据二叉搜索树特点,此节点是最大的
返回 BST
  • 找最小值函数

与找最大值函数方法一样,遍历找到最左边节点即为最小值
输入样例:
10
5 8 6 2 4 1 0 10 9 7
5
6 3 10 0 5
5
5 7 0 10 3
输出样例:
Preorder: 5 2 1 0 4 8 6 7 10 9
6 is found
3 is not found
10 is found
10 is the largest key
0 is found
0 is the smallest key
5 is found
Not Found
Inorder: 1 2 4 6 8 9

2.1.2代码截图

  • 插入函数

  • 删除函数


  • 查找函数

  • 找最大值函数

  • 找最小值函数

2.1.3本题PTA提交列表说明

2.2 题目2:是否二叉搜索树

2.2.1设计思路

判断是不是二叉搜索树首先想到了老师说的用中序遍历的方法,如果他是递增数列,那么就是一棵二叉搜索树
利用中序遍历思想首先有个问题要解决,就是这么存储遍历的节点值的问题,使得他可以和前一个比较
第一个想到的是数组,但发现这是一个函数题,不能自己随便定义,后面查资料发现可以把数组定义写在函数外面作为全局变量】
如下代码:
定义数字a【100】存储树节点的值
定义IsBST函数利用递归中序遍历判断是不是二叉搜索树
    if(树不空)
        递归遍历左子树
        将节点的值存入数组a,变量 i 记录数组长度
        递归遍历右子树
    end if
    for循环遍历数组 a 
        if(数组后面的值大于他前面的值)
            return false
    循环完后没问题就return true

另外一种思路就是不开数组,定义一个中间变量temp,边遍历边比较
temp一开始给它一个初值为负无穷
- IsBST递归遍历左子树
让所遍历的节点值和temp比较
- if(节点值>temp)//符合要求
    temp保存该节点的值
- else
    return false
- IsBST递归遍历右子树

2.2.2代码截图

2.2.3本题PTA提交列表说明

2.3 题目3:QQ帐户的申请与登陆

输入格式:
输入首先给出一个正整数N(≤100000)随后给出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

2.3.1设计思路

定义map容器存放账号和密码
- 主函数
登入类型,账号和密码定义为string类型,一开始我在想空格读进去不就一整串了吗,后面查一下发现c++中string一般遇到空格就结束
for循环输入并判断合不合法

- 判断合法性函数
定义字符串str并初值为N
- if(type为N)//注册
    - if(未找到该账号)
        该账号对应的密码为password
        输出New:OK
    - else该账号已存在
        输出ERROR:Exist
- else//登入
    - if(未找到账号)
        输出ERROR:Not Exist
    - else//判断密码正不正确
        - if(该账号对应的密码为输入的password)
            输出Login:OK
        - else 输出ERROR:WrongPW

2.3.2代码截图

  • 主函数

  • 判断函数

2.3.3本题PTA提交列表说明

  • Q1:主函数中加上insert函数会出现如下错误

  • A1:查了一下就是叫你不要画蛇添足写这句的意思,噗。。。

2.4题目4:航空公司VIP客户查询

现给定某航空公司全体会员的飞行记录,要求实现根据身份证号码快速查询会员里程积分的功能。
输入格式:
输入首先给出两个正整数N(≤100000)和K(≤500)。其中K是最低里程,即为照顾乘坐短程航班的会员,航空公司还会将航程低于K公里的航班也按K公里累积。随后N行,每行给出一条飞行记录。飞行记录的输入格式为:18位身份证号码(空格)飞行里程。其中身份证号码由17位数字加最后一位校验码组成,校验码的取值范围为0~9和x共11个符号;飞行里程单位为公里,是(0, 15 000]区间内的整数。然后给出一个正整数M(≤100000)随后给出M行查询人的身份证号码。
输出格式:
对每个查询人,给出其当前的里程累积值。如果该人不是会员,则输出No Info。每个查询结果占一行。
输入样例:
4 500
330106199010080419 499
110108198403100012 15000
120104195510156021 800
330106199010080419 1
4
120104195510156021
110108198403100012
330106199010080419
33010619901008041x
输出样例:
800
15000
1000
No Info

2.4.1设计思路

定义容器map,这题主要是身份证号那里,用整形存储肯定查找时间复杂度巨大,所以巧妙运用了字符类型,同时也简化了查找
IdNumber为char类型,distance为long long类型
- for循环输入航班信息
    - if(里程<最小里程)distance赋值为最小里程k
    - if(未找到该身份证)//第一次坐飞机
       将distance作为idNumber的value
    - else//第二次乘坐
        - 对应idNumber的value加上distance
end for
- for循环读入身份证信息
    - if(为找到该身份证)
        输出“No Info”
    - else
        输出对应idNumber下的value

2.4.2代码截图


2.4.3本题PTA提交列表说明

3.阅读代码

3.1 题目:打印学生选课清单


3.2 解题思路

此题是将字符型课程类型转换为数字型,定义容器存放学生个数
核心算法思路:
- for循环输入数据
    int h=shu(name);//将名字转换成数字存在h中
    stu[h].push_back(id)//将书号放于名字对应的堆里面,构成一个数组栈
- for循环遍历查找数据
    将前来查找学生的名字换成数字h
    利用sort函数对数字h里面的课程从小到大进行排序
    s=学生h的课程数,此处直接调用库函数size()即可
    后面就可以进行输出操作了

3.3 代码截图

3.4 学习体会

这题主要巧在利用容器解决查找问题。题目要求的是输出每个前来查询学生选的课程数,那么就顺着题目思路来,将课程划分到每一个学生后面,这样查找的时候,直接输入学生名字就可以输出对应的课程。此处还有一个就是sort排序函数,原来我只知道他适用于数组,用法为sort(数组名,长度),看完这题发现还可以写成sort(begin,end),其实思想是一样的,就是写法不同。看一些大佬写的代码,总能发现一些有意思的东西,代码简短然后会有一些没见过的代码,学习后到后发现还蛮好用的,学无止境!

posted on 2019-06-16 15:37  haiqingz  阅读(295)  评论(0编辑  收藏  举报