<数据结构与算法>之二叉查找树

  1. 基本概念:
    关于二叉查找树的概念我就不在这里说了,可以查看之前的一篇博客二叉树初看。这里主要写对二叉查找树的java 实现吧。
  2. java实现
    1) 二叉查找树数据结构:
private class TreeNode {  
        private int key;  
        private TreeNode leftChild;
        private TreeNode rightChild;
        private TreeNode parent;
        public TreeNode(int key, TreeNode leftChild, TreeNode rightChild,  
                TreeNode parent) {  
            this.key = key;  
            this.leftChild = leftChild;  
            this.rightChild = rightChild;  
            this.parent = parent;  
        }
        public int getKey() {  
            return key;  
        }
        public String toString() {  
            String leftkey = (leftChild == null ? "" : String  
                    .valueOf(leftChild.key));  
            String rightkey = (rightChild == null ? "" : String  
                    .valueOf(rightChild.key));  
            return "(" + leftkey + " , " + key + " , " + rightkey + ")";  
        }
    } 

2)查找节点

    /**
     * 查找给定的关键字
     * */
    public TreeNode search(int key) {
        TreeNode pNode = root;
        while(pNode != null && pNode.key != key) {
            if(pNode.key > key) {
                pNode = pNode.leftChild;
            } else {
                pNode = pNode.rightChild;
            }
        }
        return pNode;
    }
    /**
     * 查找最小关键字节点
     * @throws Exception 
     * */
    public TreeNode minKeyTreeNode(TreeNode node) throws Exception {
        if(node == null) {
            throw new Exception("树为空");
        }
        TreeNode pNode = node;
        while(pNode.leftChild != null) {
            pNode = pNode.leftChild;
        }
        return pNode;
    }
    /**
     * 查找最大关键字的节点
     * @throws Exception 
     * */
    public TreeNode maxKeyTreeNode(TreeNode node) throws Exception {
        if(node == null) {
            throw new Exception("树为空");
        }
        TreeNode pNode = node;
        while(pNode.rightChild != null) {
            pNode = pNode.rightChild;
        }
        return pNode;
    }
    /**
     * 获取给定节点的在中序遍历的条件下的后继节点
     * 有三个情况:1)如果当前节点有右孩子,则后继是右子树的最左节点
     * 2)当前节点无右孩子,如果当前节点是父亲节点的左儿子,则后继是父亲节点
     * 3)当前节点无右孩子,且是父亲节点的右孩子,则所在字树遍历完了,向上寻找一个作为左孩子的祖先节点,那下一个遍历的是该祖先节点的父亲节点。
     * 如果上面的情况都没有,则该节点是树的最后一个节点,无后继节点。
     * */
    public TreeNode successorInOrder(TreeNode node) throws Exception {
        if(node == null) {
            return null;
        }
        // 如果该节点的右节点不为空,则其后继节点就是右子树中的最小关键字节点
        if(node.rightChild != null) {
            return minKeyTreeNode(node.rightChild);
        }
        TreeNode parentNode = node.parent;
        while (parentNode != null && node == parentNode.rightChild) {  
            node = parentNode;  
            parentNode = parentNode.parent;  
        }  
        return parentNode;
    }
    /**
     * 获取给定节点在中序条件下的前序节点
     * 如果x有左孩子,则前驱节点是左子树中最大关键字节点
     * x无左孩子,若x是父亲节点的右孩子,则x的前驱节点为其父亲节点
     * x无左孩子,x是父亲节点的左孩子,则x的前驱节点是x的某一个祖先节点的父亲节点,并且该祖先节点是其父亲节点的右孩子
     * */
    public TreeNode presuccessor(TreeNode node) {
        if(node == null) {
            return null;
        }
        if(node.leftChild != null) {
            return maxKeyTreeNode(node.leftChild);
        }
        TreeNode parentNode = node.parent;
        while(parentNode != null && node == parentNode.leftChild) {
            node = parentNode;
            parentNode = parentNode.parent;
        }
        return parentNode;
    }

3) 插入节点

    /**
     * 将给定的关键字插入到二叉查找树中
     * */
    public void insert(int key) {
        TreeNode parentNode = null;
        TreeNode newNode =  new TreeNode(key, null, null, null);
        TreeNode pNode = root;
        if (root == null) {
            root = newNode;
            return ;
        }
        while(pNode != null) {
            parentNode = pNode;
            if(key < pNode.key) {
                pNode = pNode.leftChild;
            } else if(key > pNode.key) {
                pNode = pNode.rightChild;
            } else {
                return ; // 二叉查找树中已经存在要插入的关键字,返回
            }
        }
        if(key < parentNode.key) {
            parentNode.leftChild = newNode;
            newNode.parent = parentNode;
        } else {
            parentNode.rightChild = newNode;
            newNode.parent = parentNode;
        }
    }

4) 删除节点

    /**
     * 删除节点
     * @throws Exception 
     * */
    public void delete(int key) throws Exception {
        TreeNode pNode = search(key);
        if(pNode == null) {
            throw new Exception("树中不存在要删除的关键字");
        }
        delete(pNode);
    }
    /**
     * 从二叉查找树中删除给定的节点
     * 前置条件:给定节点在二叉查找树中已经存在
     * @throws Exception 
     * */
    public void delete(TreeNode pNode) throws Exception {
        if(pNode == null) {
            return ;
        }
        if(pNode.leftChild == null && pNode.rightChild == null) {
            TreeNode parentNode = pNode.parent;
            if(parentNode == parentNode.leftChild) {
                parentNode.leftChild = null;
            } else {
                parentNode.rightChild = null;
            }
            return ;
        }
        if(pNode.leftChild == null && pNode.rightChild != null) {
            TreeNode parentNode = pNode.parent;
            if(pNode == parentNode.leftChild) {
                parentNode.leftChild = parentNode.rightChild;
                pNode.rightChild.parent = parentNode;
            } else {
                parentNode.rightChild = pNode.rightChild;
                pNode.rightChild.parent = parentNode;
            }
            return ;
        }
        if(pNode.leftChild != null && pNode.rightChild == null) {
            TreeNode parentNode = pNode.parent;
            if(pNode == parentNode.leftChild) {
                parentNode.leftChild = pNode.leftChild;
                pNode.leftChild.parent = parentNode;
            } else {
                parentNode.rightChild = pNode.leftChild;  
                pNode.rightChild.parent = parentNode;
            }
            return ;
        }
        // 该结点左右孩子结点均非空,则删除该结点的后继结点,并用该后继结点取代该结点  
        TreeNode successorNode = successorInOrder(pNode);//找到该节点的后继节点
        delete(successorNode);
        pNode.key = successorNode.key;
    }

5) 遍历二叉树

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值