Skip to content

Commit 8b0db44

Browse files
committed
p3
1 parent 492b5b4 commit 8b0db44

File tree

1 file changed

+34
-37
lines changed

1 file changed

+34
-37
lines changed

223.md

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,55 @@
44

55
##heapq
66

7-
堆(heap),是一种数据结构。用维基百科中的说明
7+
堆(heap),是一种数据结构,引用维基百科中的说明
88

99
>堆(英语:heap),是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。
1010
11-
对于这个新的概念,读者不要感觉心慌意乱或者恐惧,因为它本质上不是新东西,而是在我们已经熟知的知识基础上的扩展
11+
对于这个新的概念,读者不要心慌意乱或者恐惧,因为它本质上不是新东西,而是在我们已经熟知的知识基础上的扩展出来的内容
1212

1313
堆的实现是通过构造二叉堆,也就是一种二叉树。
1414

1515
###基本知识
1616

17-
这是一颗在苏州很常见的香樟树,马路两边、公园里随处可见。
17+
这是一棵在苏州很常见的香樟树,马路两边、公园里随处可见,特别是在艳阳高照的时候,它的树荫能把路面遮盖
1818

1919
![](./2images/22301.jpg)
2020

21-
但是,在编程中,我们常说的树通常不是上图那样的,而是这样的
21+
但是,在编程中,我们常说的树是这样的
2222

2323
![](./2images/22302.jpg)
2424

25-
跟真实现实生活中看到的树反过来,也就是“根”在上面。为什么这样呢?我想主要是画着更方便吧。但是,我觉这棵树,是完全写实的作品。我本人做为一名隐姓埋名多年的抽象派画家,不喜欢这样的树,我画出来的是这样的:
25+
这是一棵“根”在上面树,也是编程中常说的树。为什么这样呢?我想主要是画着更方便吧。上面那棵树虽然根在上面了,还完全是写实的作品,本人做为一名隐姓埋名多年的抽象派画家,不喜欢这样的树,我画出来的是这样的:
2626

2727
![](./2images/22303.jpg)
2828

2929
这棵树有两根枝杈,可不要小看这两根枝杈哦,《道德经》上不是说“一生二,二生三,三生万物”。一就是下面那个干,二就是两个枝杈,每个枝杈还可以看做下一个一,然后再有两个枝杈,如此不断重复(这简直就是递归呀),就成为了一棵大树。
3030

31-
我的确很佩服我自己的后现代抽象派的作品。但是,我更喜欢把这棵树画成这样:
31+
这棵树画成这样就更符合编程的习惯了,可以向下不断延伸。
3232

3333
![](./2images/22304.jpg)
3434

35-
并且给它一个正规的名字:二叉树
35+
并且给它一个正规的名字:二叉树
3636

3737
![](./2images/22305.jpg)
3838

3939
这个也是二叉树,完全脱胎于我所画的后现代抽象主义作品。但是略有不同,这幅图在各个枝杈上显示的是数字。这种类型的“树”就编程语言中所说的二叉树,维基百科曰:
4040

4141
>在计算机科学中,二叉樹(英语:Binary tree)是每個節點最多有兩個子樹的樹結構。通常子樹被稱作「左子樹」(left subtree)和「右子樹」(right subtree)。二叉樹常被用於實現二叉查找樹和二叉堆。
4242
43-
在上图的二叉树中,最顶端的那个数字就相当于树根,也就称作“根”。每个数字所在位置成为一个节点,每个节点向下分散出两个“子节点”。就上图的二叉树,在最后一层,并不是所有节点都有两个子节点,这类二叉树又称为完全二叉树(Complete Binary Tree),也有的二叉树,所有的节点都有两个子节点,这类二叉树称作满二叉树(Full Binarry Tree),如下图:
43+
在上图的二叉树中,最顶端的那个数字就相当于树根,也就称作“根”。每个数字所在位置成为一个节点,每个节点向下分散出两个“子节点”。并不是所有节点都有两个子节点。这类二叉树又称为完全二叉树(Complete Binary Tree)。
44+
45+
也有的二叉树,所有的节点都有两个子节点,这类二叉树称作满二叉树(Full Binarry Tree),如下图:
4446

4547
![](./2images/22306.jpg)
4648

47-
下面讨论的对象是实现二叉堆就是通过二叉树实现的。其应该具有如下特点
49+
下面讨论的对象是通过二叉树实现的,其具有如下特点
4850

4951
- 节点的值大于等于(或者小于等于)任何子节点的值。
5052
- 节点左子树和右子树是一个二叉堆。如果父节点的值总大于等于任何一个子节点的值,其为最大堆;若父节点值总小于等于子节点值,为最小堆。上面图示中的完全二叉树,就表示一个最小堆。
5153

5254
堆的类型还有别的,如斐波那契堆等,但很少用。所以,通常就将二叉堆也说成堆。下面所说的堆,就是二叉堆。而二叉堆又是用二叉树实现的。
5355

54-
###堆的存储
55-
5656
堆用列表(有的语言中成为数组)来表示。如下图所示:
5757

5858
![](./2images/22307.jpg)
@@ -63,19 +63,19 @@
6363

6464
如果将上面的逻辑结构转换为存储结构,读者就能看出来了,不再是按照顺序排列的了。
6565

66-
关于堆的各种,如插入、删除、排序等,本节不会专门讲授编码方法,读者可以参与有关资料。但是,下面要介绍如何用python中的模块heapq来实现这些操作
66+
关于堆的各种,如插入、删除、排序等,本节不会专门讲授编码方法,读者可以参与有关资料。但是,下面要介绍如何用Python中的模块`heapq`来实现这些操作
6767

6868
###heapq模块
6969

70-
heapq中的heap是堆,q就是queue(队列)的缩写。此模块包括:
70+
`heapq`中的heap是堆,q就是queue(队列)的缩写。此模块包括:
7171

7272
>>> import heapq
7373
>>> heapq.__all__
7474
['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop']
7575

7676
依次查看这些函数的使用方法。
7777

78-
**heappush(heap, x)**将x压入对heap(这是一个列表)
78+
**heappush(heap, x)**将x压入堆heap
7979

8080
Help on built-in function heappush in module _heapq:
8181

@@ -94,7 +94,7 @@ heapq中的heap是堆,q就是queue(队列)的缩写。此模块包括:
9494
>>> heap
9595
[0, 2, 3, 9, 4, 8]
9696

97-
请读者注意我上面的操作,在向堆增加数值的时候,我并没有严格按照什么顺序,是随意的。但是,当我查看堆的数据时,显示给我的是一个有一定顺序的数据结构。这种顺序不是按照从小到大,而是按照前面所说的完全二叉树的方式排列显示的是存储结构,可以把它还原为逻辑结构,看看是不是一颗二叉树
97+
请读者注意上面的操作,在向堆增加数值的时候并没有严格按照什么顺序,是随意的。但是,当查看堆的数据时,显示的是一个有一定顺序的数据结构。这种顺序不是按照从小到大,而是按照前面所说的完全二叉树的方式排列显示的是存储结构,可以把它还原为逻辑结构,看看是不是一棵二叉树
9898

9999
![](./2images/22309.jpg)
100100

@@ -120,7 +120,7 @@ heapq中的heap是堆,q就是queue(队列)的缩写。此模块包括:
120120
>>> hl
121121
[0, 3, 1, 4, 9, 6, 2, 5, 8]
122122

123-
经过这样的操作,列表hl就变成了堆(注意观察堆的顺序,和列表不同),可以对hl(堆)使用heappop()或者heappush()等函数了。否则,不可。
123+
经过这样的操作,列表`hl`就变成了堆(堆的顺序和列表不同),可以对`hl`(堆)使用`heappop()`或者`heappush()`等函数了。否则,不可。
124124

125125
>>> heapq.heappop(hl)
126126
0
@@ -132,7 +132,7 @@ heapq中的heap是堆,q就是queue(队列)的缩写。此模块包括:
132132
>>> hl
133133
[2, 3, 5, 4, 9, 6, 8, 9]
134134

135-
不要认为堆里面只能放数字,之所以用数字,是因为对它的逻辑结构比较好理解。
135+
不要认为堆里面只能放数字,举例中之所以用数字,是因为对它的逻辑结构比较好理解。
136136

137137
>>> heapq.heappush(hl, "q")
138138
>>> hl
@@ -143,7 +143,7 @@ heapq中的heap是堆,q就是queue(队列)的缩写。此模块包括:
143143

144144
**heapreplace()**
145145

146-
是heappop()和heappush()的联合,也就是删除一个,同时加入一个。例如:
146+
`heappop()``heappush()`的联合,也就是删除一个,同时加入一个。例如:
147147

148148
>>> heap
149149
[2, 4, 3, 9, 8]
@@ -152,19 +152,17 @@ heapq中的heap是堆,q就是queue(队列)的缩写。此模块包括:
152152
>>> heap
153153
[3, 4, 3.14, 9, 8]
154154

155-
先简单罗列关于对的几个常用函数。那么堆在编程实践中的用途在哪方面呢?主要在排序上。一提到排序,读者肯定想到的是sorted()或者列表中的sort(),不错,这两个都是常用的函数,而且在一般情况下已经足够使用了。如果再使用堆排序,相对上述方法应该有优势。
156-
157-
堆排序的优势不仅更快,更重要的是有效地使用内存,当然,另外一个也不同忽视,就是简单易用。比如前面操作的,删除数列中最小的值,就是在排序基础上进行的操作。
155+
先简单罗列关于堆的几个常用函数。那么堆在编程实践中的用途有哪些呢?排序是一个应用方面。一提到排序,读者肯定想到的是`sorted()`或者列表中的`sort()`,这两个都是常用的函数,而且在一般情况下已经足够使用了。但如果使用堆排序,相对于其他排序,也有自己的优势。不同的排序方法有不同的特点,读者可以自行深入研究不同排序的优劣。
158156

159-
##deque模块
157+
##deque
160158

161-
有这样一个问题:一个列表,比如是`[1,2,3]`我打算在最右边增加一个数字
159+
有这样一个问题:一个列表,比如是`[1, 2, 3]`在最右边增加一个数字
162160

163-
这也太简单了,不就是用`append()`这个内建函数,追加一个吗?
161+
这也太简单了,不就是用`append()`追加一个吗?
164162

165-
这是简单,我要得寸进尺,能不能在最左边增加一个数字呢?
163+
这是简单。但,得寸进尺,能不能在最左边增加一个数字呢?
166164

167-
这个嘛,应该有办法。不过得想想了。读者在向下阅读的时候,能不能想出一个方法来?
165+
这个应该有办法,不过得想想了。读者在向下阅读之前候,能不能想出一个方法来?
168166

169167
>>> lst = [1, 2, 3]
170168
>>> lst.append(4)
@@ -175,20 +173,19 @@ heapq中的heap是堆,q就是queue(队列)的缩写。此模块包括:
175173
>>> nl
176174
[7, 1, 2, 3, 4]
177175

178-
你或许还有别的方法。但是,python为我们提供了一个更简单的模块,来解决这个问题。
176+
你或许还有别的方法。但是,Python为我们提供了一个更简单的模块,来解决这个问题。
179177

180178
>>> from collections import deque
181179

182-
这次用这种引用方法,因为collections模块中东西很多,我们只用到deque
180+
这次用这种引用方法是因为`collections`模块中东西很多,我们只用到`deque`
183181

184-
>>> lst
185-
[1, 2, 3, 4]
182+
>>> lst = [1, 2, 3, 4]
186183

187-
还是这个列表。试试分别从右边和左边增加数
184+
还是这个列表,试试分别从右边和左边增加数字。
188185

189186
>>> qlst = deque(lst)
190187

191-
这是必须的,将列表转化为deque。deque在汉语中有一个名字,叫做“双端队列”(double-ended queue)。
188+
这是必需的,将列表转化为deque。deque在汉语中有一个名字,叫做“双端队列”(double-ended queue)。
192189

193190
>>> qlst.append(5) #从右边增加
194191
>>> qlst
@@ -208,31 +205,31 @@ heapq中的heap是堆,q就是queue(队列)的缩写。此模块包括:
208205
>>> qlst
209206
deque([1, 2, 3, 4])
210207

211-
删除也分左右。下面这个,请读者仔细观察,更有点意思
208+
删除也分左右。下面这个,请读者仔细观察。
212209

213210
>>> qlst.rotate(3)
214211
>>> qlst
215212
deque([2, 3, 4, 1])
216213

217-
rotate()的功能是将[1, 2, 3, 4]的首位连起来,你就想象一个圆环,在上面有1,2,3,4几个数字。如果一开始正对着你的是1,依顺时针方向排列,就是从1开始的数列,如下图所示:
214+
rotate()的功能是将[1, 2, 3, 4]的首尾连起来,你就想象一个圆环,在上面有1, 2, 3, 4几个数字。如果一开始正对着你的是1,依顺时针方向排列,就是从1开始的数列,如下图所示:
218215

219216
![](./2images/22310.jpg)
220217

221218
经过`rotate()`,这个环就发生旋转了,如果是`rotate(3)`,表示每个数字按照顺时针方向前进三个位置,于是变成了:
222219

223220
![](./2images/22311.jpg)
224221

225-
请原谅我的后现代注意超级抽象派作图方式。从图中可以看出,数列变成了[2, 3, 4, 1]rotate()作用就好像在拨转这个圆环。
222+
请原谅我的后现代注意超级抽象派作图方式。从图中可以看出,数列变成了`[2, 3, 4, 1]``rotate()`作用就好像在拨转这个圆环。
226223

227224
>>> qlst
228225
deque([3, 4, 1, 2])
229226
>>> qlst.rotate(-1)
230227
>>> qlst
231228
deque([4, 1, 2, 3])
232229

233-
如果参数是复数,那么就逆时针转。
230+
如果参数是负数,那么就逆时针转。
234231

235-
在deque中,还有extend和extendleft方法。读者可自己调试。
232+
在deque中,还有`extend()``extendleft()`方法。读者可自己调试。
236233

237234
------
238235

0 commit comments

Comments
 (0)