DS博客作业07--查找
DS博客作业07--查找
1.本周学习总结
1.思维导图
2.谈谈你对查找运算的认识及学习体会。
···
查找这一章最主要的是二叉排序树、平衡二叉树、哈希表。
1.二叉排序树
用中序输出可以判断这棵树是否为二叉排序树,如果中序输出的数值是从小到大,即为二叉排序树,反之则不是。还有,二叉排序树的删除要会操作,二叉树的操作最好是和画图相结合。
2.平衡二叉树
平衡二叉树其实是对二叉排序树的调整,在插入的过程中不断的调整,在调整的过程中,一定是要在新插入结点向根方向查找第一个失去平衡的结点。
3.哈希表
哈希表要学会构造,无论是散列表还是哈希链,都要清楚的知道它的长度应该是多少,散列表的长度是根据长度=元素个数/装填因子得出来,哈希链得长度则是k mod p中的p决定。还有ASL的计算也非常容易出错,要分清楚如何计算。
···
2.PTA实验作业(6分)
2.1.题目1:6-2 是否二叉搜索树
本题要求实现函数,判断给定二叉树是否二叉搜索树。
2.1.1设计思路(伪代码)
设计思路:
一棵二叉排序树的中序遍历数值是从小到大的,所以判断树的中序遍历就好咯。
伪代码
定义全局变量tree[]用于存放中序遍历的顺序;
定义全局变量i用于控制将结点存进数组;
IsBST
{
定义j为循环变量;
if 树为空 then
return ture;
end if
if 树不为空 then
tree[i++]=树的中序遍历;
end if
for j=0 to i-1 do
if tree[j]>=tree[j+1]即中序遍历的数值没有从小到大 then
return false;
end if
end for
return true;
}
2.1.2代码截图
2.1.3本题PTA提交列表说明。
- Q1:编辑错误是因为不知道为什么我的电脑直接在pintia上的输入会是中文(已经调成英文输入法),所以一直错。
- A1:只好在Dev-C++上面打出来再复制粘贴。
- Q2:部分正确,样例2一直过不去。
- A2:我想的是把tree数组里面存放树中序遍历,结果写代码的时候把tree数组其实一直在改变,应该把tree数组设计成全局变量。
2.2.题目2:6-3 二叉搜索树中的最近公共祖先
在一棵树T中两个结点u和v的最近公共祖先(LCA),是树中以u和v为其后代的深度最大的那个结点。现给定某二叉搜索树(BST)中任意两个结点,要求你找出它们的最近公共祖先。
2.2.1设计思路(伪代码)
伪代码
if 树为空 then
return ERROR;
end if
定义flag1判断u是否在树中;
定义flag2判断v是否在树中;
定义index为下标;
定义Tree类型 指针p;
定义Tree类型 qu队列(用于层次遍历)
先将根节点入队;
while 队不空 do
p指向队首;
if 找到u then
flag1 = 1;
end if
if 找到v then
flag2 = 1;
end if
if p有左孩子 then
左孩子入队;
end if
if p有右孩子 then
右孩子入队;
end if
end while
if u和v都在树中 then
if 先到达u或v then
则当前结点为最近祖先结点;
end if
if u左v右或u右v左 then
当前结点为最近祖先结点;
end if
if u大于当前key then
递归右子树;
end if
if u小于当前key
递归左子树;
end if
end if
if u和v不都在树中 then
return ERROR;
end if
2.2.2代码截图
2.2.3本题PTA提交列表说明。
这题为借鉴的代码。
- Q1:老师上课说过这道题,单独用一个find函数来递归实现查找u和v,但这题是函数没有办法建一个find函数。
- A1:改用采用层次遍历来做到查找。
2.3.题目3:7-1 QQ帐户的申请与登陆
实现QQ新帐户申请和老帐户登陆的简化版功能。最大挑战是:据说现在的QQ号码已经有10位数了。
输入格式:
输入首先给出一个正整数N(≤10
5
),随后给出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”。
2.3.1设计思路(伪代码)
设计思路:
用STL的map容器,然后分‘N’和‘L’判断账号和密码是否匹配。
伪代码
定义n为操作次数;
定义order存放命令字符;
定义name为账号;
定义password为密码;
定义map容器QQ;
输入n
while n-- do
输入order;
if order='N' then
输入账号密码;
// 用是否存在键值对判断是否已经有该账号
if 该账号已经存在 then
输出ERROR:Exist;
end if
if 该账号不存在 then
创建name-password键值对;
输出NEW:OK;
end if
end if
if order='L' then
输入账号密码;
if 该账号已经存在 then
if 键值对正确匹配 then
输出Login:OK;
end if
if 键值对匹配不成功 then
输出ERROR:Wrong PW;
end if
end if
if 该账号不存在 then
输出ERROR:Not Exist
end if
end if
end while
2.3.2代码截图
2.3.3本题PTA提交列表说明。
- A1:这题用了STL的map容器,首先需要#include
- Q2:多种错误
- A2:把所有的输出语句全部重新复制粘贴题目的,就好了,忽略了“:”是中文字符。
- Q3:键值判断写错了
- A3:把它改一下就好咯。
3、阅读代码(-2--2分)
3.1 题目
给出二叉搜索树的根节点,该二叉树的节点值各不相同,修改二叉树,使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
节点的左子树仅包含键小于节点键的节点。
节点的右子树仅包含键大于节点键的节点。
左右子树也必须是二叉搜索树。
示例:
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
提示:
树中的节点数介于 1 和 100 之间。
每个节点的值介于 0 和 100 之间。
给定的树为二叉搜索树。
3.2 解题思路
根据二叉搜索树的定义,大于根结点的值都在右子树上,小于根结点的值都在左子树上,于是此题要求将二叉搜索树转变为更大和树,便可等价为求某个节点右边的节点和加上当前节点值(这个值就是题目所说的更大和)赋值给当前节点的新树,那么如何求这个更大和呢?根据二叉搜索树的性质,我们只需按照反转的中序遍历即可求到某个节点的更大值和。
3.3 代码截图
3.4 学习体会
这道题的更大和树其实就是求左右孩子结点与本结点的和,将他们重新构造成树。或许重新转换成树可以想到,但利用反转的中序遍历来求结点的更大值之和真的是令人窒息的操作。