ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BSTree-二叉查找树

2022-03-26 16:31:12  阅读:174  来源: 互联网

标签:node end nil delNode self 二叉 查找 BSTree 节点


 BSTree的全称: Binary Search Tree

 

【规则】

# 左子节点的值总是小于父节点

# 右子节点的值总是大于父节点

 

【添加,查找】

# 添加和查找相对简单,按着规则来就可以,比当前值小左边(蓝色),大在右边(黄色)

 【删除】

# 首先是要找到要删除的节点,然后再按下面的情况来删除

(a) 待删除节点(蓝色)没有子节点:直接删除

 (b) 待删除节点没有左孩子,删除后将它的右孩子移过去。如图中的20,30,19都是没有左孩子的节点

# 3个节点分别删除后

 (c) 待删除节点没有右孩子,删除后将它的左孩子移过去。

(d) 待删除节点左右孩子都有,在待删除节点的右子树中找到值最小的节点,用它的值替换待删除节点的值,然后删除那个最小的节点。

# 11为待删除节点,先在右子树找到最小的节点12,12值替换11,最后删除节点12(使用规则b)

# 11为待删除节点,先在右子树找到最小的节点12,12值替换11,最后删除节点12(使用规则a)

 # 其他的一些情况:待删除节点的右子树都是右孩子

# 待删除的节点在根节点

 

local Node = {}
Node.__cname = "util.BSTree.Node"
Node.__index = Node

function Node.new(v)
    local obj = {}
    setmetatable(obj, Node)
    obj:ctor(v)
    return obj
end

function Node:ctor(v)
    self.value = v
    self.left = nil
    self.right = nil
end

 

local BSTree = {}
BSTree.__cname = "util.BSTree"
BSTree.__index = BSTree

function BSTree.new(cmpFunc)
    local obj = {}
    setmetatable(obj, BSTree)
    obj:ctor(cmpFunc)
    return obj
end

function BSTree:ctor(cmpFunc)
    self.cmpFunc = cmpFunc
    self.count = 0
    self.root = nil
end

function BSTree:Clear()
    self.count = 0
    self.root = nil
end

function BSTree:GetCount()
    return self.count
end

function BSTree:Add(v)
    local newNode = Node.new(v)
    if nil == self.root then
        self.root = newNode
        self.count = self.count + 1
        return
    end

    local node = self.root
    while nil ~= node do
        local cmpResult = self.cmpFunc(v, node.value)
        if cmpResult < 0 then --小: 在左子树添加
            if nil == node.left then
                node.left = newNode
                self.count = self.count + 1
                break
            else
                node = node.left
            end
        elseif cmpResult > 0 then --大: 在右子树添加
            if nil == node.right then
                node.right = newNode
                self.count = self.count + 1
                break
            else
                node = node.right
            end
        else
            print(tostring(v), "have exist, ignore")
        end
    end
end

function BSTree:Contains(v)
    if self.count < 1 then return false end
    local node = self.root
    while nil ~= node do
        local cmpResult = self.cmpFunc(v, node.value)
        if cmpResult < 0 then
            node = node.left
        elseif cmpResult > 0 then
            node = node.right
        else
            return true
        end
    end
    return false
end

function BSTree:Remove(v)
    if self.count < 1 then return false end

    local parent = nil
    local node = self.root
    while nil ~= node do
        local cmpResult = self.cmpFunc(v, node.value)
        if cmpResult < 0 then
            parent = node
            node = node.left
        elseif cmpResult > 0 then
            parent = node
            node = node.right
        else
            self:_DelNode(node, parent)
            self.count = self.count - 1
            return true
        end
    end
    return false
end

function BSTree:_DelNode(delNode, delNodeParent)
    if nil == delNode.left and nil == delNode.right then --删除节点没有子节点, 直接删除(断开与parent的关系)
        if delNode == self.root then
            self.root = nil
        elseif delNodeParent.left == delNode then
            delNodeParent.left = nil
        elseif delNodeParent.right == delNode then
            delNodeParent.right = nil
        else
            print("error")
        end
    elseif nil == delNode.left then --删除节点只有右子节点, 断开与parent的关系, parent子节点直接指向那个右子节点
        if delNode == self.root then
            self.root = delNode.right
        elseif delNodeParent.left == delNode then
            delNodeParent.left = delNode.right
        elseif delNodeParent.right == delNode then
            delNodeParent.right = delNode.right
        else
            print("error")
        end
        delNode.right = nil --断开节点关系
    elseif nil == delNode.right then --删除节点只有左子节点, 断开与parent的关系, parent子节点直接指向那个左子节点
        if delNode == self.root then
            self.root = delNode.left
        elseif delNodeParent.left == delNode then
            delNodeParent.left = delNode.left
        elseif delNodeParent.right == delNode then
            delNodeParent.right = delNode.left
        else
            print("error")
        end
        delNode.left = nil --断开节点关系
    else --左右子节点都有, 右子树中找一个最小的节点替换到删除节点处
        local replaceNode, replaceNodeParent = self:_FindReplaceNode(delNode)
        delNode.value = replaceNode.value
        self:_DelNode(replaceNode, replaceNodeParent)
    end
end

function BSTree:_FindReplaceNode(delNode)
    local parent = delNode
    local node = delNode.right
    while nil ~= node do
        if nil ~= node.left then
            parent = node
            node = node.left
        else
            return node, parent
        end
    end
    print("error")
end

function BSTree:__tostring()
    if self.count < 1 then return "" end
    local strTb = {}
    local queue = {}
    table.insert(queue, self.root)

    while #queue > 0 do
        local node = queue[1]
        table.remove(queue, 1)
        table.insert(strTb, tostring(node.value))

        if nil ~= node.left then
            table.insert(queue, node.left)
        end
        if nil ~= node.right then
            table.insert(queue, node.right)
        end
    end
    return table.concat(strTb, ",")
end

return BSTree

 

【参考】

【数据结构】——搜索二叉树的插入,查找和删除(递归&非递归) - 龙跃十二 - 博客园 (cnblogs.com)

搜索算法—二叉搜索树 - MichaelCen - 博客园 (cnblogs.com), 讲的非常全,Floor, Ceil, Rank都讲到了

 

标签:node,end,nil,delNode,self,二叉,查找,BSTree,节点
来源: https://www.cnblogs.com/sailJs/p/16049868.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有