折半查找的平均查找长度公式推导

本文详细推导了折半查找的平均查找长度公式,利用满二叉树的性质和数学方法,包括对数运算和复合数列求和,最终得到ASL与结点数n的关系。

看严蔚敏版《数据结构》给出了折半查找的平均查找长度公式(如下图),但没有具体推导过程

所以我自己推导了一遍,用这篇文章把思路写下来

假设折半查找判定树为满二叉树,总节点数=nnn,高度(层数) =hhh

1、根据满二叉树的性质,总节点数 nnn 与高度(层数) hhh 的关系为

n=2h−1{\color{Black} n=2^{h}-1}n=2h1

移项得

2h=n+1{\color{Black} 2^{h}=n+1}2h=n+1

取对数得,高度(层数)

h=log2(n+1){\color{Black} h=log_{2}{(n+1)}}h=log2(n+1)


2、根据满二叉树的性质,从第1层开始,每层的节点数为

第1层:21−1=1{\color{Black} 2^{1-1}=1}211=1 个节点(根节点)

第2层:22−1=2{\color{Black} 2^{2-1}=2}221=2 个节点

第3层:23−1=4{\color{Black} 2^{3-1}=4}231=4 个节点

……

第h层:2h−1{\color{Black} 2^{h-1}}2h1 个节点


解释一下,上面严蔚敏版《数据结构》给出的平均查找长度公式

ASL=∑i=1nPiCi{\color{Black} ASL=\displaystyle \sum\limits_{i=1}^{n}P_{i}C_{i}}ASL=i=1nPiCi

Pi{\color{Black} P_{i}}Pi 代表查找到当前节点(第 i 个节点)的概率

Ci{\color{Black} C_{i}}Ci 代表查找到当前节点(第 i 个节点)的累计比较次数

PiCi{\color{Black} P_{i}C_{i}}PiCi代表查找到当前节点(第 i 个节点)的加权比较次数(概率×\times×累计比较次数)

∑i=1nPiCi{\color{Black} \displaystyle \sum\limits_{i=1}^{n}P_{i}C_{i}}i=1nPiCi 代表对n个节点的加权比较次数求和(即加权平均比较次数,简称平均比较次数)


为简化分析,设查找到每个节点是等概率的

因为总共n个节点且等概率,所以概率为 1n{\color{Black} \frac{1}{n}}n1

Pi=1n{\color{Black} P_{i}=\frac{1}{n}}Pi=n1 变为常数,可以从求和式中提出

ASL=∑i=1nPiCi=∑i=1n1n Ci=1n∑i=1n Ci{\color{Black} ASL=\displaystyle \sum\limits_{i=1}^{n}P_{i}C_{i}=\displaystyle \sum\limits_{i=1}^{n}\frac{1}{n}\ C_{i}=\frac{1}{n}\displaystyle \sum\limits_{i=1}^{n}\ C_{i}}ASL=i=1nPiCi=i=1nn1 Ci=n1i=1n Ci

这里 ∑i=1n Ci{\color{Black} \displaystyle \sum\limits_{i=1}^{n}\ C_{i}}i=1n Ci 代表对n个节点的累计比较次数求和(即总比较次数)

所以平均查找长度可描述为:平均查找长度=概率×\times×总比较次数


现在问题就转为求总比较次数了

下面仅分析查找成功的情况:

从折半查找判定树的根节点开始

每经过一个节点就比较一次,比较查找值与当前节点值的大小

如果查找值小于当前节点值,则选择左孩子,继续比较

如果查找值大于当前节点值,则选择右孩子,继续比较

如果查找值等于当前节点值,则查找成功

对于左(右)孩子又会重复上述比较过程

所以查找成功的整个过程,刚好是从根节点到查找成功节点的路径


例如下图这颗折半查找判定树

在这里插入图片描述

如果要查找【3】

从第1层的根节点【4】开始比较,因为3<4,所以选择左孩子,继续比较。此时累计比较1次

到第2层的左孩子【2】继续比较,因为3>2,所以选择右孩子,继续比较。此时累计比较2次

到第3层的右孩子【3】继续比较,因为3=3,所以查找成功。此时累计比较3次

查找成功的过程是 4——2——3 这条路径

可以发现

在第1层,累计比较1次

在第2层,累计比较2次

在第3层,累计比较3次

所以折半查找判定树中

节点累计比较次数=节点所在层数

那么同一层中所有节点的累计比较次数都相等(等于层数)


本文最前面,根据满二叉树的性质,已经得出每层的节点数

所以可以逐层计算,求和得出 总比较次数

第1层的累计比较次数=节点累计比较次数×\times×该层节点个数=节点所在层数×\times×该层节点个数=1×21−11 \times 2^{1-1}1×211

第2层的累计比较次数=节点累计比较次数×\times×该层节点个数=节点所在层数×\times×该层节点个数=2×22−12 \times 2^{2-1}2×221

第3层的累计比较次数=节点累计比较次数×\times×该层节点个数=节点所在层数×\times×该层节点个数=3×23−13 \times 2^{3-1}3×231

……

第h层的累计比较次数=节点累计比较次数×\times×该层节点个数=节点所在层数×\times×该层节点个数=h×2h−1h \times 2^{h-1}h×2h1

将1到h层的累计比较次数相加得到总比较次数

总比较次数=1×21−1+2×22−1+3×23−1+……+h×2h−1=∑j=1hj⋅2j−1{\color{Black} 1 \times 2^{1-1}+2 \times 2^{2-1}+3 \times 2^{3-1}+……+h \times 2^{h-1}}= \displaystyle \sum_{j=1}^{h} j\cdot 2^{j-1}1×211+2×221+3×231+……+h×2h1=j=1hj2j1

又因为之前已得出 总比较次数=∑i=1n Ci{\color{Black} \displaystyle \sum\limits_{i=1}^{n}\ C_{i}}i=1n Ci

所以 总比较次数=∑i=1n Ci=∑j=1hj⋅2j−1{\color{Black} \displaystyle \sum\limits_{i=1}^{n}\ C_{i}=\displaystyle \sum_{j=1}^{h} j\cdot 2^{j-1}}i=1n Ci=j=1hj2j1

再看严蔚敏版《数据结构》给出的平均查找长度公式 ASL=∑i=1nPiCi{\color{Black} ASL=\displaystyle \sum_{i=1}^{n}P_{i} C_{i}}ASL=i=1nPiCi

这个求和式是按每个节点来计算,从1到nnn个节点,用查找到节点的概率 ×\times× 该节点的累计比较次数

最终将n个节点求和,得到平均查找长度,但缺点是不方便计算

所以前面的推导其实是转换思路,改为逐层计算

两种计算方式都会把节点过一遍,二者是等价的

将上面得出的 总比较次数 代入 平均查找长度公式 得

平均查找长度 ASL=∑i=1nPiCi=1n∑i=1n Ci=1n∑j=1hj⋅2j−1{\color{Black} ASL=\displaystyle \sum\limits_{i=1}^{n}P_{i}C_{i}=\frac{1}{n}\sum\limits_{i=1}^{n}\ C_{i}=\frac{1}{n}\displaystyle \sum_{j=1}^{h} j\cdot 2^{j-1} }ASL=i=1nPiCi=n1i=1n Ci=n1j=1hj2j1


现在重点就转到如何计算总比较次数 ∑j=1hj⋅2j−1{\color{Black}\displaystyle \sum_{j=1}^{h} j\cdot 2^{j-1}}j=1hj2j1

其实这就是高中数学的复合数列{h⋅2h−1}\{\color{Black} {h \cdot 2^{h-1}\}}{h2h1}求和

前面是首项为1,公差为1的等差数列{h}{\color{Black} \{h\}}{h}

后面是首项为1,公比为2的等比数列{2h−1}{\color{Black} \{ 2^{h-1}\}}{2h1}

复合数列求和的计算思路与等比数列相同(乘公比,错位相减)

Sh=1×21−1+2×22−1+3×23−1+……+h×2h−12Sh=      1×22−1+2×23−1+……+(h−1)×2h−1+h×2h2Sh−Sh=(−1)×21−1+(1−2)×22−1+(2−3)×23−1+……+(h−1−h)×2h−1+h×2h=(−1)×20+(−1)×21+(−1)×22+……+(−1)×2h−1+h×2h=(−1)×(20+21+22+……+2h−1)+h×2h=(−1)×20(1−2h)1−2+h×2h=(−1)×1⋅(1−2h)−1+h×2h=1−2h+h×2h=1+(−1+h)×2hSh=(h−1)2h+1{\color{Black} \begin{align*}S_{h}&=1 \times 2^{1-1}+2 \times 2^{2-1}+3 \times 2^{3-1}+……+h \times 2^{h-1} \\[1.1ex]2S_{h}&=\qquad \qquad \; \; \; 1 \times 2^{2-1}+2 \times 2^{3-1}+……+(h-1) \times 2^{h-1}+h\times 2^{h} \\[1.1ex]\\2S_{h}-S_{h} &=(-1) \times 2^{1-1}+(1-2)\times 2^{2-1}+(2-3)\times 2^{3-1}+……+(h-1-h)\times 2^{h-1}+h\times 2^{h}\\[1.1ex]&= (-1) \times 2^{0}+(-1) \times 2^{1}+(-1) \times 2^{2}+……+(-1)\times 2^{h-1}+h\times 2^{h}\\[1.1ex] &=(-1)\times(2^{0}+2^{1}+2^{2}+……+2^{h-1})+h\times 2^{h} \\[1.1ex] &=(-1)\times \frac{2^{0}(1-2^{h})}{1-2}+h\times 2^{h} \\[1.1ex] &= (-1)\times \frac{1\cdot (1-2^{h})}{-1}+h\times 2^{h} \\[1.1ex] &=1-2^{h}+h\times 2^{h} \\[1.1ex] &=1+(-1+h)\times 2^{h}\\[1.1ex] S_{h}&=(h-1)2^{h}+1 \end{align*}}Sh2Sh2ShShSh=1×211+2×221+3×231+……+h×2h1=1×221+2×231+……+(h1)×2h1+h×2h=(1)×211+(12)×221+(23)×231+……+(h1h)×2h1+h×2h=(1)×20+(1)×21+(1)×22+……+(1)×2h1+h×2h=(1)×(20+21+22+……+2h1)+h×2h=(1)×1220(12h)+h×2h=(1)×11(12h)+h×2h=12h+h×2h=1+(1+h)×2h=(h1)2h+1

其中关键步骤是将多项式 (20+21+22+……+2h−1){\color{Black} (2^{0}+2^{1}+2^{2}+……+2^{h-1})}(20+21+22+……+2h1)看作等比数列求和

首项 a1=20=1a_{1}=2^{0}=1a1=20=1,公比 q=2q=2q=2

代入等比数列求和公式 Sn=a1(1−qn)1−q=20(1−2h)1−2{\color{Black} S_{n}=\frac{a_{1}(1-q^{n})}{1-q}=\frac{2^{0}(1-2^{h})}{1-2}}Sn=1qa1(1qn)=1220(12h)

再合并同类项,最终得出总比较次数 Sh=(h−1)2h+1{\color{Black} S_{h}=(h-1)2^{h}+1}Sh=(h1)2h+1


但是题目一般给出的是节点数 nnn,并不会给高度(层数) hhh,所以还需要把 hhh 替换掉

本文最前面,根据满二叉树的性质,已经得出 h=log2(n+1){\color{Black} h=log_{2}{(n+1)}}h=log2(n+1)

所以 hhh 可以用这个表达式替换,但是公式中还有个 2h2^{h}2h,这个怎么办呢?

其实非常简单,替换后 2h=2log2(n+1){\color{Black} 2^{h}=2^{log_{2}{(n+1)}}}2h=2log2(n+1)

根据对数定义 alogab=b{\color{Black} a^{log_{a}{b}}=b}alogab=b,所以 2log2(n+1)=n+1{\color{Black} 2^{log_{2}{(n+1)}}=n+1}2log2(n+1)=n+1

将h替换后的结果为

Sh=(h−1)2h+1=[log2(n+1)−1]2log2(n+1)+1=[log2(n+1)−1](n+1)+1=(n+1)log2(n+1)−(n+1)+1=(n+1)log2(n+1)−n−1+1=(n+1)log2(n+1)−n{\color{Black} \begin{align*} S_{h}&=(h-1)2^{h}+1\\[1.1ex] &={\Large[}log_{2}{(n+1)}-1{\Large]}2^{log_{2}{(n+1)}}+1 \\[1.1ex] &={\Large[}log_{2}{(n+1)}-1{\Large]}(n+1)+1\\[1.1ex] &=(n+1)log_{2}{(n+1)}-(n+1)+1\\[1.1ex] &=(n+1)log_{2}{(n+1)}-n-1+1\\[1.1ex] &=(n+1)log_{2}{(n+1)}-n \end{align*}} Sh=(h1)2h+1=[log2(n+1)1]2log2(n+1)+1=[log2(n+1)1](n+1)+1=(n+1)log2(n+1)(n+1)+1=(n+1)log2(n+1)n1+1=(n+1)log2(n+1)n

所以总比较次数=∑i=1n Ci=∑j=1hj⋅2j−1=(h−1)2h+1=(n+1)log2(n+1)−n{\color{Black} \displaystyle \sum\limits_{i=1}^{n}\ C_{i}=\displaystyle \sum_{j=1}^{h} j\cdot 2^{j-1}=(h-1)2^{h}+1=(n+1)log_{2}{(n+1)}-n}i=1n Ci=j=1hj2j1=(h1)2h+1=(n+1)log2(n+1)n


所以平均查找长度=概率×\times×总比较次数

ASL=∑i=1npi⋅ci=1n∑i=1n Ci=1n∑j=1hj⋅2j−1=1n[(n+1)log2(n+1)−n]=n+1nlog2(n+1)−nn=n+1nlog2(n+1)−1{\color{Black} \begin{align*} ASL=\displaystyle \sum_{i=1}^{n}p_{i}\cdot c_{i}=\frac{1}{n}\displaystyle \sum\limits_{i=1}^{n}\ C_{i}=\frac{1}{n} \displaystyle \sum_{j=1}^{h} j\cdot 2^{j-1} &=\frac{1}{n}{\Large[}(n+1)log_{2}{(n+1)}-n{\Large]} \\[1.1ex] &=\frac{n+1}{n}log_{2}{(n+1)}-\frac{n}{n}\\[1.1ex] &=\frac{n+1}{n}log_{2}{(n+1)} -1\end{align*}}ASL=i=1npici=n1i=1n Ci=n1j=1hj2j1=n1[(n+1)log2(n+1)n]=nn+1log2(n+1)nn=nn+1log2(n+1)1

折半查找的平均查找长度ASL=n+1nlog2(n+1)−1{\color{Black} ASL= {\Large \frac{n+1}{n}}log_{2}{(n+1)}- 1 }ASL=nn+1log2(n+1)1

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值