二叉树排序

二叉树排序代码实现(重复数据无法插入)

public class MyTree {

Node root;//根节点
class Node{
    Node left;//左儿子
    Node right;//右儿子
    Node parent;//父节点
    Object data;//数据
    public Node(Object data) {
        super();
        this.data = data;
    }
}

/**
 * 打印整个二叉树
 */
public void print(){
    see(root);
}

/**
 * 从node节点开始察看二叉树
 * @param node
 */
public void see(Node node){
    if (node != null) {
        see(node.left);
        System.out.println(node.data);
        see(node.right);
    }
}

/**
 * 不可重复添加数据
 * @param data
 */
public void add(Object data){
    //判断data是否已经存在
    Node node = findNode(data);
    if (node == null) {
        //数据不存在
        //可以添加
        //创建节点将数据放入节点中
        node = new Node(data);
        if (root == null) {
            //二叉树为空
            root = node;
        }else {
            //二叉树不为空
            Node parent = findparent(data,root);
            //认爹
            node.parent = parent;
            //爹认孩子
            if (compare(parent.data, node.data) > 0) {
                //左儿子
                parent.left = node;
            }else {
                //右儿子
                parent.right = node;
            }
        }
    }else {
        //数据已经存在,不能再添加
        return;
    }
}

/**
 * 删除数据
 * @param data
 */
public void remove(Object data){
    //判断数据是否在二叉树中
    Node node = findNode(data);
    if (node == null) {
        //数据不在二叉树中
        return;
    }else {
        //数据在二叉树中
        delete(node);
    }
}

/**
 * 删除某个节点
 * @param node
 */
private void delete(Node node) {
    if (root == node) {
        //1.删除根节点
        if (node.left == null && node.right == null) {
            //1.1没有儿子
            root = null;
        }else if (node.right == null) {
            //1.2只有左儿子
            //左儿子继位
            root = root.left;
            //断开左儿子的parent指针对node的引用
            root.parent = null;
        }else if (node.left == null) {
            //1.3只有右儿子
            //右儿子继位
            root = root.right;
            //断开右儿子的parent指针对node的引用
            root.parent = null;
        }else {
            //1.4有两个儿子
            Node left = splite(node);
            //左儿子继位
            root = left;
            //断开left的parent属性对node的引用
            left.parent = null;
        }
    }else {
        //2.删除非根节点
        if (node.left == null && node.right == null) {
            //2.1没有儿子
            //判断node到底是左儿子还是右儿子
            Node parent = node.parent;
            if (compare(parent.data, node.data) > 0) {
                //说明node是左儿子
                parent.left = null;
            }else {
                //说明node是右儿子
                parent.right = null;
            }
        }else if (node.right == null) {
            //2.2只有左儿子
            //断开左儿子的parent指针对node的引用
            node.left.parent = node.parent;
            //断开node的父节点的left/right指针对node的引用
            //判断node是它的父节点的左儿子还是右儿子
            Node parent = node.parent;//node的父节点
            if (compare(parent.data, node.data) > 0) {
                //node是左儿子
                parent.left = node.left;
            }else {
                //node是右儿子
                parent.right = node.left;
            }
        }else if (node.left == null) {
            //2.3只有右儿子
            //断开右儿子的parent指针对node的引用
            node.right.parent = node.parent;
            //断开node 的父节点的left/right指针对node的引用
            //判断node到底是左儿子还是右儿子
            Node parent = node.parent;
            if (compare(parent.data, node.data) > 0) {
                //node是左儿子
                parent.left = node.right;
            }else {
                //node是右儿子
                parent.right = node.right;
            }
        }else {
            //2.4有两儿子
            //分裂node的两个儿子,保留左儿子,将右儿子放到左儿子的最右边(断开node的右儿子的parent指针对node的引用)
            Node left = splite(node);
            //断开node的左儿子的parent指针对node的引用
            left.parent = node.parent;
            //断开node的父节点的left/right指针对node的引用
            //判断node到底是左儿子还是右儿子
            Node parent = node.parent;//node的父节点
            if (compare(node.parent.data, node.data) > 0) {
                //node是左儿子
                parent.left = left;
            }else {
                //node是右儿子
                parent.right = left;
            }
        }
    }
}

/**
 * 分裂两个儿子,保留左儿子,将右儿子放到左儿子的最右边
 * @param node
 * @return
 */
private Node splite(Node node) {
    Node left = node.left;
    Node right = node.right;
    //开始给right找新爹
    Node parent = findparent(right.data, left);
    //right认爹
    right.parent = parent;
    //parent认儿子
    parent.right = right;
    return left;
}

/**
 * 比较两个数据大小的方法
 * @param data1
 * @param data2
 * @return
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public int compare(Object data1,Object data2){
    Comparable c1 = null;
    Comparable c2 = null;
    if (data1 instanceof Comparable) {
        c1 = (Comparable) data1;
        c2 = (Comparable) data2;
    }else {
        c1 = data1.toString();
        c2 = data2.toString();
    }
    return c1.compareTo(c2);
}

/**
 * 从node节点开始遍历给data找父节点
 * @param data
 * @return
 */
private Node findparent(Object data,Node node) {
    //从根节点开始遍历
    //Node node = root;
    Node parent = null;
    while(node != null){
        parent = node;
        //判断node.data与data的大小
        if (compare(data, node.data) > 0) {
            //data大,往右找
            node = node.right;
        }else {
            node = node.left;
        }
    }
    return parent;
}

/**
 * 找数据所在的节点
 * @param data
 * @return
 */
private Node findNode(Object data) {
    //从根节点开始遍历
    Node node = root;
    while(node != null){
        if (node.data.equals(data) && node.data.hashCode() == data.hashCode()) {
            //找到了
            break;
        }else {
            //如果没找到
            //比较data与node.data的大小
            if (compare(data, node.data) > 0) {
                //data大,往右找
                node = node.right;
            }else {
                //往左找
                node = node.left;
            }
        }
    }
    return node;
}

}

/测试案例/

public class Testtree {

public static void main(String[] args) {
    MyTree tree = new MyTree();
    tree.add(38);
    tree.add(28);
    tree.add(48);
    tree.add(24);
    tree.add(32);
    tree.add(40);
    tree.add(55);
    tree.add(30);
    tree.add(20);
    tree.remove(32);
    tree.print();
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值