Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
lmpythw-zh
提交
48bcea75
L
lmpythw-zh
项目概览
OpenDocCN
/
lmpythw-zh
8 个月 前同步成功
通知
0
Star
18
Fork
5
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
lmpythw-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
48bcea75
编写于
8月 10, 2017
作者:
W
wizardforcel
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ex23
上级
a61ac21a
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
101 addition
and
0 deletion
+101
-0
ex23.md
ex23.md
+101
-0
未找到文件。
ex23.md
0 → 100644
浏览文件 @
48bcea75
# 练习 23:三叉搜索树
> 原文:[Exercise 23: Ternary Search Trees](https://learncodethehardway.org/more-python-book/ex23.html)
> 译者:[飞龙](https://github.com/wizardforcel)
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
> 自豪地采用[谷歌翻译](https://translate.google.cn/)
我们将研究的最终数据结构称为三叉搜索树(TSTree),它可以在一组字符串中的快速查找字符串。它类似于
`BSTree`
,但是它有三个子节点,而不是两个,每个子节点只是一个字符而不是整个字符串。在
`BSTree`
中,左子节点和右子节点是树的“小于”和“大于”的分支。在
`TSTree`
中,左子节点,中子节点和右子节点是“小于”,“等于”和“大于”的分支。这可以让你选取一个字符串,将其分解成字符,然后遍历
`TSTree`
,每次一个字符,直到找到它或者你到达了末尾。
通过将你要搜索的一组键拆成单个字符的节点,
`TSTree`
高效地使用空间换取时间。每一个这些节点将占用比
`BSTree`
更多的空间,但这允许你仅仅通过比较键中的字符来搜索键。使用
`BSTree`
,您必须比较每个节点的键和被搜索键中的大多数字符。使用
`TSTree`
,您只需要比较被搜索键的每个字母,当您到达末尾,就完成了。
`TSTree`
的另一件不错的事情是,它知道一个键何时不存在于集合中。想象一下,您的键的长度为 10 个字符,您需要在一组其他的键中找到它,但是如果键不存在,则需要快速停止。使用
`TSTree`
,您可以在一到两个字符的地方停止,到达树的末尾,并且知道这个键不存在。您最多只能比较键中的 10 个字符来发现它,字符比较比
`BSTree`
少得多。
## 挑战练习
这个练习中,你打算完成另一个“代码大师复制”的一部分,之后独立完成
`TSTree `
。你所需的代码是:
```
py
class
TSTreeNode
(
object
):
def
__init__
(
self
,
key
,
value
,
low
,
eq
,
high
):
self
.
key
=
key
self
.
low
=
low
self
.
eq
=
eq
self
.
high
=
high
self
.
value
=
value
class
TSTree
(
object
):
def
__init__
(
self
):
self
.
root
=
None
def
_get
(
self
,
node
,
keys
):
key
=
keys
[
0
]
if
key
<
node
.
key
:
return
self
.
_get
(
node
.
low
,
keys
)
elif
key
==
node
.
key
:
if
len
(
keys
)
>
1
:
return
self
.
_get
(
node
.
eq
,
keys
[
1
:])
else
:
return
node
.
value
else
:
return
self
.
_get
(
node
.
high
,
keys
)
def
get
(
self
,
key
):
keys
=
[
x
for
x
in
key
]
return
self
.
_get
(
self
.
root
,
keys
)
def
_set
(
self
,
node
,
keys
,
value
):
next_key
=
keys
[
0
]
if
not
node
:
# what happens if you add the value here?
node
=
TSTreeNode
(
next_key
,
None
,
None
,
None
,
None
)
if
next_key
<
node
.
key
:
node
.
low
=
self
.
_set
(
node
.
low
,
keys
,
value
)
elif
next_key
==
node
.
key
:
if
len
(
keys
)
>
1
:
node
.
eq
=
self
.
_set
(
node
.
eq
,
keys
[
1
:],
value
)
else
:
# what happens if you DO NOT add the value here?
node
.
value
=
value
else
:
node
.
high
=
self
.
_set
(
node
.
high
,
keys
,
value
)
return
node
def
set
(
self
,
key
,
value
):
keys
=
[
x
for
x
in
key
]
self
.
root
=
self
.
_set
(
self
.
root
,
keys
,
value
)
```
您需要使用您学到的“代码大师复制”方法学习。要特别注意如何处理
`node.eq`
路径以及如何设置
`node.value`
。一旦你了解了
`get`
和
`set`
的工作方式,你将实现剩下的函数和所有的测试。要实现的函数有:
> `find_shortest`
> 给定一个关键字`K`,找到以`K`开头的最短键/值对。这意味着如果您的`set`中有`apple`和`application` ,那么调用`find_shortest("appl")`将返回关联`apple`的值。
> `find_longest`
> 给定一个关键字`K`,找到以`K`开头的最长键/值对。这意味着如果您的`set`中有`apple`和`application` ,那么调用`find_shortest("appl")`将返回关联`application`的值。
> `find_all`
> 给定一个关键字`K`,找到以`K`开头的所有键/值对。我会先实现它,然后基于它实现`find_shortest`和`find_longest`。
> `find_part`
> 给定一个关键字`K`,找到最短的键,它拥有`K`的开头的一部分。研究如何以及在哪里设置`node.value`来使其生效。
## 研究性学习
+
查看原始代码的注释,看看在
`_set`
过程中,在哪里放置
`value`
。修改它会修改
`get`
的含义吗?为什么?
+
确保你使用随机数据来测试,并测量一些性能。
+
您也可以在
`TSTree`
中进行模糊匹配。我认为这是一个附加题,所以尝试实现它们,看看你想出了什么。部分匹配是,
`'a.p.e'`
匹配
`"apple"`
、
`"anpxe"`
和
`"ajpqe"`
。
+
如何搜索字符串的结尾?提示:不要过度考虑它。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录