关于二叉查找树的平均查找时间的问题

来源:互联网 发布:win10软件都不见了 编辑:程序博客网 时间:2024/05/23 01:11

首先,放附上二叉查找树

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)=2D(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).
得证。