美文网首页
二叉排序树

二叉排序树

作者: scarerow | 来源:发表于2017-11-17 08:46 被阅读0次

二叉排序树百度百科定义

二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树


二叉排序树或者是一棵空树,或者是具有下列性质的二叉树

  • (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;

  • (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;

  • (3)左、右子树也分别为二叉排序树;

百度百科图.png

二叉排序树代码实现

数据结构

public class TreeNode{
        int data;
        // 左子树(节点)
        TreeNode leftChild;
        // 右子树(右节点)
        TreeNode rightChild;
        // 父节点
        TreeNode parent;
        public TreeNode(int data) {
            super();
            this.data = data;
            this.leftChild = null;
            this.rightChild = null;
            this.parent = null;
        }
        public int getData() {
            return data;
        }
        public void setData(int data) {
            this.data = data;
        }
        public TreeNode getLeftChild() {
            return leftChild;
        }
        public void setLeftChild(TreeNode leftChild) {
            this.leftChild = leftChild;
        }
        public TreeNode getRightChild() {
            return rightChild;
        }
        public void setRightChild(TreeNode rightChild) {
            this.rightChild = rightChild;
        }
        public TreeNode getParent() {
            return parent;
        }
        public void setParent(TreeNode parent) {
            this.parent = parent;
        }
    }

插入

插入原理:

  1. 如果根节点为空,插入根节点
  2. 依次和每个节点比较,大于获取节点右边,小于获取节点左边,直到查到到叶子节点
  3. 和查找到的叶子节点比较,决定放到左边还是右边
  4. 插入节点的父节点等于查找到的节点
public TreeNode put(int data) {
      //根节点为空,插入根节点
        if (root == null) {
            TreeNode node = new TreeNode(data);
            root = node;
            return node;
        }
        
        
        //依次和每个节点比较,大于获取节点右边,小于获取节点左边
        // 直到查到到叶子节点
        TreeNode parent = null;
        TreeNode node = root;
        for(; node != null;) {
            // parent 作用是记录查找符合要求的叶子节点
            parent = node;
            if (data < node.data) {
                node = node.leftChild;
            } else if(data > node.data) {
                node = node.rightChild;
            } else {
                return node;
            }
        }
        // 和查找到的叶子节点比较,决定放到左边还是右边
        TreeNode newNode = new TreeNode(data);
        if (data < parent.data) {
            parent.leftChild = newNode;
        } else {
            parent.rightChild = newNode;
        }
        
        // 有坑
        newNode.parent = parent;
        return newNode;
        
    }

查找

查找节点的原理

  1. 判断是否为空树,如果为空,返回null
  2. 用输入值(data)和节点值(node.data)比较,如果data > node.data,data再与node的右子节点比较,
    如果data < node.data,data再与node的左子节点比较
  3. 如此循环,知道找到node.data = data ,返回node,或者查找到叶子节点还没找到,返回空
public TreeNode searchNode (int data) { 
        if (root == null) {
            return null;
        }
        TreeNode node = root;
        while (node != null) {
           if (node.data == data) {
               return node;
           } else if (node.data < data) {
               node = node.rightChild;
           } else if(node.data > data) {
               node = node.leftChild;
           }
        }   
        return null;
    }

删除

/**
     * 删除一个节点
     * @param node
     */
    private void delNode(TreeNode node){
        if(node == null) {
            throw new NoSuchElementException();
        } else {
            
            // 一 先找到parent节点
            TreeNode parent = node.parent;
            //1:没有孩子
            if (node.leftChild ==null && node.rightChild ==null) {
                if (parent == null) {
                    //只有一个Root节点,删除掉,树就变成了空树
                    root = null;
                } else if (parent.rightChild == node) {
                    parent.rightChild = null;
                } else if(parent.leftChild == node) {
                    parent.leftChild = null;
                }
                node.parent = null;
            } else if (node.leftChild != null && node.rightChild == null) {
                //2:只有左孩子
                if (parent == null) {
                    // 删除root节点
                    node.parent = null;
                    node.leftChild.parent = null;
                    root = node.leftChild;
                } else {
                    //判断删除的节点是父节点的左节点,还是右节点
                    if (parent.leftChild == node) {
                        parent.leftChild = node.leftChild;
                    } else {
                        parent.rightChild = node.leftChild;
                    }
                    node.parent = null;
                }
            } else if (node.leftChild == null && node.rightChild != null) {
                //3:只有右孩子
                if (parent == null) {
                    // 删除root节点
                    node.parent = null;
                    node.rightChild.parent = null;
                    root = node.rightChild;
                } else {
                    //判断删除的节点是父节点的左节点,还是右节点
                    if (parent.leftChild == node) {
                        parent.leftChild = node.rightChild;
                    } else {
                        parent.rightChild = node.rightChild;
                    }
                    node.parent = null;
                }
            } else {
                /*
                 * 有左右两个孩子的步骤
                 * 一 找到右边子树的最小值节点   占用被删除节点的位置
                 * 二 
                 * 
                 * 
                 * */
                
                
                //4:有左右两个孩子
                
                
               // 情况一 :删除节点的右子树的左子树为空,则把要删除节点的左子树设为删除点的右子树的左子树
                if (node.rightChild.leftChild == null) {
                    node.rightChild.leftChild = node.leftChild;
                    if (parent == null) {
                        // 只有一个root节点情况
                        root = node.rightChild;
                    } else {
                        // 判断被删除节点 是左 是右
                        if (parent.leftChild == node) {
                            parent.leftChild = node.rightChild;
                        } else {
                            parent.rightChild = node.rightChild;
                        }
                    }
                    node.parent = null;
                } else {
                    
                    //  情况二 : 被删除节点的右节点的左子树不为空
                    
                    /*
                     * leftNode : 删除节点的右子树的最左节点
                     * node :被删除的节点
                     * leftNodeP :leftNode的父节点
                     * */
                    // 1 找到被删除节点的 右子树的最小值节点(这个值最接近被删除节点的值)
                    TreeNode leftNode = getMinLeftTreeNode(node.rightChild);
                    // 2 leftNode接收删除节点的左子树
                    leftNode.leftChild = node.leftChild;
                    // 3 leftNode的右子树 作为leftNodeP的左子树
                    TreeNode leftNodeP = leftNode.parent;
                    leftNodeP.leftChild = leftNode.rightChild;
                    
                    //4 leftNode的右子树 = node的右子树
                    leftNode.rightChild = node.rightChild;
                    // 5 parent 指向新的节点
                    if (parent == null) {
                        root = leftNode;
                    } else {
                        // 判断删除的节点是父节点的左还是右 
                        if (parent.leftChild == node) {
                            parent.leftChild = leftNode;
                        } else {
                            parent.rightChild = leftNode;
                        }
                    }
                }   
            }
        }   
    }
private TreeNode getMinLeftTreeNode(TreeNode node) {
        TreeNode curRoot = null;
        if (node == null) {
            return null;
        } else {
            curRoot = node;
            while(curRoot.leftChild != null) {
                curRoot = curRoot.leftChild;
            }
        }
        return curRoot;
    }


二叉树bmli

    public void midOrderTraverse(TreeNode root) {
        if (root == null) {
            return;
        }
        midOrderTraverse(root.leftChild);
        System.out.print(root.data + "  ");
        midOrderTraverse(root.rightChild);
    }
    
    
    public void preOrderTraverse(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.println("pre Order: " + root.data);
        preOrderTraverse(root.leftChild);
        preOrderTraverse(root.rightChild);
    }

public void postOrderTraverse(TreeNode root) {
        if (root == null) {
            return;
        }
        preOrderTraverse(root.leftChild);
        preOrderTraverse(root.rightChild);
                System.out.println("pre Order: " + root.data);
    }

相关文章

  • 详解Java二叉排序树

    姓名: 李小娜 [嵌牛导读] :这篇文章主要介绍了Java二叉排序树,包括二叉排序树的定义、二叉排序树的性质、二叉...

  • Java数据结构:二叉排序树(BST)

    一、基本介绍 二叉排序树 BST: (Binary Sort(Search) Tree), 对于二叉排序树的任何一...

  • 2018-06-19/20 机试准备09

    数据结构 四、二叉排序树 对二叉排序树进行中序遍历 结果必然是一个递增序列 所以通过建立二叉排序树可以对无序序列进...

  • 二叉搜索树(BST)

    构造一棵二叉排序树的目的,其实并不是为了排序,而是为了提高查找的效率。 那么什么是二叉排序树呢?二叉排序树具有以下...

  • Binary Search Tree

    如果二叉排序树是平衡的,则n个节点的二叉排序树的高度为 ,其查找效率为 ,近似于折半查找。如果二叉排序树完全不平衡...

  • 红黑树

    二叉排序树 非空二叉排序树具有如下特点: 二叉排序树中,如果其根结点有左子树,那么左子树上所有结点的值都小于根结点...

  • 数据结构之二叉排序树

    二叉排序数 1.二叉排序树介绍 二叉排序树:BST: (Binary Sort(Search) Tree), 对于...

  • 数据结构学习第四弹 二叉排序树

    二叉排序树又称为二叉搜索树或二叉查找树,这是一种插入、删除和检索记录效率都很高的树结构 二叉排序树概念 二叉排序树...

  • 数据结构与算法——基础篇(五)

    二叉排序树——BST——Binary Sort(Search) Tree 二叉排序树的出现是为了解决数组的查询快,...

  • 看图说话之平衡二叉排序树

    本文在看图说话之二叉排序树的基础上介绍了平衡二叉排序树,结构性较好的二叉排序树其插入和删除操作的时间复杂度接近Lo...

网友评论

      本文标题:二叉排序树

      本文链接:https://www.haomeiwen.com/subject/cxedvxtx.html