前端笔试题总结(七) - 数据结构与算法篇

1. 若查找每个记录的概率均相等,则在具有n个记录的连续顺序文件中,采用顺序查找的方式查找一个记录,其平均查找长度ASL为(\frac{1+n}{2}

ASL:平均查找长度。查找算法在查找成功时的平均查找长度。为了确定某个值在查找表中的位置,需要和给定值进行比较次数的期望。

ASL = \sum_{i=1}^{n}p_i*c_i

 

 2. 顺序查找(Sequence Search):

查找方式为从头查到尾。找到指定元素即查找成功,若到尾部都没有找到,则说明查找失败。

首先,不论是何种方式,每个元素被查找到的概率都是相同的。有n个元素,那么每个元素被查找到的概率都是 \LARGE \frac{1}{n} 。第一个元素需要查找一次,第二个元素需要查找两次,第三个元素需要查找三次......第n个元素需要查找n次。所以对于顺序查找来说:

  • 成功查找到对应元素时:

ASL_{success} = \sum_{i=1}^{n}p_i*c_i =\frac{1}{n}*\sum_{i=1}^{n}c_i= \frac{1}{n} * (1+2+3+\cdot\cdot\cdot +n)=\frac{1}{n}*\frac{(1+n)*n}{2} = \frac{1+n}{2}

  • 查找失败时,就需要从头查到尾,因此平均查找长度就是元素个数n:

ASL_{fail} = n

 

3. 折半查找(Binary Search):

首先,折半查找要求待查找表一定是一个有序表。在查找过程中,用二叉树描述查找过程,查找区间中间位置作为根,左子表为左子树,右子表为右子树。

查找方式:先与根节点进行比较,若大于根节点,则与右子树进行比较,若小于根节点,则与左子树进行比较。递归上述过程,直到找到找到对应位置或查找失败为止。

在n个元素组成的查找判定树中,由于关键字序列是用树构建的,所以查找路径实际为树中从根节点到被查找节点的一条路径,先用一个图片描述一下这棵树:

  • 对于某个元素来说,当查找成功时,比较次数刚好为该元素在树中所对应的层数。就上面这棵折半查找判定树来说,在查找成功时,平均查找长度为【p_i为每个节点的查找概率,level(k_i) 为这棵树对应内部节点的层次,对应遍历到每个内部节点的比较次数总和】:

ASL_{success} = \sum_{i=1}^{n}p_i*{level(k_i)}=\frac{1*1+2*2+4*3+4*4}{11}=3

  • 当查找失败时,就是从根节点到某外部节点(外部节点没有明确的定义,在本例子中,所有的空子树就是外部节点)也没有找到,比较次数就是该元素在树中对应的层数+1。所以查找失败时,平均查找长度为【一个二叉树数有n+1个外部节点,q_i 就表示查找到每个外部节点的概率,查找到每个外部节点的概率是相同的,均可以表示为q_i=\frac{1}{n+1}level(u_i)表示外部节点的层次,对应遍历到每个外部节点需要比较次数的总和】:

ASL_{fail} = \sum_{i=0}^{n}q_i*(level(u_i)-1)=\frac{4*3+8*4}{11}=3.67

  • 在一棵有n个节点的满二叉树,节点总数n和高度h之间的关系为:n=2^{h}-1,所以高度h就可以表示为h=\log_2(n+1),第 i 层上的节点个数为2^{i-1},那么它的平均查找长度也可以进一步化简:

ASL= \sum_{i=1}^{n}p_i*c_i =\frac{1}{n}*\sum_{i=1}^{h}2^{i-1}*i=\frac{n+1}{n}*log_2(n+1)-1\approx log_2(n+1)-1

 

4. 在一个循环队列中,用数组A[0...m-1]存放队列元素,其队头、队尾分别为:front、rear,则当前队列中元素的个数是:(rear + m - front) % m。

 

5. 循环队列

循环队列最好的方法是用链表来实现,我们暂时用数组来实现一下循环队列,只要数组实现循环队列的方法可以明白,链表实现循环队列自然就很容易明白了。

循环队列诣在解决一个问题:一个普通队列,队首元素出队后,多出来的空间无法利用。

于是循环队列就应运而生,怎么做呢?现在就以一个数组为例,队首弹出了几个元素后,数组的前方空出了几个位置,当指向最后一个元素的指针,指向数组的尾部时,再增加的元素,从被空出来数组的头部开始添加。这样,就可以循环利用这段空间了。

  • 首先想到的是让f指向队列头部,让r指向队列尾部,整个队列可以全部填满。但是我们发现,这种情况下,不论是循环队列为空还是为满,判定条件均是( r+1 ) % N == f。×

  • 【方法一】不过,针对这种方法,我么可以进行一个优化,换一个判断队满和队空的方式,增加一个count元素来记录队列中元素的个数,就可以实现我们目的了:

  • 【方法二】我们可以换个想法,可以让整个队列空出一个元素,当一个队列足够长时,空出一个位置对于占用内存的影响并不大。此时队列为空和队列为满的表达式就不再相同了:

  • 【方法三】我们最常用的呢,就是空出一个元素的同时,让r指向队列末尾的下一个元素:

  • 我们知道,* / 的效率不如 + - ,% 的效率不如 * /,那么我们就可以对其进行一个优化

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麦田里的POLO桔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值