CS61B - Lec 21 - Binary Search Tree

news/2024/11/28 0:57:13/

Lec 21 - BST

  • Binary Search Trees
  • 概念
  • 查找
  • 插入
  • 删除

从Lec20开始,就转战CS61B Spring 2019了,18后面全变成公开课了。
本章主要讲的是Binary Search Tree,是一种非常流行的数据结构,据说各大面试中都会出现。其中用到了超多的recursion思想。

Binary Search Trees

在这里插入图片描述
对于一个有序List,需要实现与查找有关的操作时,需要O(N)的复杂度,挺高的。怎么优化呢?
其实之前就想过这个问题。就像Deque结构一样,基本的思路是加入一些标记性的指针。
在这里插入图片描述
不断地在中间插入指针,并改变一些指针的方向,发现可以变为上图的树状结构,这就是一个基本二叉树。

二叉树的灵感来源还是二分查找算法。想到这我就有个问题:为什么会另外发明一个二叉树数据结构,而不是直接用二分法查找?

想了想,对于一组经常需要添加、删除操作的数据,需要查找 - 添加/删除 - 更新这三步。一个数组,查找一个值可以用二分法,复杂度跟二叉树一样,但是添加/删除复杂度就很高,拷过来拷过去的;一个链表,添加/删除很简单,但是查找就只能靠遍历。所以,综合以上两者的优势,才有了二叉树这种数据结构。

概念

在这里插入图片描述
何为树?总结一句话就是:两个节点间只存在一条路。
在这里插入图片描述
对于一个Binary Tree,每个节点只能有0~2个children,只能有1个parent。
在这里插入图片描述
每个节点左边的子树上所有节点的值都小于该节点,右边子树上所有的值都大于该节点。
在思考二叉树的结构时,想着二分法查找一个数组就可以了,将二维的变成一维。

查找

在这里插入图片描述
常规recursion,比较简单。复杂度为O(log(N)),与二分法一样。

插入

在这里插入图片描述
插入就十分巧妙了。如何插入呢?首先按照大小,在树中找插入的值,找到就不插了。没找到那肯定查到底了,到底了就按照树的规则,插左边或者右边。
然而实现的代码十分的recursive。第一个if,当插到底时返回一个新的节点。但是为什么只有返回没有指向?返回给谁?接下来一对if, else if解答了。如果找到了插入的父节点,会根据规则返回给T.left或者T.right;如果找到了和插入值相同的节点,则返回该节点,给上层的父节点的left或者right,没有任何改变。十分巧妙的recursion!
右边的代码是我们最容易想到的recursion的方式,一点都不优雅。

删除

最麻烦的是删除某个节点。插入肯定是插到底,删除就有三种可能:没有chiledren、有一个child和有两个children。
在这里插入图片描述
没有children的,直接删除。
在这里插入图片描述
有一个child的,将父节点指向自己的指针指向child。
在这里插入图片描述
有两个children的,需要拷贝左子树最右边的节点或者右子树最左边的节点,删除,然后放在删除节点相同的位置上。原因在于删除的节点是一个中间节点,删除之前需要找到一个新的中间节点替代,要不树就散了,中间节点需要大于左子树所有值,小于右子树所有值,所以自然想到取以上两个节点。


http://www.ppmy.cn/news/239802.html

相关文章

Lex正则表达式

字符 解释 . 匹配除换行符("/n")以外的任何单个字符 * 匹配前面表达式的零个或多个拷贝 [] 匹配括号中的任意的字符类 ^ 作为正则表达式的第一个字符匹配行的开头 $ 作为正则表达式的最后一个字符匹配行的结尾 {} …

lex yacc

http://www.linuxdiyf.com/viewarticle.php?id91568 作者:绚丽也尘埃 最近看《GCC-the-Complete-Reference-fly》才知道有lex和yacc这两个有趣的工具,并且fedora core 8也默认安装有这两个工具,所以趁此机会学习一下,以前学编译…

lex与yacc之lex符号表示例

在lex初探篇中,每次要定义新的单词,都需要重新编译,这是非常麻烦的。但是如果在词法分析程序运行时能够构建一个单词表,那么就可以在 添加新的单词时不用修改和重新编译lex程序。symboltable.l%{/** Word recognizer with a symbo…

linux下lex词法分析器,Lex词法分析器

LEX/FLEX词法分析器 CONTENTS: [TOC] 这篇文章的内容包括: lex语法格式 linux下flex的安装和使用 flex实例 flex源代码的编译和使用 Lex/Flex词法分析器 Lex是LEXical compiler的缩写,是Unix环境下非常著名的工具,主要功能是生成一个词法分析器(scanner)的C源码,描述规则采用…

flex RSL

RSL(Runtime shared libraries)即动态链接库,在程序运行时由FlashPlayer动态加载。静态链接库是SWC文件,通过编译器的library-path和include-libraries编译进应用程序。采用静态链接的应用程序SWF会产生比较大的文件以及更长的下载时间。使用RSL的应用程…

用Flex写的RIA应用网站开张了(http://www.2ren.cn)

偶做的flex网站终于可以拿出来献丑了!本来不想用csdn的blog发文章了的。高兴嘛就再发一篇! 前端用flex,后台使用java,并结合spring、hibernate等。 欢迎大家访问我的RIA网站http://www.2ren.cn

lex 正则表达式

规则: . 匹配任何单个字符,除\n. - 表示匹配范围,如:a-z,表示匹配a-z之间的任何字符 * 匹配前面表达式的零个或多个拷贝。 [] 匹配括号内的任意字符的字符类,第一个符号是"^",表示…

Lex+YACC( Flex+Bison)

源码 编译前期最常实验的工具,分别是用来做 lexical analyse 和 semantic analyse 的,这两个工具的使用基本不需要很深的编译知识,只需要掌握正则表达式的书写(lexical analyse阶段使用)和上下文无关文法(…