二叉搜索树——python

二叉搜索树

  • 首先是一棵二叉树
  • 满足性质:
    • 设x是二叉树的一个节点。如果y是x左子树的一个节点,那么y.key <= x.key;如果y是x的右子树的一个节点,那么y.key >= x.key
  • 二叉搜索树的操作:查询、插入、删除

插入——构建

class BiTreeNode():  
    def __init__(self,data):  
        self.data = data  
        self.lchild = None  
 		self.rchild = None  
 		self.parent = None  
  
  
class BST():  
    def __init__(self, li=None):  
        self.root = None  
 		if li:  
            for val in li:  
                self.insert_no_rec(val)  
  
    def insert(self, node, val):    # 插入函数  
 		if not node:                # 如果node是空  
 			node = BiTreeNode(val)  
        elif val < node.data:  
            node.lchild = self.insert(node.lchild, val)  
            node.lchild.parent = node  
        elif val < node.data:  
            node.rchild = self.insert(node.rchild, val)  
            node.rchild.parent = node  
        return node  
  
    def insert_no_rec(self, val):   # 非递归插入,比递归快  
 		p = self.root               # 如果val是第一个数,则p = None  
 		if not p:                   # 空树,特殊处理  
 			self.root = BiTreeNode(val)  
            return  
 		while True:  
            if val < p.data:  
                if p.lchild:        # 如果左子树有东西  
 					p = p.lchild  
                else:               # 如果左孩子是空的  
 					p.lchild = BiTreeNode(val)  
                    p.lchild.parent = p  
                    return  
 			elif val > p.data:  
                if p.rchild:  
                    p = p.rchild  
                else:  
                    p.rchild = BiTreeNode(val)  
                    p.rchild.parent = p  
                    return  
 			else:  
                return  
  
 	# 三种遍历  
 	# 前序遍历  
 	def pre_order(self, root):  # root为根节点  
 		if root:  # 如果root不是空  
 			print(root.data, end=' ')  
            self.pre_order(root.lchild)  
            self.pre_order(root.rchild)  
  
    # 中序遍历  
 	def in_order(self, root):  
        if root:  
            self.in_order(root.lchild)  
            print(root.data, end=' ')  
            self.in_order(root.rchild)  
  
    # 后续遍历  
 	def post_order(self, root):  
        if root:  
            self.post_order(root.lchild)  
            self.post_order(root.rchild)  
            print(root.data, end=' ')  
  
tree = BST([4,6,7,9,2,1,3,5,8])  
tree.pre_order(tree.root)  
#  4 2 1 3 6 5 7 9 8  
print()  
tree.in_order(tree.root)        # 中序序列是排好序的!!!  
#  1 2 3 4 5 6 7 8 9 print()  
tree.post_order(tree.root)  
#  1 3 2 5 8 9 7 6 4  
print()
  • 二叉搜索树的中序是升序的

查询

def query(self, node, val): # 查询——递归版本  
 	if not node:  
        return None  
 	if val > node.data:  
        return self.query(node.rchild,val)  
    elif val < node.data:  
        return self.query(node.lchild,val)  
    else:  
        return node  
  
def query_no_rec(self, val): # 查询——非递归版本  
	p = self.root  
    while p:  
        if p.data < val:  
            p = p.rchild  
        elif val < p.data:  
            p = p.lchild  
        else:  
            return p  
    return None

删除

  1. 如果要删除的节点是叶子节点:直接删除
  2. 如果要删除的节点只有一个孩子:将此节点的孩子与父亲连接,然后删除该节点
  3. 如果要删除的节点有两个孩子·:将其右子树的最小节点(右子树往左走到头)删除,并替换该节点![[20211020143703163471182324350 1.png]]
def remove_node_1(self, node):      # 删除操作  
 	# 情况1:node是叶子节点  
 	if not node.parent:             # node的父亲为None——node为根节点时  
 		self.root = None  
 	if node == node.parent.lchild:  # node是一个左孩子  
 		node.parent.lchild = None  
 	else:  
        node.parent.rchild = None  
  
def remove_node_2_1(self, node):  
    # 情况2_1:node只有一个左孩子  
 	if not node.parent:             # node的父亲为None——node为根节点时  
 		self.root = node.lchild  
        node.lchild.parent = None  
 	elif node == node.parent.lchild:  
        node.parent.lchild = node.lchild  
        node.lchild.parent = node.parent  
    else:  
        node.parent.rchild = node.lchild  
        node.lchild = node.parent  
  
def remove_node_2_2(self, node):  
    # 情况2_2:node只有一个右孩子  
 	if not node.parent:             # node的父亲为None——node为根节点时  
 		self.root = node.rchild  
        node.rchild.parent = None  
 	elif node == node.parent.lchild:  
        node.parent.lchild = node.rchild  
        node.rchild.parent = node.parent  
    else:  
        node.parent.rchild = node.rchild  
        node.rchild = node.parent  
  
def delete(self, val):  
    if self.root:           # 不是空树  
 		node = self.query_no_rec(val)    # 先找到节点  
 		if not node:    # node = None 时进入——node不存在  
 			return False  
 		if not node.lchild and not node.rchild:  
        	self.remove_node_1(node)  
        elif not node.rchild:   # 只有一个左孩子  
 			self.remove_node_2_1(node)  
        elif not node.lchild:  
            self.remove_node_2_2(node)  
        else:                   # 两个孩子都有  
 			min_node = node.rchild  
            while min_node.lchild:      # min_node是右子树往左走到头  
 			min_node = min_node.lchild  
            node.data = min_node.data  
            # 删除min_node——判断min_node是否有右孩子,属于哪种删除情况  
 			if min_node.rchild:  
                self.remove_node_2_2(min_node)  
            else:  
                self.remove_node_1(min_node)

完整代码

class BiTreeNode():
    def __init__(self,data):
        self.data = data
        self.lchild = None
        self.rchild = None
        self.parent = None


class BST():
    def __init__(self, li=None):
        self.root = None
        if li:
            for val in li:
                self.insert_no_rec(val)

    def insert(self, node, val):    # 插入函数——递归版
        if not node:                # 如果node是空
            node = BiTreeNode(val)
        elif val < node.data:
            node.lchild = self.insert(node.lchild, val)
            node.lchild.parent = node
        elif val < node.data:
            node.rchild = self.insert(node.rchild, val)
            node.rchild.parent = node
        return node

    def insert_no_rec(self, val):   # 插入——非递归版,比递归快
        p = self.root               # 如果val是第一个数,则p = None
        if not p:                   # 空树,特殊处理
            self.root = BiTreeNode(val)
            return
        while True:
            if val < p.data:
                if p.lchild:        # 如果左子树有东西
                    p = p.lchild
                else:               # 如果左孩子是空的
                    p.lchild = BiTreeNode(val)
                    p.lchild.parent = p
                    return
            elif val > p.data:
                if p.rchild:
                    p = p.rchild
                else:
                    p.rchild = BiTreeNode(val)
                    p.rchild.parent = p
                    return
            else:                   # val = p.data  此处不支持
                return

    def query(self, node, val): # 查询——递归版本
        if not node:
            return None
        if val > node.data:
            return self.query(node.rchild,val)
        elif val < node.data:
            return self.query(node.lchild,val)
        else:
            return node

    def query_no_rec(self, val): # 查询——非递归版本
        p = self.root
        while p:
            if p.data < val:
                p = p.rchild
            elif val < p.data:
                p = p.lchild
            else:
                return p
        return None

    def remove_node_1(self, node):      # 删除操作
        # 情况1:node是叶子节点
        if not node.parent:             # node的父亲为None——node为根节点时
            self.root = None
        if node == node.parent.lchild:  # node是一个左孩子
            node.parent.lchild = None
        else:
            node.parent.rchild = None

    def remove_node_2_1(self, node):
        # 情况2_1:node只有一个左孩子
        if not node.parent:             # node的父亲为None——node为根节点时
            self.root = node.lchild
            node.lchild.parent = None
        elif node == node.parent.lchild:
            node.parent.lchild = node.lchild
            node.lchild.parent = node.parent
        else:
            node.parent.rchild = node.lchild
            node.lchild = node.parent

    def remove_node_2_2(self, node):
        # 情况2_2:node只有一个右孩子
        if not node.parent:             # node的父亲为None——node为根节点时
            self.root = node.rchild
            node.rchild.parent = None
        elif node == node.parent.lchild:
            node.parent.lchild = node.rchild
            node.rchild.parent = node.parent
        else:
            node.parent.rchild = node.rchild
            node.rchild = node.parent

    def delete(self, val):
        if self.root:           # 不是空树
            node = self.query_no_rec(val)    # 先找到节点
            if not node:    # node = None 时进入——node不存在
                return False
            if not node.lchild and not node.rchild:
                self.remove_node_1(node)
            elif not node.rchild:   # 只有一个左孩子
                self.remove_node_2_1(node)
            elif not node.lchild:
                self.remove_node_2_2(node)
            else:                   # 两个孩子都有
                min_node = node.rchild
                while min_node.lchild:      # min_node是右子树往左走到头
                    min_node = min_node.lchild
                node.data = min_node.data
                # 删除min_node——判断min_node是否有右孩子,属于哪种删除情况
                if min_node.rchild:
                    self.remove_node_2_2(min_node)
                else:
                    self.remove_node_1(min_node)

    #  三种遍历
    #  前序遍历
    def pre_order(self, root):  # root为根节点
        if root:  # 如果root不是空
            print(root.data, end=' ')
            self.pre_order(root.lchild)
            self.pre_order(root.rchild)

    #  中序遍历
    def in_order(self, root):
        if root:
            self.in_order(root.lchild)
            print(root.data, end=' ')
            self.in_order(root.rchild)

    #  后续遍历
    def post_order(self, root):
        if root:
            self.post_order(root.lchild)
            self.post_order(root.rchild)
            print(root.data, end=' ')


tree = BST([4,6,7,9,2,1,3,5,8])
tree.pre_order(tree.root)
#  4 2 1 3 6 5 7 9 8
print()
tree.in_order(tree.root)        # 中序序列是排好序的!!!
#  1 2 3 4 5 6 7 8 9
print()
tree.post_order(tree.root)
#  1 3 2 5 8 9 7 6 4
print()
print(tree.query_no_rec(4))
tree.delete(4)
tree.in_order(tree.root)
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值