• 树结构_二叉搜索树


    二叉搜索树(BST, Binary Search Tree)

      1. 二叉树也是一颗二叉树, 可以为空

      2. 如果不为空,则满足以下条件

                    1. 非空左子树的所有键值小于其根节点的键值

                    2. 非空右子树的所有键值大于其根节点的键值

                    3. 左, 右子树本身也是搜索树

      3. 二叉搜索树的特点

                    1. 二叉搜索树中,相对较小的值总包存在左节点上, 嫌贵较大的值总是保存在右节点上

                        注: 这一特性可以保证二叉搜索树高效的送偶所特性

      4. 二叉搜索树的节点的属性

                    this.item = item

                    this.left = null

                    this.right = null 

      5. 二叉搜索树的属性

      6. 二叉搜索树的方法

                    1. insertItem(item)                     向树中插入一个新的键

                    2. search(key)                          查看树中是否包含指定的键值,若节点存在则返回true,否则返回false

                    3. preOrderTravel()                     先序遍历

                    4. inOrderTravel()                      中序遍历

                    5. postOrderTravel()                    后序遍历

                    6.                                      层序遍历

                    7. min()                                返回书中最小的值/键

                    8. max()                                返回树中最大的值/键

                    9. remove(key)                          从树中移除某个键

      7. remove方法思路

                    删除的节点分三种情况:

                        1. 被删除的节点为叶节点(即没有子节点)

                        2. 被删除的节点只有一个子节点

                        3. 被删除的节点有两个子节点

      8. 二叉搜索树的嗲马实现

      

        function BinarySarchTree(){
            // 1. 封装节点类
            function Node(item){
                this.item = item;
                this.left = null;
                this.right = null;
            }
    
            // 2. 二叉搜索树的属性
            this.root = null;
    
            // // 3. 二叉搜索树的方法
            // 1. 向树中插入一个新的键
            BinarySarchTree.prototype.insertItem = function(key){
                // 1. 首先创建节点
                var newNode = new Node(key);
    
                // 2. 首先判断根节点是否有值
                if(this.root == null){
                    this.root = newNode;
                }else{
                    this.insertNode(this.root, newNode);
                }
            }
            // 内部函数——插入节点
            BinarySarchTree.prototype.insertNode = function(node, newNode){
                if(newNode.item < node.item){
                    // 向左查找
                    if(node.left == null){
                        node.left = newNode;
                    }else{
                        this.insertNode(node.left, newNode);
                    }
                }else{
                    // 向右查找
                    if(node.right == null){
                        node.right = newNode;
                    }else{
                        this.insertNode(node.right, newNode);
                    }
                }
            }
    
            // 2. 查看树中是否包含指定的键值,若节点存在则返回true,否则返回false
            BinarySarchTree.prototype.search = function(key){
                var node = this.root;
                while(node != null){
                    if(key < node.item){
                        node = node.left;
                    }else if(key > node.item){
                        node = node.right;
                    }else{
                        return true;
                    }
                }
                return false;
            }
    
            // 3. 先序遍历
            /* 
                遍历过程:
                    1. 访问根节点
                    2. 先序遍历其左子树
                    3. 先序遍历其右子树
            */
            BinarySarchTree.prototype.preOrderTravel = function(handler){
                this.preOrderTravelNode(this.root, handler);
            } 
            // 内部函数——先序遍历
            BinarySarchTree.prototype.preOrderTravelNode = function(node, handler){
                // 若节点不为空
                if(node !== null){
                    // 1. 调用回调函数
                    handler(node.item);
    
                    // 2. 处理左子树
                    this.preOrderTravelNode(node.left, handler);
    
                    // 3. 处理右子树
                    this.preOrderTravelNode(node.right, handler);
                }
            }
    
            // 4. 中序遍历
            /*
                遍历过程:
                    1. 先序遍历其左子树
                    2. 访问根节点
                    3. 先序遍历其右子树
            */
            BinarySarchTree.prototype.inOrderTravel = function(handler){
                this.inOrderTravelNode(this.root, handler);
            }
            // 内部函数——先序遍历
            BinarySarchTree.prototype.inOrderTravelNode = function(node, handler){
                // 若节点不为空
                if(node !== null){
                    // 1. 处理左子树
                    this.inOrderTravelNode(node.left, handler);
    
                    // 2. 调用回调函数
                    handler(node.item);
    
                    // 3. 处理右子树
                    this.inOrderTravelNode(node.right, handler);
                }
            }
    
            // 5. 后序遍历
             /*
                遍历过程:
                    1. 先序遍历其左子树
                    2. 先序遍历其右子树
                    3. 访问根节点
            */
            BinarySarchTree.prototype.postOrderTravel = function(handler){
                this.postOrderTravelNode(this.root, handler);
            }
            // 内部函数——先序遍历
            BinarySarchTree.prototype.postOrderTravelNode = function(node, handler){
                // 若节点不为空
                if(node !== null){
                    // 1. 处理左子树
                    this.postOrderTravelNode(node.left, handler);
    
                    // 2. 处理右子树
                    this.postOrderTravelNode(node.right, handler);
    
                    // 3. 调用回调函数
                    handler(node.item);
                }
            } 
    
            // 6. 层序遍历
    
            // 7. 返回树中最小的值/键
            BinarySarchTree.prototype.min = function(){
                var cur = this.root;
                if(cur == null){
                    return null;
                }
    
                // 依次向左查找
                while(cur.left != null){
                    cur = cur.left;
                }
                return cur.item;
    
            }
    
            // 8. 返回树中最大的值/键
            BinarySarchTree.prototype.max = function(){
                var cur = this.root;
                if(cur == null){
                    return null;
                }
    
                // 依次向右查找
                while(cur.right != null){
                    cur = cur.right;
                }
                return cur.item;
            }
    
    
            // 9. 从树中移除某个键
            BinarySarchTree.prototype.remove = function(key){
                // 1. 寻找需要删除的节点
                var cur = this.root;
                var parent = null;
                var isLeft = true;
                if(cur == null){
                    return false;
                }else{
                    while(key != cur.item){
                        parent = cur;
                        if(key < cur.item){
                            cur = cur.left;
                            isLeft = true;
                        }else{
                            cur = cur.right;
                            isLeft = false;
                        }
    
                        // 若cur为空,则说明没找到,直接返回
                        if(cur == null){
                            return false;
                        }
                    }
    
                    // 能跳出while循环,则说明找到了
                    // 找到的节点为cur,其父节点为parent
                    // 2. 判断所找到的节点类型
                    // 2.1 若被删除的节点为叶节点
                    if(cur.left == null && cur.right == null){
                        if(cur == this.root){
                            this.root = null;
                        }else if(isLeft == true){
                            // 若需要删除的叶节点为父节点的左子节点,则将右子节点赋值给左子节点, 然后将右子节点置为空
                            parent.left =  null
                        }
                    }
    
                    // 2.2 若被删除的节点只有一个子节点
                    else if(cur.left == null){
                        if(cur == this.root){
                            this.root = cur.right;
                        }
                        // cur.left = null 说明cur节点的左节点为空,右节点不为空
                        else if(isLeft == true){
                            parent.left = cur.right;
                        }else{
                            parent.right = cur.right;
                        }
                    }else if(cur.right == null){
                        if(cur == this.root){
                            this.root = cur.left;
                        }
                        // cur.right = null 说明cur节点的左节不为空,右节点为空
                        else if(isLeft == true){
                            parent.left = cur.left;
                        }else{
                            parent.right = cur.left;
                        }
                    }
                }
            }
        }
    View Code
  • 相关阅读:
    Eclipse的tab键为4个空格完整方法 附:阿里代码开发规范书
    Linux系统 安装JDK和tomcat
    Window10安装linux
    oracle 查询表重复数据 并 删除保留一条
    Oracle 新增数据 insert into整理
    业需软需word小技巧
    oracle数据库创建表且主键自增
    eclipse更改jdk版本(1.6》1.7 以此类推)
    pytest框架优化——清理历史截图图片和allure报告文件
    allure定制化输出测试报告,让报告锦上添花!
  • 原文地址:https://www.cnblogs.com/carreyBlog/p/13657129.html
Copyright © 2020-2023  润新知