DS博客作业07--查找

1.本周学习总结

思维导图

谈谈你对查找运算的认识及学习体会

在学习本章的知识前,我们得先掌握之前的二叉树的内容,这样才能顺利的掌握课本知识。在编程前要先想清楚思路再开始写代码,灵活地利用书上的知识。对于书上的算法代码,我们一定要仔细钻研每一步的具体含义和目的,在此基础上深入的了解算法的实现过程,在查找时利用书中给出的各种方法可以极大地减少时间复杂度,从而提高查找速度,使算法更加简单。很多时候单看书上的内容会觉得很简单,但是真正做起来又很容易忘东忘西,所以增加实际应用经验很重要。

2.PTA实验作业

2.1.题目1:QQ帐户的申请与登陆

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

2.1.1设计思路

main函数{
定义整型数N;
定义字符 c;
输入N;
定义结构体数组a[N];
定义map QQ;
for i=0 to N
    输入c,a[i].qq,a[i].code;
    if 输入‘N’  //注册账号
        if QQ.find(a[i].qq)等于QQ.end() //map查找qq账号,如果账号不存在
            QQ[a[i].qq]=a[i].code;
            输出"New: OK"; //账号创建成功
        else 输出“ERROR: Exist”; //qq账号已存在,创建失败
    else if 输入‘L’ //登录账号
    if QQ.find(a[i].qq)等于QQ.end()  //map查找qq账号,如果账号不存在 
        输出"ERROR: Not Exist";
    else
        if QQ[a[i].qq]等于a[i].code  //如果账号和密码匹配成功 
            输出“Login: OK”;
        else
            输出“ERROR: Wrong PW”;

return 0;
        
}

2.1.2代码截图


2.1.3本题PTA提交列表说明

  • 本来想的思路比较复杂,但后来发现用map会很简单。
  • 在登录的那几行代码中因为if else语句叠了三层所以有些逻辑混乱,导致老是找不出错误原因。

2.2.题目2:二叉搜索树中的最近公共祖先

在一棵树T中两个结点u和v的最近公共祖先(LCA),是树中以u和v为其后代的深度最大的那个结点。现给定某二叉搜索树(BST)中任意两个结点,要求你找出它们的最近公共祖先。

2.2.1设计思路

LCA函数{
定义两个树节点指针t,s;
定义一个flag;
if 树为空 返回 ERROR
while t不为空
    if 当前节点等于u
        flag++;
        break;
    else if 当前节点大于u 
        t等于它的左孩子
    else t等于它的右孩子
while s不为空
    if 当前节点等于v
        flag++;
        break;
    else if 当前节点大于v 
        t等于它的左孩子
    else t等于它的右孩子

if flag不等于2说明u,v有一个不在二叉树内,返回ERROR

while T的左右孩子有一个不为空
    if T.Key等于u或者等于v 
        return T->Key;
    if T->Key大于u且T->Key小于v或T->Key小于u且T->Key大于v
        return T->Key;
    if T->Key 大于 u和v
        T等于它的左孩子;
    if T->Key 小于 u和v
        T等于它的右孩子;
}

2.2.2代码截图


2.2.3本题PTA提交列表说明

  • Q1:刚开始提交只对了三个测试点,发现是检查u和v是否在二叉树的代码有误。
  • A1:将两个循环中的else if语句中的条件修改了。
  • Q2:当LCA是本身时的测试点过不去。
  • A2:添加了补充条件后仍过不了,发现是总的循环条件写错了,导致只能遍历到左右孩子都有的节点,最后把&&改成||就对了。

2.3.题目3:二叉搜索树的操作集

本题要求实现给定二叉搜索树的5种常用操作。

2.3.1设计思路


Insert函数{
    if BST为空
        BST->Data等于X;
        BST的左右孩子都置为空;
    else if X不等于BST->Data
        if X小于BST->Data
            BST->Left等于Insert(BST->left,X);
        else
            BST->Left等于Insert(BST->left,X);
return BST;
}

Delete函数{
定义树节点 q;
if BST为空 输出"Not Found\n";
else{
	if(X小于BST->Data)
		BST左孩子等于Delete(BST->Left,X);
	else if(X大于BST->Data)
	{
		BST右孩子等于Delete(BST->Right,X);
	}
	else  //考虑如果找到这个位置,并且有左节点或者右节点或者没有节点三种情况
        {
            if BST的左右孩子都在 {
                q=FindMin(BST->Right);  
                BST->Data=q->Data;
                BST->Right=Delete(BST->Right,BST->Data);
            }
            else
            {                                
                q=BST;
                if(左孩子为空) BST = BST->Right;       
                else if(右孩子为空) BST = BST->Left;
                释放q;                         
            }
       }
	}
	return BST;
}

Find函数{
    if(BST为空) return NULL;
    if(BST->Data等于X) return BST;
    else if(X小于BST->Data) {
        return Find(BST->Left,X);
    }
    else if(X大于BST->Data)
    {
        return Find(BST->Right,X);
    }
    return BST;
}

FindMin函数{
    if(BST不为空)
    {
        while(BST的左孩子不为空)
            BST=BST->Left;
    }
    return BST;
}

FindMax函数{
    if(BST不为空)
    {
        while(BST的右孩子不为空)
             BST=BST->Right;
    }
    return BST;
}

2.3.2代码截图




2.3.3本题PTA提交列表说明

  • 在写删除函数代码时,参考书上的思路会时自己的思路比较清晰

3.阅读代码

3.1 题目:是否完全二叉搜索树

3.2 解题思路

完全二叉树的定义是:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边。
因为右子树的结点编号是父节点的两倍,而左子树的结点编号是父节点的两倍加一,所以可以用数组模拟建树的过程。最后题目要求层序输出,直接按编号大小输出。而最后一行的结点编号和n相等。

3.3 代码截图


3.4 学习体会

本题定义了一个数组a来模拟建树的过程使代码变得更加简单,这要求要掌握完全二叉树的概念和性质,了解左子树的结点编号和它父结点的结点编号的关系。在判断是否为完全二叉树时,他巧妙地利用结点数和i来判断。当置数组a的初值时他用到了memset函数,但我们自己在使用memset时要千万小心,要知道在给char以外的数组赋值时,只能初始化为0或者-1。

posted @ 2019-06-14 15:35  chianun  阅读(199)  评论(0编辑  收藏  举报