其他分享
首页 > 其他分享> > BSTree-二叉查找树

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