数据结构查找(二分、分块、折半、哈希查找)

一、解答

1. 衡量查找性能的标准是什么?
衡量查找性能的标准是平均查找长度,即对表中任何元素查找次数的期望值。平均查找长度描述了某一种查找算法在某一种查找表中整体的查找性能。查找成功的平均查找长度是找到表中每一个元素的可能比较次数的总平均值,查找不成功的平均查找长度是查找在表中没有的元素的可能比较次数的总平均值。

2. 比较在无序顺序表中从前向后顺序查找和从后向前顺序查找各有什么优点?
如果表中有多个数据与给定值相等的元素,从前向后查找可以首先找到位于最前面的元素,而从后向前查找可以首先找到位于最后面的元素。若设表中元素存放于0~n-1号位置,如果表中没有与给定值相等的元素,从前向后查找的数据比较停留在第n个位置,这恰恰是新元素插入的位置,而从后向前查找的数据比较停留在第-1个位置,该位置不能插入,但入们习惯于把返回-1视为查找失败的信息。

3. 折半查找的限制是什么?衡量折半查找性能的标准是什么?
折半查找只能用于有序顺序表。衡量折半查找性能标准是平均查找长度。在相等查找概率的情况下,查找成功的平均查找长度为 :ASL成功≈log2(n+1)-1
查找不成功的平均查找长度为:在这里插入图片描述
4.如果一棵二叉树中每个节点的关键码都大于左子女的关键码,且小于右子女的关键码,此二叉树是否为二叉查找树?
不一定是二叉查找树,虽然每个结点的关键码都大于其左子女的关键码,小于其右子女的关键码,但不是二叉查找树,中序遍历不能把所有结点数据有序排列。下图(b)是二叉查找树,每个结点的关键码大于其左子树(非空)上所有结点的关键码,小于其右子树(非空)上所有结点的关键码。
在这里插入图片描述

5. 二叉树,二叉查找树和AVL树之间是什么关系?

  • 二叉树是一种满足二叉树特性的树形结构,它对树中结点的值没有特别限定,在一棵二叉树中结点的值可以重复,也可以不重复。
  • 二叉查找树是满足二叉查找树特性的二叉树,每个结点的值不重复出现,且比左子树中所有结点的值大,比右子树中所有结点的值小。二叉查找树是二叉树的特殊情形。
  • AVL树是二叉查找树的特殊情形,为保持较高的查找效率,在插入或删除结点时进行了平衡化处理,使每个结点的左、右子树的高度的差的绝对值不超过1。
    归纳起来,其关系是: AVL树⊂二叉查找树⊂二叉树。

6. 完全二叉树或理想平衡树是AVL树吗?
AVL树是高度平衡的,就是说,树中每个结点的左、右子树的高度差的绝对值不超过1。完全二叉树和理想平衡树在树形上属于平衡二叉树,即所有结点的平衡因子的差的绝对值不超过1,但树中结点的数据值的分布不一定满足二叉查找树的定义。所以完全二叉树和理想平衡树不一定是AVL树,除非它们满足二叉查找树的要求。

7. 平衡旋转的目的是什么?
平衡化旋转的目的是保持二叉查找树的高度降至最低,以保持较高的查找效率。例如,若在某结点的较高的子树上插入新结点,将使得该子树的高度更高,造成了不平衡,最严重的情况将导致单支树,使得查找效率降到顺序查找的情形。进行平衡化旋转,可降低该结点为根的子树的高度,使之恢复平衡。另一方面,在AVL树中删除某一结点后,有可能使以该结点为根的子树的高度降低,导致其祖先结点失去平衡,也需要自下而上对其失去平衡的祖先结点做平衡旋转。

8. 平衡二叉树的插入,删除以及旋转操作要掌握,这里不再给出练习。

9. 在用开地址法造表的情形中,为何删除一个元素时不能做物理删除,而只能做删除标记?如果插入新元素时,在寻找插入位置的探测过程中遇到已做删除标记的记录,可否在此位置插入?
答:如果物理删除一个元素,会导致其他元素的探测序列中断,当查找那些元素时会造成“没有此元素”的误判,所以不能真正物理删除一个表中元素,只可做删除标记。在插入新元素时在其探测序列中遇到已做逻辑删除标记的记录,不应在此位置插入。因为后面有可能存在与新元素相同的元素。这样做会使表中可用空间越来越少,应定期对表重构,把做过逻辑删除的元素从各元素的探测序列中摘出来,将其物理删除。

二、ALV树

(1) 高度平衡的二叉查找树。如果非空,则其根节点的左右子树都是AVL树,且左子树和右子树的高度差的绝对值不超过1.
(2) 结点的平衡因子bf定义为该结点左子树高度减去右子树的高度所得的差,则bf只可能是-1,0,1
(3) 只要有一个节点的bf的绝对值大于1,则该二叉树就是不平衡的。

三、B树与B+树

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、代码

  1. 力扣三数之和
    (1)题目:给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j !=k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
    注意:答案中不可以包含重复的三元组。
    (2)实例
    输入:nums = [-1,0,1,2,-1,-4]
    输出:[[-1,-1,2],[-1,0,1]]
    解释:
    nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
    nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
    nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
    不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
    注意,输出的顺序和三元组的顺序并不重要。
    (3)代码
vector<vector<int>> threeSum(vector<int>& nums)
{   vector< vector<int> > ans;
    if(nums.size() < 3 || nums.empty()) return ans; // 特判
    int n = nums.size();
    sort(nums.begin(), nums.end()); //排序
    for(int i = 0; i < n; i++)  // 枚举最小值
    {
        if(nums[i] > 0) return ans;
        if(i > 0 && nums[i] == nums[i-1]) continue;   // 最小元素去重!
        int l = i+1;
        int r = n-1;
        while(l < r)    // 枚举中间值和最大值
        {  int x = nums[l] + nums[r] + nums[i];
            if(x == 0){ // 符合条件,存储,并且去重,双端都移到下一个位置
                ans.push_back({ nums[i], nums[l], nums[r] });
                while( l < r && nums[l] == nums[l+1]) l++; l++;
                while( l < r && nums[r] == nums[r-1]) r--; r--;
            }
            else if(x > 0) // 大了就让右边最大值变小   r--;
            else        // 小了就让左边中间值变大     l++;
        }
    } return ans;
}
  1. 有效的完全平方数
    (1)题目
    给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false。进阶:不要 使用任何内置的库函数,如 sqrt 。
    (2)示例
    输入:num = 16
    输出:true
    (3)代码
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值