Skip to content

Commit c9890d9

Browse files
committed
algorithm
1 parent c0b9846 commit c9890d9

10 files changed

Lines changed: 180 additions & 10 deletions

README.md

Lines changed: 180 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4751,32 +4751,202 @@ if __name__ == '__main__':
47514751

47524752
动画还是用matplotlib做出来的,这就更完美了,一边学完美的算法,一边还能提升Python熟练度,一边还能学到使用matplotlib制作动画。
47534753

4754-
#### 2 快速排序动画展示
4755-
4756-
一个随机序列,使用快速排序算法,由小到大排序的过程:
4754+
快速排序动画展示
47574755

47584756
![img](https://mmbiz.qpic.cn/mmbiz_gif/FQd8gQcyN256Z0UkwIAVsP1pMsIUYTaHibX8xewf1Sgyvfh3VAR7IkWdwQtbNsniaiaXHzjG0Tcefl3Dv4OibhbGeg/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1)
47594757

4760-
#### 3 归并排序动画展示
4758+
归并排序动画展示
47614759

4762-
一个随机序列,使用归并排序算法,由小到大排序的过程:
47634760

4761+
![img](https://mmbiz.qpic.cn/mmbiz_gif/FQd8gQcyN256Z0UkwIAVsP1pMsIUYTaHpD5ibgM0kmia30zVM163X3RF9HnX2icibkJNghcibfjicxbibIJLLYprxqOqw/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1)
47644762

4763+
堆排序动画展示
47654764

4766-
![img](https://mmbiz.qpic.cn/mmbiz_gif/FQd8gQcyN256Z0UkwIAVsP1pMsIUYTaHpD5ibgM0kmia30zVM163X3RF9HnX2icibkJNghcibfjicxbibIJLLYprxqOqw/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1)
4765+
![img](https://mmbiz.qpic.cn/mmbiz_gif/FQd8gQcyN256Z0UkwIAVsP1pMsIUYTaH7HenTzoiaicwFrMTCiav18yLEhPmXombelTAlAMeBhzic4icnsuoQg1D7sw/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1)
47674766

4768-
#### 4 堆排序动画展示
4769-
一个随机序列,使用堆排序算法,由小到大排序的过程:
4767+
这些算法动画使用Matplotlib制作,接下来逐个补充。
47704768

4769+
#### 2 排序算法的动画展示
47714770

4771+
学会第一部分如何制作动画后,可将此技术应用于排序算法调整过程的动态展示上。
47724772

4773+
首先生成测试使用的数据,待排序的数据个数至多`20个`,待排序序列为`random_wait_sort`,为每个值赋一个颜色值,这个由`random_rgb`负责:
47734774

4775+
```python
4776+
data_count = 20 # here, max value of data_count is 20
47744777

4775-
![img](https://mmbiz.qpic.cn/mmbiz_gif/FQd8gQcyN256Z0UkwIAVsP1pMsIUYTaH7HenTzoiaicwFrMTCiav18yLEhPmXombelTAlAMeBhzic4icnsuoQg1D7sw/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1)
4778+
random_wait_sort = [12, 34, 32, 24, 28, 39, 5,
4779+
22, 11, 25, 33, 32, 1, 25, 3, 8, 7, 1, 34, 7]
47764780

4777-
这些算法动画使用Matplotlib制作,接下来逐个补充。
4781+
random_rgb = [(0.5, 0.811565104942967, 0.11211028937187217),
4782+
(0.5, 0.5201323831224014, 0.6660999602342474),
4783+
(0.5, 0.575976663060455, 0.17788242607567772),
4784+
(0.5, 0.6880174797416493, 0.43581701833249353),
4785+
(0.5, 0.4443131322001743, 0.6993600264279745),
4786+
(0.5, 0.5538835821863523, 0.889276053938713),
4787+
(0.5, 0.4851681185146841, 0.7977608586163772),
4788+
(0.5, 0.3886717808488436, 0.09319137949618972),
4789+
(0.5, 0.8952456581687489, 0.8282376936934484),
4790+
(0.5, 0.16360202854998007, 0.4538892160157194),
4791+
(0.5, 0.23233400128809478, 0.8544141586189615),
4792+
(0.5, 0.5224648797546528, 0.8194014475829123),
4793+
(0.5, 0.49396099968405016, 0.47441724394796825),
4794+
(0.5, 0.12078104526714728, 0.7715022079860492),
4795+
(0.5, 0.19428498518228154, 0.08174917157481443),
4796+
(0.5, 0.6058698403873457, 0.6085936584142663),
4797+
(0.5, 0.7801178568951216, 0.6414767240649862),
4798+
(0.5, 0.4768865661174162, 0.3889866229610085),
4799+
(0.5, 0.4301945092238082, 0.961688141676841),
4800+
(0.5, 0.40496648895289855, 0.24234095882836093)]
4801+
4802+
4803+
```
4804+
4805+
再封装一个简单的数据对象`Data`
4806+
```python
4807+
class Data:
4808+
def __init__(self, value, rgb):
4809+
self.value = value
4810+
self.color = rgb
4811+
4812+
# 造数据
4813+
@classmethod
4814+
def create(cls):
4815+
return [Data(val, rgb) for val, rgb in zip(random_wait_sort[:data_count],
4816+
random_rgb[:data_count])]
4817+
```
4818+
4819+
4820+
#### 3 先拿冒泡实验
4821+
4822+
一旦发生调整,我们立即保存到帧列表`frames`中,注意此处需要`deepcopy`:
4823+
```python
4824+
# 冒泡排序
4825+
def bubble_sort(waiting_sort_data):
4826+
frames = [waiting_sort_data]
4827+
ds = copy.deepcopy(waiting_sort_data)
4828+
for i in range(data_count-1):
4829+
for j in range(data_count-i-1):
4830+
if ds[j].value > ds[j+1].value:
4831+
ds[j], ds[j+1] = ds[j+1], ds[j]
4832+
frames.append(copy.deepcopy(ds))
4833+
frames.append(ds)
4834+
return frames
4835+
```
4836+
4837+
实验结果图:
4838+
4839+
![image-20200104232411426](./img/image-20200104232411426.png)
4840+
4841+
完整动画演示:
4842+
4843+
![img](./img/bubble_sort.gif)
4844+
4845+
#### 4 快速排序
4846+
先上代码,比较经典,值得回味:
4847+
```python
4848+
def quick_sort(data_set):
4849+
frames = [data_set]
4850+
ds = copy.deepcopy(data_set)
4851+
4852+
def qsort(head, tail):
4853+
if tail - head > 1:
4854+
i = head
4855+
j = tail - 1
4856+
pivot = ds[j].value
4857+
while i < j:
4858+
if ds[i].value > pivot or ds[j].value < pivot:
4859+
ds[i], ds[j] = ds[j], ds[i]
4860+
frames.append(copy.deepcopy(ds))
4861+
if ds[i].value == pivot:
4862+
j -= 1
4863+
else:
4864+
i += 1
4865+
qsort(head, i)
4866+
qsort(i+1, tail)
4867+
4868+
qsort(0, data_count)
4869+
frames.append(ds)
4870+
return frames
4871+
```
4872+
快速排序算法对输入为随机的序列优势往往较为明显,同样的输入数据,它只需要`24`帧调整就能完成排序:
4873+
4874+
![image-20200104232337713](./img/image-20200104232337713.png)
4875+
4876+
#### 5 选择排序
4877+
选择排序和堆排序都是选择思维,但是性能却不如堆排序:
4878+
```python
4879+
def selection_sort(data_set):
4880+
frames = [data_set]
4881+
ds = copy.deepcopy(data_set)
4882+
for i in range(0, data_count-1):
4883+
for j in range(i+1, data_count):
4884+
if ds[j].value < ds[i].value:
4885+
ds[i], ds[j] = ds[j], ds[i]
4886+
frames.append(copy.deepcopy(ds))
4887+
4888+
frames.append(ds)
4889+
return frames
4890+
```
4891+
同样的输入数据,它完成排序需要`108`帧:
4892+
4893+
![image-20200104232448531](./img/image-20200104232448531.png)
4894+
4895+
4896+
4897+
动画展示如下,每轮会从未排序的列表中,挑出一个最小值,放到已排序序列后面。
4898+
4899+
![img](./img/select_sort.gif)
4900+
4901+
#### 6 堆排序
4902+
堆排序大大改进了选择排序,逻辑上使用二叉树,先建立一个大根堆,然后根节点与未排序序列的最后一个元素交换,重新对未排序序列建堆。
4903+
4904+
完整代码如下:
4905+
4906+
```python
4907+
def heap_sort(data_set):
4908+
frames = [data_set]
4909+
ds = copy.deepcopy(data_set)
4910+
4911+
def heap_adjust(head, tail):
4912+
i = head * 2 + 1 # head的左孩子
4913+
while i < tail:
4914+
if i + 1 < tail and ds[i].value < ds[i+1].value: # 选择一个更大的孩子
4915+
i += 1
4916+
if ds[i].value <= ds[head].value:
4917+
break
4918+
ds[head], ds[i] = ds[i], ds[head]
4919+
frames.append(copy.deepcopy(ds))
4920+
head = i
4921+
i = i * 2 + 1
4922+
4923+
# 建立一个最大堆,从最后一个父节点开始调整
4924+
for i in range(data_count//2-1, -1, -1):
4925+
heap_adjust(i, data_count)
4926+
for i in range(data_count-1, 0, -1):
4927+
ds[i], ds[0] = ds[0], ds[i] # 把最大值放在位置i处
4928+
heap_adjust(0, i) # 从0~i-1进行堆调整
4929+
frames.append(ds)
4930+
return frames
4931+
```
4932+
堆排序的性能也比较优秀,完成排序需要51次调整。
4933+
4934+
![image-20200104232824967](./img/image-20200104232824967.png)
4935+
4936+
4937+
#### 7 综合
4938+
依次调用以上常见的4种排序算法,分别保存所有帧和html文件。
4939+
4940+
```python
4941+
waiting_sort_data = Data.create()
4942+
for sort_method in [bubble_sort, quick_sort, selection_sort, heap_sort]:
4943+
frames = sort_method(waiting_sort_data)
4944+
draw_chart(frames, file_name='%s.html' % (sort_method.__name__,))
4945+
```
47784946

4947+
获取以上完整代码、所有数据文件、结果文件:[完整源码下载](./data/sort.zip)
47794948

4949+
---
47804950

47814951
### 十一、 Python机器学习
47824952

data/sort.zip

426 KB
Binary file not shown.

img/bubble_animate.gif

298 KB
Loading

img/bubble_sort.gif

155 KB
Loading

img/image-20200104232337713.png

143 KB
Loading

img/image-20200104232355978.png

5.55 KB
Loading

img/image-20200104232411426.png

316 KB
Loading

img/image-20200104232448531.png

477 KB
Loading

img/image-20200104232824967.png

142 KB
Loading

img/select_sort.gif

319 KB
Loading

0 commit comments

Comments
 (0)