西峡做网站网站建设有哪三部

bicheng/2026/1/17 14:45:18/文章来源:
西峡做网站,网站建设有哪三部,定制软件开发公司,做窗帘网站图片大全二叉查找树(BST) 二叉树的一种应用就是来实现堆#xff0c;今天我们再看看用二叉查找树(Binary Search Tree, BST)。 前面有章节说到了查找操作#xff0c;包括线性查找、二分查找、哈希查找等#xff0c;线性查找效率比较低#xff0c;二分又要求必须是有序的序列#x…二叉查找树(BST) 二叉树的一种应用就是来实现堆今天我们再看看用二叉查找树(Binary Search Tree, BST)。 前面有章节说到了查找操作包括线性查找、二分查找、哈希查找等线性查找效率比较低二分又要求必须是有序的序列 为了维持有序插入的代价比较高、哈希查找效率很高但是浪费空间。能不能有一种插入和查找都比较快的数据结构呢二叉查找树就是这样一种结构可以高效地插入和查询节点。 BST 定义 二叉查找树是这样一种二叉树结构它的每个节点包含一个 key 和它附带的数据对于每个内部节点 V 所有 key 小于 V 的都被存储在 V 的左子树所有 key 大于 V 的都存储在 V 的右子树 注意这个限制条件可别和堆搞混了。说白了就是对于每个内部节点左子树的 key 都比它小右子树都比它大。 如果中序遍历(二叉树遍历讲过了)这颗二叉树你会发现输出的顺序正好是有序的。 我们先来定义一下 BST 的节点结构 class BSTNode(object):def __init__(self, key, value, leftNone, rightNone):self.key, self.value, self.left, self.right key, value, left, right构造一个 BST 我们还像之前构造二叉树一样按照上图构造一个 BST 用来演示 class BST(object):def __init__(self, rootNone):self.root rootclassmethoddef build_from(cls, node_list):cls.size 0key_to_node_dict {}for node_dict in node_list:key node_dict[key]key_to_node_dict[key] BSTNode(key, valuekey) # 这里值暂时用 和 key一样的for node_dict in node_list:key node_dict[key]node key_to_node_dict[key]if node_dict[is_root]:root nodenode.left key_to_node_dict.get(node_dict[left])node.right key_to_node_dict.get(node_dict[right])cls.size 1return cls(root)NODE_LIST [{key: 60, left: 12, right: 90, is_root: True},{key: 12, left: 4, right: 41, is_root: False},{key: 4, left: 1, right: None, is_root: False},{key: 1, left: None, right: None, is_root: False},{key: 41, left: 29, right: None, is_root: False},{key: 29, left: 23, right: 37, is_root: False},{key: 23, left: None, right: None, is_root: False},{key: 37, left: None, right: None, is_root: False},{key: 90, left: 71, right: 100, is_root: False},{key: 71, left: None, right: 84, is_root: False},{key: 100, left: None, right: None, is_root: False},{key: 84, left: None, right: None, is_root: False}, ] bst BST.build_from(NODE_LIST)BST 操作 查找 如何查找一个指定的节点呢根据定义我们知道每个内部节点左子树的 key 都比它小右子树的 key 都比它大所以 对于带查找的节点 search_key从根节点开始如果 search_key 大于当前 key就去右子树查找否则去左子树查找。 一直到当前节点是 None 了说明没找到对应 key。 好撸代码 def _bst_search(self, subtree, key):if subtree is None: # 没找到return Noneelif key subtree.key:return self._bst_search(subtree.left, key)elif key subtree.key:return self._bst_search(subtree.right, key)else:return subtreedef get(self, key, defaultNone):node self._bst_search(self.root, key)if node is None:return defaultelse:return node.value获取最大和最小 key 的节点 其实还按照其定义最小值就一直向着左子树找最大值一直向右子树找递归查找就行。 def _bst_min_node(self, subtree):if subtree is None:return Noneelif subtree.left is None: # 找到左子树的头return subtreeelse:return self._bst_min_node(subtree.left)def bst_min(self):node self._bst_min_node(self.root)return node.value if node else None插入 插入节点的时候我们需要一直保持 BST 的性质每次插入一个节点我们都通过递归比较把它放到正确的位置。 你会发现新节点总是被作为叶子结点插入。请你思考这是为什么 def _bst_insert(self, subtree, key, value): 插入并且返回根节点:param subtree::param key::param value:if subtree is None: # 插入的节点一定是根节点包括 root 为空的情况subtree BSTNode(key, value)elif key subtree.key:subtree.left self._bst_insert(subtree.left, key, value)elif key subtree.key:subtree.right self._bst_insert(subtree.right, key, value)return subtreedef add(self, key, value):node self._bst_search(self.root, key)if node is not None: # 更新已经存在的 keynode.value valuereturn Falseelse:self.root self._bst_insert(self.root, key, value)self.size 1return True删除节点 删除操作相比上边的操作要麻烦很多首先需要定位一个节点删除节点后我们需要始终保持 BST 的性质。 删除一个节点涉及到三种情况 节点是叶节点节点有一个孩子节点有两个孩子 我们分别来看看三种情况下如何删除一个节点 删除叶节点 这是最简单的一种情况只需要把它的父亲指向它的指针设置为 None 就好。 删除只有一个孩子的节点 删除有一个孩子的节点时我们拿掉需要删除的节点之后把它的父亲指向它的孩子就行因为根据 BST 左子树都小于节点右子树都大于节点的特性删除它之后这个条件依旧满足。 删除有两个孩子的内部节点 假如我们想删除 12 这个节点改怎么做呢你的第一反应可能是按照下图的方式 但是这种方式可能会影响树的高度降低查找的效率。这里我们用另一种非常巧妙的方式。 还记得上边提到的吗如果你中序遍历 BST 并且输出每个节点的 key你会发现就是一个有序的数组。 [1 4 12 23 29 37 41 60 71 84 90 100]。这里我们定义两个概念逻辑前任(predecessor)和后继(successor)请看下图: 12 在中序遍历中的逻辑前任和后继分别是 4 和 23 节点。于是我们还有一种方法来删除 12 这个节点 找到待删除节点 N(12) 的后继节点 S(23)复制节点 S 到节点 N从 N 的右子树中删除节点 S并更新其删除后继节点后的右子树 说白了就是找到后继并且替换这里之所以能保证这种方法是正确的你会发现替换后依旧是保持了 BST 的性质。 有个问题是如何找到后继节点呢待删除节点的右子树的最小的节点不就是后继嘛上边我们已经实现了找到最小 key 的方法了。 我们开始编写代码实现和之前的操作类似我们还是通过辅助函数的形式来实现这个递归函数会比较复杂请你仔细理解: def _bst_remove(self, subtree, key):删除节点并返回根节点if subtree is None:return Noneelif key subtree.key:subtree.left self._bst_remove(subtree.left, key)return subtreeelif key subtree.key:subtree.right self._bst_remove(subtree.right, key)return subtreeelse: # 找到了需要删除的节点if subtree.left is None and subtree.right is None: # 叶节点返回 None 把其父亲指向它的指针置为 Nonereturn Noneelif subtree.left is None or subtree.right is None: # 只有一个孩子if subtree.left is not None:return subtree.left # 返回它的孩子并让它的父亲指过去else:return subtree.rightelse: # 俩孩子寻找后继节点替换并从待删节点的右子树中删除后继节点successor_node self._bst_min_node(subtree.right)subtree.key, subtree.value successor_node.key, successor_node.valuesubtree.right self._bst_remove(subtree.right, successor_node.key)return subtreedef remove(self, key):assert key in selfself.size - 1return self._bst_remove(self.root, key)完整代码你可以在本章的 bst.py 找到。 另外推荐一个可以在线演示过程的网址大家可以手动执行下看看效果 https://www.cs.usfca.edu/~galles/visualization/BST.html 时间复杂度分析 上边介绍的操作时间复杂度和二叉树的形状有关。平均来说时间复杂度是和树的高度成正比的树的高度 h 是 log(n) 但是最坏情况下以上操作的时间复杂度都是 O(n)。为了改善 BST 有很多变种感兴趣请参考延伸阅读中的内容。 源码 # -*- coding: utf-8 -*-class BSTNode(object):def __init__(self, key, value, leftNone, rightNone):self.key, self.value, self.left, self.right key, value, left, rightclass BST(object):def __init__(self, rootNone):self.root rootclassmethoddef build_from(cls, node_list):cls.size 0key_to_node_dict {}for node_dict in node_list:key node_dict[key]key_to_node_dict[key] BSTNode(key, valuekey) # 这里值暂时用 和 key一样的for node_dict in node_list:key node_dict[key]node key_to_node_dict[key]if node_dict[is_root]:root nodenode.left key_to_node_dict.get(node_dict[left])node.right key_to_node_dict.get(node_dict[right])cls.size 1return cls(root)def _bst_search(self, subtree, key):if subtree is None: # 没找到return Noneelif key subtree.key:return self._bst_search(subtree.left, key)elif key subtree.key:return self._bst_search(subtree.right, key)else:return subtreedef __contains__(self, key):实现 in 操作符return self._bst_search(self.root, key) is not Nonedef get(self, key, defaultNone):node self._bst_search(self.root, key)if node is None:return defaultelse:return node.valuedef _bst_min_node(self, subtree):if subtree is None:return Noneelif subtree.left is None: # 找到左子树的头return subtreeelse:return self._bst_min_node(subtree.left)def bst_min(self):node self._bst_min_node(self.root)return node.value if node else Nonedef _bst_insert(self, subtree, key, value): 插入并且返回根节点:param subtree::param key::param value:if subtree is None: # 插入的节点一定是根节点包括 root 为空的情况subtree BSTNode(key, value)elif key subtree.key:subtree.left self._bst_insert(subtree.left, key, value)elif key subtree.key:subtree.right self._bst_insert(subtree.right, key, value)return subtreedef add(self, key, value):node self._bst_search(self.root, key)if node is not None: # 更新已经存在的 keynode.value valuereturn Falseelse:self.root self._bst_insert(self.root, key, value)self.size 1return Truedef _bst_remove(self, subtree, key):删除节点并返回根节点if subtree is None:return Noneelif key subtree.key:subtree.left self._bst_remove(subtree.left, key)return subtreeelif key subtree.key:subtree.right self._bst_remove(subtree.right, key)return subtreeelse: # 找到了需要删除的节点if subtree.left is None and subtree.right is None: # 叶节点返回 None 把其父亲指向它的指针置为 Nonereturn Noneelif subtree.left is None or subtree.right is None: # 只有一个孩子if subtree.left is not None:return subtree.left # 返回它的孩子并让它的父亲指过去else:return subtree.rightelse: # 俩孩子寻找后继节点替换并删除其右子树的后继节点同时更新其右子树successor_node self._bst_min_node(subtree.right)subtree.key, subtree.value successor_node.key, successor_node.valuesubtree.right self._bst_remove(subtree.right, successor_node.key)return subtreedef remove(self, key):assert key in selfself.size - 1return self._bst_remove(self.root, key)NODE_LIST [{key: 60, left: 12, right: 90, is_root: True},{key: 12, left: 4, right: 41, is_root: False},{key: 4, left: 1, right: None, is_root: False},{key: 1, left: None, right: None, is_root: False},{key: 41, left: 29, right: None, is_root: False},{key: 29, left: 23, right: 37, is_root: False},{key: 23, left: None, right: None, is_root: False},{key: 37, left: None, right: None, is_root: False},{key: 90, left: 71, right: 100, is_root: False},{key: 71, left: None, right: 84, is_root: False},{key: 100, left: None, right: None, is_root: False},{key: 84, left: None, right: None, is_root: False}, ]def test_bst_tree():bst BST.build_from(NODE_LIST)for node_dict in NODE_LIST:key node_dict[key]assert bst.get(key) keyassert bst.size len(NODE_LIST)assert bst.get(-1) is None # 单例的 None 我们用 is 来比较assert bst.bst_min() 1bst.add(0, 0)assert bst.bst_min() 0bst.remove(12)assert bst.get(12) is Nonebst.remove(1)assert bst.get(1) is Nonebst.remove(29)assert bst.get(29) is None练习题 请你实现查找 BST 最大值的函数 延伸阅读 《Data Structures and Algorithms in Python》14 章树的概念和算法还有很多我们这里介绍最基本的帮你打个基础了解红黑树。普通二叉查找树有个很大的问题就是难以保证树的平衡极端情况下某些节点可能会非常深导致查找复杂度大幅退化。而平衡二叉树就是为了解决这个问题。请搜索对应资料了解下。了解 mysql 索引使用的 B-Tree 结构(多路平衡查找树)这个是后端面试数据库的常考点。想想为什么当元素非常多的时候二叉树的深度会很深导致多次磁盘查找。从B树、B树、B*树谈到R 树 Leetcode 验证是否是合法二叉搜索树 [validate-binary-search-tree](https://leetcode.com/problems/validate-binary-search-tree/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/89540.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

东莞网站建设(乐云践新)应该选用哪种口罩

目录 声明 前言 正文 (1)下载git压缩包 (2)git压缩包解压 (3)解压完成后需要进行源码的编译操作 a.首先进去到解压后的文件目录中: b.执行: 编译的过程中可能遇到的问题&am…

福州市交通建设集团有限公司网站江苏seo和网络推广

工厂模式 工厂函数通常是指一个函数,它用来创建和返回其他函数或对象的实例。 人话: 当new Class 或 Function 时,根据传入的参数,而返回不同的值,这就是工厂模式。 (所以可以说,这是我们开…

二级域名网站怎么建设无法与wordpress建立连接

阿里云2核4G服务器多少钱一年?2核4G配置1个月多少钱?2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年。可以在阿里云CLUB中心查看 aliyun.club 当前最新2核4G服务器精准报价、优惠券和活动信息。 阿里云官方2…

局域网网站建设步骤如何做国外外贸网站

ERR_SSL_KEY_USAGE_INCOMPATIBLE报错原因 ERR_SSL_KEY_USAGE_INCOMPATIBLE 错误通常发生在使用 SSL/TLS 连接时,指的是客户端和服务器之间进行安全通信尝试失败,原因是证书中的密钥用途(Key Usage)或扩展密钥用途(Extended Key Usage, EKU)与正在尝试的操作不兼容。这意味…

怎样运营推广网站屏蔽蜘蛛抓取 对网站有什么影响

阿里云8核32G服务器g8y租用优惠价格243.30元/月,配置云服务器g8y(ecs.g8y.2xlarge)8核32G、按固定带宽1M-5M、可选ESSD云盘40G起,优惠价格243.30元一个月, 阿里云服务器优惠活动 aliyunfuwuqi.com/go/aliyun 阿里云服务…

网络推广是什么职业合肥网络seo推广服务

C#语言中用于结构化程序设计的三种基本结构是:顺序结构、选择结构、循环结构。本文详细整理了以上三种结构的用法,案例。 文章目录 4.1 顺序结构4.1.1 赋值语句4.1.2 输入语句4.1.3 输出语句4.1.4 复合语句4.1.5 应用实例4.2 选择结构4.2.1 if条件语句4.2.2 switch结构4.3 循…

上海企业建站公司哪家好钦州做网站

鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 鸿蒙开发-UI-图形-图片 鸿蒙开发-UI-图形-绘制几何图形 鸿蒙开发-UI-图形-绘制自定义图形 鸿蒙开发-UI-图形-页面内动画 文章目录 前言 一、基本概…

手机网站设计建设服务没内涵网站源码

众所周知,TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入,包括主流标准协议国标GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。在视频流的处理与分发上,视频监控…

学校网站如何建设农业银行官网

关于 Function Module 这个技术点,在面试过程中一般会考察以下几个问题: 1 函数处理类型的更新模式 一般会问到异步和事务(逻辑单元 LUW),异步函数的调试方式、SM13监控更新函数的执行过程(V1 与 V2 模式…

站酷网官网入口蜂蜜网络营销推广方案

让数据中台真正落地是实现数字化转型的重中之重。企业做好数据治理、体系建设及人才配备等前期工作后,接下来要做的是数据中台实施落地的关键。 企业首先要掌握数据中台建设的三大核心要素:选对数据建设方式、厘清建设思路、避开数据中台建设误区&#…

中山做网站的公司哈尔滨高端模板建站

1. JavaScript 特殊字符 2. 正反斜杠互相替换 a/b/c.replace(/\//g,\\) // "a\b\c" $0.value.replace(/\\/g,\/) // a/b/c 获取到 而不提取出 某个值后进行直接处理 \ 有转义功能,所以一旦解析必然转义,通常是直接获取到数据源…

临沂外贸网站制作网站的发展前景

借鉴地址uniapp极光做消息推送_uniapp 极光 配置 ios 自定义消息-CSDN博客

景德镇市建设局建设信用网站网站建设实训实训心得

大家好我是二狗。 ChatGPT变懒这件事又有了最新解释了。 这两天,推特用户Dylan Patel发文表示: 你想知道为什么 ChatGPT 和 6 个月前相比会如此糟糕吗? 那是因为ChatGPT系统Prompt是竟然包含1700 tokens,看看这个prompt里面有多…

摄影网站建设内容安徽网站建站系统平台

带你一起走进网工的世界!G-LAB网工入门免费公开课即将开讲!无论是想学习基础网络组网还是网络互通技术实施,这个公开课都是你不容错过的! 公开课课程为期两天,11月7日&11月8日晚20:00 分享主题…

广州做网站的公网页图片另存为的时候保存不了jpg

选择 (512 \times 512)、(1024 \times 1024) 等像素大小的原因与计算机科学中的一些基本概念有关: 二进制和内存对齐:计算机系统基于二进制运作,因此处理二的幂次方的数值(如 (2^9 512), (2^{10} 1024) 等)时更为高效…

大数据对网站建设教育的影响河南建站网站

信息打点-CDN绕过 文章目录 信息打点-CDN绕过本节思维导图相关链接&工具站&项目工具前置知识:CDN配置:配置1:加速域名-需要启用加速的域名配置2:加速区域-需要启用加速的地区配置3:加速类型-需要启用加速的资源…

网站建设制作设计推广优化陕西省住房建设厅官方网站

题目: * 题目: * 回文串,是一种特殊的字符串,它从左往右和从右往左读是一样的。 * 现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变为完美的回文回文串。 * 例如:mamad * 第…

无锡网站排名公司t恤定制网站

网址:融资总额近3亿美元、药明康德押注,这家抗衰老明星公司有何过人之处-36氪 想要抓取文章内容,但是找不到啊,可能是文字格式的问题,也可能文章内容进行了加密。 在元素中查看,window.initialState返回的就…

网站 免备案网站建设价格方案

介绍 基于Stage模型,对Ability的创建和使用进行讲解。首先在课程中我们将带领大家使用DevEco Studio创建一个Stage模型Ability,并使用UIAbilityContext启动另一个Ability,然后借助Want,在Ability之间传递参数,最后我们…

网站404页面下载凡客诚品购物官网

random_score的使用 在Elasticsearch中&#xff0c;random_score查询可以用来随机排序搜索结果&#xff0c;这对于实现诸如轮播、随机推荐等功能非常有用。 random_score的语法 GET /<索引名>/_search {"query": {"function_score": {"query…