算法导论——(2)二叉查找树的实现

来源:互联网 发布:淘宝刷一个皇冠多少钱 编辑:程序博客网 时间:2024/06/05 17:28

正在学习算法导论,根据书上的伪代码和思想实现二叉查找树。
主要方法有:
1.查找最大关键字的结点
2.查找最小关键字的结点
3.查找特定关键字的结点
4.查找一个结点的后继结点(即按照中序遍历在该点后一个位置的点,这个点的键值是比该点键值大的最近的点)。
5.插入节点
6.删除结点

每个方法的思想:
1.查找最大关键值的点:
根据二叉查找树的性质,关键字最大的点在树的最右边

Entry TreeMaximum(Entry x) {        if (x.right!= null)            x = x.right;        return x;    }

2.同理,关键字最小的点在最左边

Entry TreeMinimum(Entry x) {        if (x.left != null)            x = x.left;        return x;    }

3.查找特定关键字的点

Entry TreeSearch(int key){        Entry x=root;        while(x!=null&&x.key!=key){            if(x.key<key)                x=x.right;            else                 x=x.left;        }        //要么x==null,要么x.key=-key,x==null说明没找到        return x;    }

4.查找一个节点的后继结点(即按照中序遍历在该点后一个位置的点,这个点的键值是比该点键值大的最近的点)。:
这里分两种情况,
1)当该节点的右孩子结点不为空时,我们可以确定比该键值大的最接近的节点一定在该节点的右子树上。并且是右子树的最小键值结点。
2)当该节点没有右孩子结点,那么它的后继节点一定是他的祖先,并且该节点处于后继结点的左子树上。那么找到最近的一个祖先结点y,y.left也是该节点的祖先(一个节点可以是自己的祖先)

Entry TreeSuccessor(Entry x) {        if (x.right != null) {            return TreeMinimum(x);        } else {            Entry y = x.p;            while (y != null && x == y.right) {                x = y;                y = y.p;            }            return y;        }    }

5.插入节点,这个比较简单,一直比较找到一个合适的父节点就行了。然后挂在父节点的下面

void TreeInsert(Entry x) {        Entry k = root;        Entry y=null;        while (k != null) {            y=k;            if (x.key < k.key)                k = k.left;            else                k = k.right;        }        if(y!=null)            if(x.key<y.key)                y.left=x;            else                y.right=x;        else            root=x;        x.p=y;    }

6.删除结点,这个比较麻烦,分四种情况:
1)当该节点孤家寡人,没有子节点时,好办!直接把他的父节点的左(右)节点设置为null
2)当该节点只有一个孩子节点时,如果是只有左孩子,那么将该节点的父节点的左(或者右)孩子节点(看本身该节点处于其父节点的左还是右孩子节点)设置为该节点的左孩子节点;只有右孩子结点,相同的处理,将该节点的父节点的左(或者右)孩子节点(看本身该节点处于其父节点的左还是右孩子节点)设置为该节点的右孩子节点。
3)当该节点左孩子和右孩子都不为空时,我们要找到他的后继(前驱结点也行)结点y去替换掉当前的结点的位置,分两种情况:
<1>当后继结点y直接是该节点的右孩子,直接替换。把该节点的左子树挂到后继结点的左子树上

            Transplant(x,y);            y.left=x.left;            y.left.p=y;

<2>当后继结点y不是该节点的右孩子而是右子树上的最小键值的一个节点,根据二叉查找树的性质该后继结点没有左子树(如果有左子树那它就不会是最小的键值结点了)。首先我们要把这个结点提取出来,用后继结点y的右孩子结点替换掉y的位置,再用y替换掉要删除的结点

            if(y!=x.right){                Transplant(y,y.right);                y.right=x.right;                y.right.p=y;            }            Transplant(x,y);            y.left=x.left;            y.left.p=y;

替换函数为:

    void Transplant(Entry u,Entry v){        if(u.p==null)//u为根节点            root=v;        else if(u==u.p.left)            u.p.left=v;        else            u.p.right=v;        if(v!=null)            v.p=u.p;    }

好了到这里二叉查找树的基本函数都有了,遍历函数应该不用谢了,就是普通的二叉树遍历,下面是一个完整的二叉查找树实现例子

public class SearchTree {    Entry root=null;    public void print(){        InOrderTreeWalk(root);    }    void InOrderTreeWalk(Entry x){        if(x!=null){            InOrderTreeWalk(x.left);            System.out.print(x.key+" ");            InOrderTreeWalk(x.right);        }    }    Entry TreeMinimum(Entry x) {        if (x.left != null)            x = x.left;        return x;    }    Entry TreeSuccessor(Entry x) {        if (x.right != null) {            return TreeMinimum(x);        } else {            Entry y = x.p;            while (y != null && x == y.right) {                x = y;                y = y.p;            }            return y;        }    }    void TreeInsert(Entry x) {        Entry k = root;        Entry y=null;        while (k != null) {            y=k;            if (x.key < k.key)                k = k.left;            else                k = k.right;        }        if(y!=null)            if(x.key<y.key)                y.left=x;            else                y.right=x;        else            root=x;        x.p=y;    }    void Transplant(Entry u,Entry v){        if(u.p==null)            root=v;        else if(u==u.p.left)            u.p.left=v;        else            u.p.right=v;        if(v!=null)            v.p=u.p;    }    void TreeDelete(Entry x){        Entry p=x.p;        if(x.left==null)            Transplant(x,x.right);        else if(x.right==null)            Transplant(x,x.left);        else{            Entry y=TreeMinimum(x.right);            if(y!=x.right){                Transplant(y,y.right);                y.right=x.right;                y.right.p=y;            }            Transplant(x,y);            y.left=x.left;            y.left.p=y;        }    }    Entry TreeSearch(int key){        Entry x=root;        while(x!=null&&x.key!=key){            if(x.key<key)                x=x.right;            else                 x=x.left;        }        return x;    }    public static void main(String args[]){        SearchTree tree=new SearchTree();        tree.TreeInsert(new Entry(15));        tree.TreeInsert(new Entry(6));        tree.TreeInsert(new Entry(18));        tree.TreeInsert(new Entry(3));        tree.TreeInsert(new Entry(8));        tree.TreeInsert(new Entry(7));        tree.TreeInsert(new Entry(17));        tree.TreeInsert(new Entry(20));        tree.TreeInsert(new Entry(2));        tree.TreeInsert(new Entry(4));        tree.TreeInsert(new Entry(13));        tree.TreeInsert(new Entry(9));        tree.print();        System.out.println();        int key=8;        Entry x=tree.TreeSearch(key);        tree.TreeDelete(x);        tree.print();    }}class Entry {    int key;     Entry left;     Entry right;     Entry p;    public Entry(int key) {        this.key = key;        left = null;        right = null;        p = null;    }}
0 0
原创粉丝点击