关于二叉查找树的平均查找时间的问题
2017-06-29 13:08
405 查看
首先,放附上二叉查找树
以上是二叉查找树的Java实现
那么对于一个具有N个节点的,其内部路径长记为D(N),表示所有节点的深度之和。所以轻易可得D(N)=1.
若一棵二叉树的左子树的其内部路径长用D(i)来表示,则其右子树的内部路径长为D(N-i-1)。
又因为在原树内,左子树与右子树的深度都应当+1,所以最终该树的内部路径长可表示为
因而二叉树的平均查找时间应该是O(logN)。
补充关于上式的证明内容,先去掉-1,如下:
N*D(N)=2∑D(j) +N*N(j的上限为N-1,下限为0)
轻易可得
(N-1)D(N-1)=2∑D(j)+(N-1)(N-1)(j的上限为N-2,下限为0)
用(1)-(2)可得
N*D(N)-(N-1)D(N-1)=2D(N-1)+2(N-1)
经移项可得
N*D(N)=(N+1)D(N-1)+2N-2
无关项-2去掉,两边同除N(N+1)
D(N)/N+1=D(N-1)/N+2/N+1
D(N-1)/N=D(N-2)/N+2/N
...
D(2)/3=D(1)/2+2/3
将上述各式相加
得
得证。
package com.company.adt; /** * Created by Administrator on 2017/6/2. */ public class BiSearchTree<E extends Comparable<? super E>> { private TreeNode<E> root; private int count; public BiSearchTree(){ count=0; root=null; } public BiSearchTree(TreeNode<E> root) { this.root = root; count=1; } public TreeNode<E> getRoot() { return root; } public void setRoot(TreeNode<E> root) { this.root = root; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public boolean contains(E x){ return contains(root,x); } private boolean contains(TreeNode<E> t, E x) { if (t!=null){ int compareResult=x.compareTo(t.getX()); if (compareResult>0){ return contains(t.getRight(),x); }else if (compareResult<0){ return contains(t.getLeft(),x); }else { return true; } }else { return false; } } public boolean insert(E x){ return insert(root,x); } private boolean insert(TreeNode<E> t, E x) { int compareResult=x.compareTo(t.getX()); if (compareResult<0){ if (t.getLeft()==null){ TreeNode tmp=new TreeNode(x); t.setLeft(tmp); tmp.setParent(t); return true; }else { t=t.getLeft(); insert(t,x); } }else if (compareResult>0){ if (t.getRight()==null){ TreeNode tmp=new TreeNode(x); t.setRight(tmp); tmp.setParent(t); return true; }else { t=t.getRight(); insert(t,x); } } return false; } public void delete(E x){ delete(root,x); } private void delete(TreeNode<E> t, E x) { if (t!=null){ int compareResult=x.compareTo(t.getX()); if (compareResult<0){ delete(t.getLeft(),x); }else if (compareResult>0){ delete(t.getRight(),x); }else if(t.getLeft()!=null&&t.getRight()!=null){ //寻找到待删除的节点 TreeNode min=t.getRight(); while (min.getLeft()!=null) min=min.getLeft(); t.setX((E) min.getX()); delete(t.getRight(), (E) min.getX()); }else{ if(t.getLeft()==null&&t.getRight()!=null){ t.getParent().setRight(t.getRight()); t.getRight().setParent(t.getParent()); }else if (t.getRight()==null&&t.getLeft()!=null){ t.getParent().setLeft(t.getLeft()); t.getLeft().setParent(t.getParent()); }else { TreeNode tmp=t.getParent(); if (tmp.getLeft()==t) tmp.setLeft(null); else tmp.setRight(null); } } } } private boolean isEmpty() { return root==null; } }
以上是二叉查找树的Java实现
那么对于一个具有N个节点的,其内部路径长记为D(N),表示所有节点的深度之和。所以轻易可得D(N)=1.
若一棵二叉树的左子树的其内部路径长用D(i)来表示,则其右子树的内部路径长为D(N-i-1)。
又因为在原树内,左子树与右子树的深度都应当+1,所以最终该树的内部路径长可表示为
D(N)=D(i)+D(N-i-1)+N-1
如果所有子树的概率平均,那么有对于左右子树,有其平均内部路径长为D(i)=1/N∑D(j)
则D(N)=2/N∑D(j) +N-1
上式最终可证O(logN)因而二叉树的平均查找时间应该是O(logN)。
补充关于上式的证明内容,先去掉-1,如下:
N*D(N)=2∑D(j) +N*N(j的上限为N-1,下限为0)
(1)
轻易可得(N-1)D(N-1)=2∑D(j)+(N-1)(N-1)(j的上限为N-2,下限为0)
(2)
用(1)-(2)可得N*D(N)-(N-1)D(N-1)=2D(N-1)+2(N-1)
(3)
经移项可得N*D(N)=(N+1)D(N-1)+2N-2
(4)
无关项-2去掉,两边同除N(N+1)D(N)/N+1=D(N-1)/N+2/N+1
D(N-1)/N=D(N-2)/N+2/N
...
D(2)/3=D(1)/2+2/3
将上述各式相加
得
D(N)/N+1=D(1)/2+2∑1/i(i上限N+1,下限3)
该式近似等于log(N+1),所以D(N)=O(NlogN).得证。
相关文章推荐
- 关于java将String类型的时间字符串转换为Date类型的问题
- Android开发关于onActivityResult()的执行时间问题
- 关于easyui时间获取的问题
- 关于时间插件的问题
- 关于向MySQL数据库插入datetime类型时间的问题
- zf-关于通知公告如果发布的是无限制时间的,那么默认隐藏时间输入框的问题
- 关于获取当前时间出现1970年问题的解决
- 关于Eureka服务调用服务不通问题的查找
- 关于Tomcat查找错误的问题
- 关于SpringMVC+java+mysql的Date类型的时间问题
- 二分法查找和快速排序 二分法是分治算法的一种特殊形式,利用分治策略求解时,所需时间取决于分解后子问题的个数、子问题的规模大小等因素,而二分法,由于其划分的简单和均匀的特点,是查找数据时经常采用的一种有
- 关于windebug查询进程中各个线程占用cpu时间,解决CPU占用很大问题
- 关于 mysql的 datatime类型默认值 0000-00-00 00:00:00 错误或者说没办法创建类型为时间的问题
- 关于WCF,DataService中,查找模型对象时,主键含有数值时找不到对象问题处理
- 关于jsp文件中公共类的问题!费了好多时间!唉唉!
- 一个关于插入查找和排序问题
- 石油主管道最优位置问题(平均时间为线性时间)C++实现
- 关于时间戳和QDateTime相互转换的有关问题(转)
- Pentaho PDI 数据导入关于时间格式及重复数据处理这2个问题的解决方法
- 急急急!!!请教一个关于ASP不报错的问题!浪费一下午的时间啊。。。。。。