搜索二叉树的实现


定义二叉树的节点:包含左节点,右节点和当前结点的值
    /**
     * 定义二叉搜索树的节点
     * @param <AnyType>
     */
    private static class BinaryNode<AnyType>{
        BinaryNode(AnyType theElement){
            this(theElement, null, null);
        }
        //通过构造函数创建节点
        BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right){
            this.theElement = theElement;
            this.left = left;
            this.right = right;
        }

        AnyType theElement;
        BinaryNode left;
        BinaryNode right;
    }
节点之间的比较方法:通过自定义的Comparator或默认的Compare方法
    /**
     * 定义比较方法:若传入了比较方式,则用传入的比较方式,否则用默认方式
     * 返回为0表示 lhs = rhs
     * 返回为负数表示 lhs < rhs
     * 返回为正数表示 lhs > rhs
     * @param lhs
     * @param rhs
     * @return
     */
    private int myCompare(AnyType lhs, AnyType rhs){
        if (cmp != null){
            return cmp.compare(lhs, rhs);
        } else {
            return  ((Comparable)lhs).compareTo(rhs);
        }
    }
查找结点:比较传入的元素与当前结点元素的值,若传入的元素小于当前节点的元素,则继续查找当前结点的左子树,若大于,则继续查找当前结点的右子树,若等于,表示找到该节点,返回true。
    /**
     * 搜索二叉树中是否包含某个元素节点
     * @param x
     * @param t
     * @return
     */
    private boolean contains(AnyType x, BinaryNode<AnyType> t){
        if (t == null){
            return false;
        }
        //比较元素与当前结点的元素
        int compareResult = myCompare(x, t.theElement);
        //小于当前元素,则搜索左子树
        if (compareResult < 0){
            contains(x, t.left);
        }
        //大于当前元素,则搜索右子树
        else if (compareResult > 0){
            contains(x, t.right);
        }
        //等于情况,表示存在,直接返回
        return true;
    }
插入节点:若当前结点为空,则将新节点放置此处,否则判断传入的值与当前节点的值,若传入的值小于当前结点的值则继续搜索当前结点的左子树,若大于,则继续搜索当前结点的右子树。
    /**
     * 实现插入操作
     * @param x
     * @param t
     * @return
     */
    private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
        //当前节点为空,则将该节点在此处
        if (t == null){
            return new BinaryNode<AnyType>(x, null, null);
        }
        //进行比较
        int compareResult = myCompare(x, t.theElement);
        //元素小于当前结点元素,则加入到左子树
        if (compareResult < 0){
            t.left = insert(x, t.left);
        } else if (compareResult > 0){
            t.right = insert(x, t.right);
        } else {
            //do nothing
        }
        return t;
    }
删除某个节点:先根据给定的值找到要删除的节点,若没有找到该节点,则不会进行删除操作。

a. 删除的节点为叶子节点,即没有孩子,则直接删除即可,不会破坏树的结构。

Paste_Image.png

b. 若节点中只包含左子树,或只包含右子树,则直接删除该节点,并将其左子树或右子树设置为父节点的左子树或右子树即可。

Paste_Image.png

c. 当删除的节点中包含左右子树时,一般的策略是用其右子树的最小数据代替要删除的节点,并递归删除该节点。因为右子树的最小节点是不可能有左子树的,因此第二次删除较为容易。

Paste_Image.png

如上图,我们要删除的节点是5,则找到该节点,然后找到节点值为5的右子树的最小节点,即节点值为6的节点--->将节点值为6的节点代替要删除的节点5---->然后递归删除原本的节点6

    /**
     * 实现移除某个节点
     * @param x
     * @param t
     * @return
     */
    private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
        if (t == null){
            return t;
        }
        //比较大小
        int compareResult = myCompare(x, t.theElement);
        //元素小于当前结点元素,则搜索左子树
        if (compareResult < 0){
            t.left = remove(x, t.left);
        }
        //元素大于当前结点元素,则搜索右子树
        else if (compareResult > 0){
            t.right = remove(x, t.right);
        }
        //相等,表示找到对应的节点,如果该节点存在左右孩子
        else if (t.left != null && t.right != null){
            //搜索到右子树的最小节点,并替代当前结点
            t.theElement = (AnyType) findMin(t.right).theElement;
            //并递归删除右子树的最小节点
            t.right = remove(t.theElement, t.right);
        }
        //否则,将不为空的孩子节点替代掉当前结点
        else {
            t = (t.left != null) ? t.left : t.right;
        }
        return t;
    }
查找最大的节点:不断向右边搜索节点,直到该节点不存在右边子节点。
查找最小的节点:不断向左边搜索节点,直到该节点不存在左边子节点。
    /**
     *  实现获取二叉树中最小的节点
     *  递归查找左子树,直到当前结点的左节点为空,则返回当前节点
     * @param t
     * @return
     */
    private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){
        if (t == null){
            return null;
        } else if (t.left == null){
            return t;
        }
        return findMin(t.left);
    }

    /**
     * 实现获取二叉树中最大的节点
     * 递归查找右子树,直到当前节点的右节点为空,返回当前节点
     * @param t
     * @return
     */
    private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
        if (t == null){
            return null;
        } else if (t.right == null){
            return t;
        }
        return findMax(t.right);
    }

实现三种遍历树的方式:
/**
     * 前序遍历
     * 访问顺序为:根节点->左节点->右节点
     * @param node
     */
    public void preOrder(BinaryNode<AnyType> node){
        if (node != null){
            System.out.print(node.right + " ");
            preOrder(node.left);
            preOrder(node.right);
        }
    }

    /**
     * 中序遍历
     * 访问顺序为:左节点->根节点->右节点
     * @param node
     */
    public void inOrder(BinaryNode<AnyType> node){
        if (node != null){
            inOrder(node.left);
            System.out.print(node.theElement + " ");
            inOrder(node.right);
        }
    }

    /**
     * 后序遍历
     * 访问顺序为:左节点->右节点->根节点
     * @param node
     */
    public void postOrder(BinaryNode<AnyType> node){
        if (node != null){
            postOrder(node.left);
            postOrder(node.right);
            System.out.print(node.theElement + " ");
        }
    }
完整代码:
package BinaryTree;

import org.omg.CORBA.Any;

import java.nio.BufferUnderflowException;
import java.util.Comparator;

/**
 * Created by Administrator on 2017/3/7/007.
 * 实现搜索二叉树的基本操作
 */
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {

    /**
     * 定义二叉搜索树的节点
     * @param <AnyType>
     */
    private static class BinaryNode<AnyType>{
        BinaryNode(AnyType theElement){
            this(theElement, null, null);
        }
        //通过构造函数创建节点
        BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right){
            this.theElement = theElement;
            this.left = left;
            this.right = right;
        }

        AnyType theElement;
        BinaryNode left;
        BinaryNode right;
    }

    /**
     * 定义二叉树的根节点
     */
    private BinaryNode<AnyType> root;

    /**
     * 定义比较方式
     */
    private Comparator<? super AnyType> cmp;

    public BinarySearchTree(){
        this(null);
    }

    /**
     * 构造函数,传入比较方式
     * @param c
     */
    public BinarySearchTree(Comparator<? super AnyType> c){
        root = null;
        cmp = c;
    }

    /**
     * 定义比较方法:若传入了比较方式,则用传入的比较方式,否则用默认的方法
     * @param lhs
     * @param rhs
     * @return
     */
    private int myCompare(AnyType lhs, AnyType rhs){
        if (cmp != null){
            return cmp.compare(lhs, rhs);
        } else {
            return  ((Comparable)lhs).compareTo(rhs);
        }

    }

    /**
     * 使二叉树变为空
     */
    public void makeEmpty(){
        root = null;
    }

    /**
     * 检查二叉树是否为空
     * @return
     */
    public boolean isEmpty(){
        return root == null;
    }

    /**
     * 检查二叉树中是否包含某个元素
     * @param x
     * @return
     */
    public boolean contains(AnyType x){
        return contains(x, root);
    }

    /**
     * 搜索查找二叉树中最小的元素
     * @return
     */
    public AnyType findMin(){
        if (isEmpty()) throw new BufferUnderflowException();
        return findMin(root).theElement;
    }

    /**
     * 搜索查找二叉树中最大的元素
     * @return
     */
    public AnyType findMax(){
        if (isEmpty()) throw new BufferUnderflowException();
        return findMax(root).theElement;
    }

    /**
     * 插入元素
     * @param x
     */
    public void insert(AnyType x){
        root = insert(x, root);
    }

    /**
     * 删除元素
     * @param x
     */
    public void remove(AnyType x){
        root = remove(x, root);
    }


    /**
     * 搜索二叉树中是否包含某个元素节点
     * @param x
     * @param t
     * @return
     */
    private boolean contains(AnyType x, BinaryNode<AnyType> t){
        if (t == null){
            return false;
        }
        //比较元素与当前结点的元素
        int compareResult = myCompare(x, t.theElement);
        //小于当前元素,则搜索左子树
        if (compareResult < 0){
            contains(x, t.left);
        }
        //大于当前元素,则搜索右子树
        else if (compareResult > 0){
            contains(x, t.right);
        }
        //等于情况,表示存在,直接返回
        return true;
    }

    /**
     *  实现获取二叉树中最小的节点
     *  递归查找左子树,直到当前结点的左节点为空,则返回当前节点
     * @param t
     * @return
     */
    private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){
        if (t == null){
            return null;
        } else if (t.left == null){
            return t;
        }
        return findMin(t.left);
    }

    /**
     * 实现获取二叉树中最大的节点
     * 递归查找右子树,直到当前节点的右节点为空,返回当前节点
     * @param t
     * @return
     */
    private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
        if (t == null){
            return null;
        } else if (t.right == null){
            return t;
        }
        return findMax(t.right);
    }

    /**
     * 实现插入操作
     * @param x
     * @param t
     * @return
     */
    private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
        //当前节点为空,则将该节点在此处
        if (t == null){
            return new BinaryNode<AnyType>(x, null, null);
        }
        //进行比较
        int compareResult = myCompare(x, t.theElement);
        //元素小于当前结点元素,则加入到左子树
        if (compareResult < 0){
            t.left = insert(x, t.left);
        } else if (compareResult > 0){
            t.right = insert(x, t.right);
        } else {
            //do nothing
        }
        return t;
    }

    /**
     * 实现移除某个节点
     * @param x
     * @param t
     * @return
     */
    private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
        if (t == null){
            return t;
        }
        //比较大小
        int compareResult = myCompare(x, t.theElement);
        //元素小于当前结点元素,则搜索左子树
        if (compareResult < 0){
            t.left = remove(x, t.left);
        }
        //元素大于当前结点元素,则搜索右子树
        else if (compareResult > 0){
            t.right = remove(x, t.right);
        }
        //相等,表示找到对应的节点,如果该节点存在左右孩子
        else if (t.left != null && t.right != null){
            //搜索到右子树的最小节点,并替代当前结点
            t.theElement = (AnyType) findMin(t.right).theElement;
            //并递归删除右子树的最小节点
            t.right = remove(t.theElement, t.right);
        }
        //否则,将不为空的孩子节点替代掉当前结点
        else {
            t = (t.left != null) ? t.left : t.right;
        }
        return t;
    }

    /**
     * 前序遍历
     * 访问顺序为:根节点->左节点->右节点
     * @param node
     */
    public void preOrder(BinaryNode<AnyType> node){
        if (node != null){
            System.out.print(node.right + " ");
            preOrder(node.left);
            preOrder(node.right);
        }
    }

    /**
     * 中序遍历
     * 访问顺序为:左节点->根节点->右节点
     * @param node
     */
    public void inOrder(BinaryNode<AnyType> node){
        if (node != null){
            inOrder(node.left);
            System.out.print(node.theElement + " ");
            inOrder(node.right);
        }
    }

    /**
     * 后序遍历
     * 访问顺序为:左节点->右节点->根节点
     * @param node
     */
    public void postOrder(BinaryNode<AnyType> node){
        if (node != null){
            postOrder(node.left);
            postOrder(node.right);
            System.out.print(node.theElement + " ");
        }
    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,999评论 4 368
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,102评论 1 302
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,709评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,439评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,846评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,881评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,062评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,783评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,517评论 1 248
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,762评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,241评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,568评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,236评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,145评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,941评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,965评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,802评论 2 275

推荐阅读更多精彩内容