数据结构之二叉树

package oder;
/*二叉树*/
import java.util.ArrayList;

@SuppressWarnings("all")
public class BinaryTree {

    private Node root;//根节点

    public BinaryTree() {
        root = null;
    }
    
    //关键字查找节点
    public Node find(int key){
        Node cur = root;//从根节点开始查找
        
        if(cur == null){
            return null;
        }
        
        
        while(cur.age != key){
            if(cur.age < key){
                cur = cur.leftChild;//如果关键字比当前节点小,转向左子节点
            }else{
                cur = cur.rightChid;//如果关键字不小于当前节点,转向右子节点
            }
            
            if(cur == null){
                return null;
            }
        }    
        return cur;
    }
    
    //插入新节点
    public void insert(Node node){
        if(node == null){
            root = node;//如果树为空,则新插入的节点为根节点
        }else{
            Node cur = root;
            
            while(true){
                if(node.age < cur.age){
                    if(cur.leftChild == null){
                        cur.leftChild = node;//找到要插入节点的父节点
                        return;
                    }
                    cur = cur.leftChild;
                }else{
                    if(cur.rightChid == null){
                        cur.rightChid = node;
                        return;
                    }
                    cur = cur.rightChid;
                }
            }
        }
        
    }
    
    //删除指定节点    
    public boolean delete(Node node){
        if(root == null){
            return false;//如果为空树,则直接返回false
        }
        
        boolean isLeftChild = true;//是否为父节点的左子节点
        Node cur = root;//需要删除的节点
        Node parent  = null;//需要删除的父节点
        
        while(cur.age != node.age){//确定要删除的节点和其父节点
            parent = cur;
            if(node.age < cur.age){
                cur = cur.leftChild;
            }else{
                isLeftChild = false;
                cur = cur.rightChid;
            }
            
            if(cur == null){
                return false;//没有找到要删除的
            }
        }
        
        if(cur.leftChild == null && cur.rightChid == null){//目标节点为叶子节点
            if(cur == null){//要删除的为根节点
                root = null;
            }else if(isLeftChild){
                //要删除的不是根节点,则该节点肯定有父节点,该节点删除后,需要将父节点指向它的引用置空
                parent.leftChild = null;
            }else{
                parent.rightChid = null;
            }
        }else if(cur.leftChild == null){
            if(cur == null){
                root = cur.rightChid;
            }else if(isLeftChild){
                parent.leftChild = cur.rightChid;
            }else{
                parent.rightChid = cur.rightChid;
            }
        }else if(cur.rightChid == null){
            if(cur == null){
                root = cur.leftChild;
            }else if(isLeftChild){
                parent.leftChild = cur.leftChild;            
            }else{
                parent.rightChid = cur.rightChid;
            }
        }else{//有两个子节点,第一步要找到欲删除节点的后继节点
            Node successor = cur.rightChid;
            Node successorParent = null;
            
            while(successor.leftChild != null){
                successorParent = successor;
                successor = successor.leftChild;
            }
            
            //欲删除的右子节点是它的后继,证明该后继无左子节点,则将以该后继节点为根的子树上移即可
            if(successorParent == null){
                if(cur == root){//要删除的为根节点,将后继设置为根,且根的左子节点设置为欲删除的节点的左子节点
                    root = successor;
                    root.leftChild = cur.leftChild;
                }else if(isLeftChild){
                    parent.leftChild = successor;
                    successor.leftChild = cur.leftChild;
                }else{
                    parent.rightChid = successor;
                    successor.leftChild = cur.leftChild;
                }
            }else{//欲删除的节点的后继不是它的右子节点
                successorParent.leftChild = successor.rightChid;
                successor.rightChid = cur.rightChid;
                if(cur == root){
                    root = successor;
                    successor.leftChild = cur.leftChild;
                }else if(isLeftChild){
                    parent.leftChild = root;
                    successor.leftChild = cur.leftChild;
                }else{
                    parent.leftChild = successor;
                    successor.leftChild = cur.leftChild;
                }
                
            }
        }
        return true;
    }
    
    public static final int PREORDER = 1;//前序遍历
    public static final int INORDER = 2;//中序遍历
    public static final int POSTORDER =3;//后序遍历
    
    //遍历
    public void traverse(int type){
        switch(type){
        case 1:
            System.out.println("前序遍历:\t");
            preorder(root);
            System.err.println();
            break;
        case 2:
            System.out.println("中序遍历:\t");
            inorder(root);
            System.out.println();
            break;
        case 3:
            System.out.println("后续遍历:\t");
            postorder(root);
            System.out.println();
            break;
        }
    }
    
    //前序遍历
    private void preorder(Node currentRoot) {
        if(currentRoot != null){
            System.out.println(currentRoot.age + "\t");
            preorder(currentRoot.leftChild);
            preorder(currentRoot.rightChid);
            
        }
    }

    //中序遍历
    private void inorder(Node currentRoot) {
        if(currentRoot != null){
            inorder(currentRoot.leftChild);//先对当前节点的左子树进行中序遍历
            System.out.println(currentRoot.age + "\t");//然后访问当前节点
            inorder(currentRoot.rightChid);//最后对当前节点的右子树进行中序遍历
        }
    }
        
    //后续遍历
    private void postorder(Node currentRoot) {
        if(currentRoot != null){
            System.out.println(currentRoot.age + "\t");
            postorder(currentRoot.leftChild);
            postorder(currentRoot.rightChid);
        }
    }

    //私有方法,用迭代方法来获得左子树和右子树的最大深度,返回两者的最大值
    private int getDepth(Node currentRoot,int initDeep){
        int deep = initDeep;//当前节点已达到的深度
        int leftDeep = initDeep;
        int rightDeep = initDeep;
        if(currentRoot.leftChild != null){
            getDepth(currentRoot.leftChild, deep+1);
        }else if(currentRoot.rightChid != null){
            getDepth(currentRoot.rightChid, deep+1);
        }
        return Math.max(leftDeep, rightDeep);
    }

    //获取树的深度
    public int getTreeDepth(){
        if(root == null){
            return 0;
        }
        return getDepth(root, 1);
    }
    
    //返回关键值得最大节点
    public Node getMax(){
        if(isEmpty()){
            return null;
        }
        Node cur = root;
        if(cur.rightChid != null){
            cur = cur.rightChid; 
        }
        return cur;
    }
    
    //返回关键值最小节点
    public Node getMin(){
        if(isEmpty()){
            return null;
        }
        Node cur = root;
        if(cur.rightChid != null){
            cur = cur.rightChid;
        }
        return cur;
    }
    
    //以树得形式打印出该树
    public void displayTree(){
        int treeDepth = getTreeDepth();
        ArrayList<Node> currentLayerNodes = new ArrayList<Node>();
        currentLayerNodes.add(root);//存储该层所有节点
        
        int layerIndex = 1;
        while(layerIndex <= treeDepth){
            int nodeBlankNum = (int)(Math.pow(2, treeDepth-layerIndex)-1);//在节点之前和之后应该打印几个空位
            for(int i = 0; i < currentLayerNodes.size(); i++){
                Node node = currentLayerNodes.get(i);
                printBlank(nodeBlankNum);//节点之前打印空位
                
                if(node == null){
                    System.out.println("*\t");
                }else{
                    System.out.println("* "+node.age+"\t");
                }
                printBlank(nodeBlankNum);//节点之后打印空位
                System.out.println("*\t");//补齐空位
            }
            System.out.println();
            layerIndex++;
            currentLayerNodes = getAllNodeOfThisLayer(currentLayerNodes);//获取下一层所有得节点
        }
    }

    private ArrayList<Node> getAllNodeOfThisLayer(ArrayList<Node> currentLayerNodes) {
        ArrayList<Node> nodeList = new ArrayList<Node>();
        Node parentNode;
        for(int i = 0; i < currentLayerNodes.size(); i++){
            parentNode = currentLayerNodes.get(i);
            if(parentNode != null){
                //如果上层左子节点存在,加入集合,如果不存在,用null代替,一样加入集合
                if(parentNode.leftChild != null){
                    nodeList.add(parentNode.leftChild);
                }else{
                    nodeList.add(null);
                }
                if(parentNode.rightChid != null){
                    nodeList.add(parentNode.rightChid);
                }else{
                    nodeList.add(null);
                }
            }else{
                //如果上层父节点不存在,用两个null占位,代表左右两个子节点
                nodeList.add(null);
                nodeList.add(null);
            }
        }
        return null;
    }

    public class Node{
        int age;
        String name;
        Node leftChild;//左子节点的引用
        Node rightChid;//右子节点的引用
        
        public Node(int age,String name) {
            this.age = age;
            this.name = name;
        }
        
        //打印该节点的信息
        public void displayNode(){
            System.out.println("name:" + name + ",age:" + age);
        }
    }
    
    //打印指定个数得空位
    public void printBlank(int num){
        for(int i= 0; i < num; i++){
            System.out.println("*\t");
        }
    }
    
    //判空
    public boolean isEmpty(){
        return (root == null);
    }
    
    //判断是否为叶子节点
    public boolean isLeaf(Node node){
        return (node.leftChild != null || node.rightChid != null);
    }
    
    //获取根节点
    public Node getRoot(){
        return root;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值