1. 若查找每个记录的概率均相等,则在具有n个记录的连续顺序文件中,采用顺序查找的方式查找一个记录,其平均查找长度ASL为()
ASL:平均查找长度。查找算法在查找成功时的平均查找长度。为了确定某个值在查找表中的位置,需要和给定值进行比较次数的期望。
2. 顺序查找(Sequence Search):
查找方式为从头查到尾。找到指定元素即查找成功,若到尾部都没有找到,则说明查找失败。
首先,不论是何种方式,每个元素被查找到的概率都是相同的。有n个元素,那么每个元素被查找到的概率都是 。第一个元素需要查找一次,第二个元素需要查找两次,第三个元素需要查找三次......第n个元素需要查找n次。所以对于顺序查找来说:
- 当成功查找到对应元素时:
- 查找失败时,就需要从头查到尾,因此平均查找长度就是元素个数n:
3. 折半查找(Binary Search):
首先,折半查找要求待查找表一定是一个有序表。在查找过程中,用二叉树描述查找过程,查找区间中间位置作为根,左子表为左子树,右子表为右子树。
查找方式:先与根节点进行比较,若大于根节点,则与右子树进行比较,若小于根节点,则与左子树进行比较。递归上述过程,直到找到找到对应位置或查找失败为止。
在n个元素组成的查找判定树中,由于关键字序列是用树构建的,所以查找路径实际为树中从根节点到被查找节点的一条路径,先用一个图片描述一下这棵树:
- 对于某个元素来说,当查找成功时,比较次数刚好为该元素在树中所对应的层数。就上面这棵折半查找判定树来说,在查找成功时,平均查找长度为【为每个节点的查找概率, 为这棵树对应内部节点的层次,对应遍历到每个内部节点的比较次数总和】:
- 当查找失败时,就是从根节点到某外部节点(外部节点没有明确的定义,在本例子中,所有的空子树就是外部节点)也没有找到,比较次数就是该元素在树中对应的层数+1。所以查找失败时,平均查找长度为【一个二叉树数有n+1个外部节点, 就表示查找到每个外部节点的概率,查找到每个外部节点的概率是相同的,均可以表示为,表示外部节点的层次,对应遍历到每个外部节点需要比较次数的总和】:
- 在一棵有n个节点的满二叉树,节点总数n和高度h之间的关系为:,所以高度h就可以表示为,第 i 层上的节点个数为,那么它的平均查找长度也可以进一步化简:
4. 在一个循环队列中,用数组A[0...m-1]存放队列元素,其队头、队尾分别为:front、rear,则当前队列中元素的个数是:(rear + m - front) % m。
5. 循环队列
循环队列最好的方法是用链表来实现,我们暂时用数组来实现一下循环队列,只要数组实现循环队列的方法可以明白,链表实现循环队列自然就很容易明白了。
循环队列诣在解决一个问题:一个普通队列,队首元素出队后,多出来的空间无法利用。
于是循环队列就应运而生,怎么做呢?现在就以一个数组为例,队首弹出了几个元素后,数组的前方空出了几个位置,当指向最后一个元素的指针,指向数组的尾部时,再增加的元素,从被空出来数组的头部开始添加。这样,就可以循环利用这段空间了。
- 首先想到的是让f指向队列头部,让r指向队列尾部,整个队列可以全部填满。但是我们发现,这种情况下,不论是循环队列为空还是为满,判定条件均是( r+1 ) % N == f。×
- 【方法一】不过,针对这种方法,我么可以进行一个优化,换一个判断队满和队空的方式,增加一个count元素来记录队列中元素的个数,就可以实现我们目的了:
- 【方法二】我们可以换个想法,可以让整个队列空出一个元素,当一个队列足够长时,空出一个位置对于占用内存的影响并不大。此时队列为空和队列为满的表达式就不再相同了:
- 【方法三】我们最常用的呢,就是空出一个元素的同时,让r指向队列末尾的下一个元素:
- 我们知道,* / 的效率不如 + - ,% 的效率不如 * /,那么我们就可以对其进行一个优化: