DS05-查找
Posted xyx129221
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DS05-查找相关的知识,希望对你有一定的参考价值。
目录
0.PTA得分截图
1.本周学习总结
1.1 总结查找内容
1.2 谈谈你对查找的认识及学习体会
2.PTA题目介绍
2.1 7-1 是否完全二叉搜索树
- 题目
将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果。
输入格式:
输入第一行给出一个不超过20的正整数N;第二行给出N个互不相同的正整数,其间以空格分隔。
输出格式:
将输入的N个正整数顺序插入一个初始为空的二叉搜索树。在第一行中输出结果树的层序遍历结果,数字间以1个空格分隔,行的首尾不得有多余空格。第二行输出YES,如果该树是完全二叉树;否则输出NO。
输入样例1:
9
38 45 42 24 58 30 67 12 51
输出样例1:
38 45 24 58 42 30 12 67 51
YES
输入样例2:
8
38 24 12 45 58 67 42 51
输出样例2:
38 45 24 58 42 12 67 51
NO
- 代码
#include<iostream>
#include<string.h>//memset头文件是string.h,记成stdlib.h了
using namespace std;
int tree[100], num;
int N;
void AddTree(int i, int d);//加入到二叉搜索树中
int main()
{
int i = 0;
int j = 0;//j记录结点的总数量
int flag = 0;//flag记录输出的个数
cin >> N;//给出一个不超过20的正整数N
memset(tree, -1, sizeof(tree));//初始化树的所有结点为-1
for (i = 0; i < N; i++)//输入N个互不相同的正整数
{
cin >> num;
AddTree(1, num);//加入到二叉搜索树中
}
while (flag < N)
{
while (tree[j] == -1)//当j结点为-1,即该结点没有存入的数值
{
j++;//去下一个结点
}
if (flag)//不是0,前面需要输出空格
{
cout << " " << tree[j];
}
else//flag为0,即第一个,直接输出
{
cout << tree[j];
}
j++;
flag++;
}
if (j == N + 1)//j等于N+1,表示已经输出了N个数,因为j++是放在输出后面的
{
cout << endl << "YES";//需要换行
}
else
{
cout << endl << "NO";
}
}
void AddTree(int i, int d)//加入到二叉搜索树中
{
if (tree[i] == -1)//该结点为空,没有孩子
{
tree[i] = d;//将输入的数字存入该结点
return;
}
if (d > tree[i])//如果大于该结点
{
AddTree(i * 2, d);//函数递归找其左孩子继续判断,左子树与根节点位置的关系是2*i
}
else//如果小于该结点
{
AddTree(i * 2 + 1, d);//函数递归找其右孩子继续判断,右子树与根节点位置关系是2*i+1
}
//因为题目已经说明是N个互不相同的正整数,所以不用考虑等于
}
2.1.1 该题的设计思路
-
题面分析
- 首先这道题先要输入N,代表接下来要将N个数构建一棵二叉搜索树;然后接下来就是输入这N个数。
- 在构建二叉搜索树时,需要注意的是题干中的“定义为左子树键值大,右子树键值小”,也就是比父结点大的数在左孩子处,比父结点小的数在右孩子处,和我们平时构建的不一样;构建时还需要按照给定数字顺序来构建。
- 在输出时,需要层次遍历二叉搜索树,然后将遍历的结果输出,注意空格问题;当该二叉搜索树是完全二叉树(若设二叉树的深度为k,除第 k 层外,其它各层 (1~k-1) 的结点数都达到最大个数,第k层所有的结点都连续集中在最左边,这就是完全二叉树)时,输出“YES”;其他情况输出“NO”。
-
图文介绍
(1)完全二叉树:若设二叉树的深度为k,除第 k 层外,其它各层 (1~k-1) 的结点数都达到最大个数,第k层所有的结点都连续集中在最左边,这就是完全二叉树。
(2)样例1构建的二叉搜索树
层次遍历结果:38 45 24 58 42 30 12 67 51,符合完全二叉树,输出YES
(3)样例2构建的二叉搜索树
层次遍历结果:38 45 24 58 42 12 67 51,第三层的12没有兄弟,但是接下来还有第四层,所以不符合完全二叉树,输出NO
- 复杂度分析
- 建立二叉搜索树的时间复杂度为O(log2n),层次遍历二叉树的时间复杂度为O(n),所以总的时间复杂度为O(log2n)
2.1.2 该题的伪代码
tree[100]存储各结点的值
num为结点的数值
N为输入的数目
int main()
{
i为遍历序号
j记录结点的总数量
flag记录输出的个数
输入一个不超过20的正整数N
初始化树的所有结点为-1
for (i = 0 to i < N,i++)//输入N个互不相同的正整数
{
输入正整数num
调用函数AddTree()加入到二叉搜索树中,从1开始才能符合后面的结点间的2*i和2*i+1的关系
}
while (flag 小于 N)
{
while (tree[j]为 - 1)
{
该结点没有存入的数值,去下一个结点
}
if (flag不是0)
{
输出tree[j],且前面需要输出空格
}
else
{
直接输出tree[j]
}
j++,flag++
}
if (j 等于 N + 1)
{
换行输出YES
}
else
{
换行输出NO
}
}
void AddTree(int i, int d)
{
if (tree[i] 等于 - 1)
{
将输入的数字存入该结点
返回
}
if (d 大于 该结点tree[i])
{
函数递归找其左孩子继续判断,左子树与根节点位置的关系是2* i
}
else
{
函数递归找其右孩子继续判断,右子树与根节点位置关系是2* i + 1
}
}
2.1.3 PTA提交列表
- memset头文件应该是string.h,记成stdlib.h了,所以导致了编译错误
- 最后输出YES或者NO时的判断由于j++是放在输出后面的,所以应该是jN+1,不是jN
2.1.4 本题涉及的知识点
- memset函数:
- memset函数是计算机中C/C++语言初始化函数。作用是将某一块内存中的内容全部设置为指定的值,这个函数通常为新申请的内存做初始化工作。
- 本题我所使用的是memset()的深刻内涵是:用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化。例如:memset(a,‘ ‘,sizeof(a));
- memset函数在头文件:#include<string.h>中
- 运用了创建二叉树时左子树与根节点位置的关系是2i、右子树与根节点位置关系是2i+1的关系
- 判断是否是完全二叉树时通过j将遍历过的结点的数量记录下来,然后进行判断,且层次遍历直接按照下标顺序来判断即可
2.2 题目
- 题目
- 代码
2.2.1 该题的设计思路
2.2.2 该题的伪代码
2.2.3 PTA提交列表
2.2.4 本题涉及的知识点
2.3 7-5(哈希链) 航空公司VIP客户查询
- 题目
不少航空公司都会提供优惠的会员服务,当某顾客飞行里程累积达到一定数量后,可以使用里程积分直接兑换奖励机票或奖励升舱等服务。现给定某航空公司全体会员的飞行记录,要求实现根据身份证号码快速查询会员里程积分的功能。
输入格式:
输入首先给出两个正整数N(≤10^5)和K(≤500)。其中K是最低里程,即为照顾乘坐短程航班的会员,航空公司还会将航程低于K公里的航班也按K公里累积。随后N行,每行给出一条飞行记录。飞行记录的输入格式为:18位身份证号码(空格)飞行里程。其中身份证号码由17位数字加最后一位校验码组成,校验码的取值范围为0~9和x共11个符号;飞行里程单位为公里,是(0, 15 000]区间内的整数。然后给出一个正整数M(≤10^5),随后给出M行查询人的身份证号码。
输出格式:
对每个查询人,给出其当前的里程累积值。如果该人不是会员,则输出No Info。每个查询结果占一行。
输入样例:
4 500
330106199010080419 499
110108198403100012 15000
120104195510156021 800
330106199010080419 1
4
120104195510156021
110108198403100012
330106199010080419
33010619901008041x
输出样例:
800
15000
1000
No Info
- 代码
2.3.1 该题的设计思路
-
题面分析
- 首先理解题目数据:
- N表示的是接下来有N条飞行记录,但是这N条飞行记录的持有者都是会员。
- K表示的是会员的飞行里程的最低要求,其中需要注意的是低于K公里的航班也按K公里累积,即:比如规定最低里程K为20时,当某客户飞行里程为5,按照20算;飞行里程为20时,即为20;飞行里程超过20时,就按实际飞行里程计算。
- M表示的是要查询M个人的里程累积值,但是前提是这个人是会员,也就是前面所给的N条飞行记录里是否有这个人的身份证号码;如果他不是会员,即飞行记录里没有他,就输出No Info;格式上要注意每个查询结果占一行。
- 然后分析所给示例:
- 题目中首先给了4条飞行记录,以及最低飞行里程要求为500公里。
- 第一个和第二个要查询的人都是会员,且飞行里程都超过了500,所以输出其实际的飞行里程就可以。
- 而第三个要查询的人,4条记录中的第一条和第四条是这个人的,且都没有达到最低要求500,所以相当于是两个500,也就是身份证号为330106199010080419的这个人相当于累计了1000公里的飞行里程,所以输出的是1000。
- 第四个人,在前面的飞行记录中没有他的身份证号码,也就是说他不是会员,所以要No Info。
- 首先理解题目数据:
-
解题思路
-
复杂度分析
2.3.2 该题的伪代码
2.3.3 PTA提交列表
2.3.4 本题涉及的知识点
以上是关于DS05-查找的主要内容,如果未能解决你的问题,请参考以下文章