├── .idea
├── DataStructur.iml
├── inspectionProfiles
│ └── Project_Default.xml
├── misc.xml
├── modules.xml
└── workspace.xml
├── AVL
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ ├── avl_map.cpython-36.pyc
│ └── avl_tree.cpython-36.pyc
├── avl_map.py
├── avl_set.py
├── avl_tree.py
└── pride-and-prejudice.txt
├── Array
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── array.cpython-36.pyc
└── array.py
├── Binary_Search_Tree
├── BST.py
├── __init__.py
└── __pycache__
│ ├── BST.cpython-36.pyc
│ └── __init__.cpython-36.pyc
├── Hash_Table
├── __init__.py
├── hash_table.py
└── pride-and-prejudice.txt
├── Linked_List
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── linked_list.cpython-36.pyc
└── linked_list.py
├── Map
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── map_base.cpython-36.pyc
├── bst_map.py
├── linked_list_map.py
├── map_base.py
└── shakespeare.txt
├── MaxHeap
├── __init__.py
└── max_heap.py
├── README.md
├── SegmentTree
├── __init__.py
└── segment_tree.py
├── Set
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── set_base.cpython-36.pyc
├── bst_set.py
├── linked_list_set.py
├── set_base.py
└── shakespeare.txt
├── Stack
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── stack_base.cpython-36.pyc
├── array_stack.py
├── linked_list_stack.py
└── stack_base.py
├── Trie
├── __init__.py
└── trie.py
├── UnionFind
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── unionfind_base.cpython-36.pyc
├── unionfind.py
└── unionfind_base.py
└── _Queue
├── __init__.py
├── __pycache__
├── __init__.cpython-36.pyc
├── array_queue.cpython-36.pyc
└── queue_base.cpython-36.pyc
├── array_queue.py
├── linked_list_queue.py
├── loop_queue.py
├── priority_queue.py
└── queue_base.py
/.idea/DataStructur.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
87 |
88 |
89 |
90 |
91 | true
92 | DEFINITION_ORDER
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 | 1552765229823
317 |
318 |
319 | 1552765229823
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 | file://$PROJECT_DIR$/Binary_Search_Tree/BST.py
361 | 142
362 |
363 |
364 |
365 | file://$PROJECT_DIR$/Map/bst_map.py
366 | 79
367 |
368 |
369 |
370 | file://$PROJECT_DIR$/Map/linked_list_map.py
371 | 43
372 |
373 |
374 |
375 | file://$PROJECT_DIR$/Map/linked_list_map.py
376 | 56
377 |
378 |
379 |
380 | file://$PROJECT_DIR$/SegmentTree/segment_tree.py
381 | 52
382 |
383 |
384 |
385 | file://$PROJECT_DIR$/AVL/avl_map.py
386 | 18
387 |
388 |
389 |
390 | file://$PROJECT_DIR$/AVL/avl_map.py
391 | 21
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
--------------------------------------------------------------------------------
/AVL/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/AVL/__init__.py
--------------------------------------------------------------------------------
/AVL/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/AVL/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/AVL/__pycache__/avl_map.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/AVL/__pycache__/avl_map.cpython-36.pyc
--------------------------------------------------------------------------------
/AVL/__pycache__/avl_tree.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/AVL/__pycache__/avl_tree.cpython-36.pyc
--------------------------------------------------------------------------------
/AVL/avl_map.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--07--Map(基于AVL树进行实现)
3 | '''
4 | from Map.map_base import MapBase
5 | from AVL.avl_tree import AVLTree
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2019/3/19 19:53'
9 |
10 |
11 | class AVLMap(MapBase):
12 | '''
13 | 数据结构--07--Map(基于AVL树进行实现)
14 | '''
15 | def __init__(self):
16 | self._avl = AVLTree()
17 |
18 | def __getitem__(self, key):
19 | return self._avl.getter(key)
20 |
21 | def __setitem__(self, key, value):
22 | self._avl.setter(key, value)
23 |
24 | def add(self, key, value):
25 | self._avl.add(key, value)
26 |
27 | def remove(self, key):
28 | return self._avl.remove(key)
29 |
30 | def getter(self, key):
31 | return self._avl.getter(key)
32 |
33 | def setter(self, key, value):
34 | self._avl.setter(key, value)
35 |
36 | def contains(self, key):
37 | return self._avl.contains(key)
38 |
39 | def get_size(self):
40 | return self._avl.get_size()
41 |
42 | def is_empty(self):
43 | return self._avl.is_empty()
44 |
--------------------------------------------------------------------------------
/AVL/avl_set.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--06--Set(基于AVL树进行实现)
3 | '''
4 | from Set.set_base import SetBase
5 | from AVL.avl_tree import AVLTree
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2019/3/19 19:47'
9 |
10 |
11 | class AVLSet(SetBase):
12 | '''
13 | 数据结构--06--Set(基于AVL树进行实现)
14 | '''
15 | def __init__(self):
16 | self._avl = AVLTree()
17 |
18 | def add(self, value):
19 | self._avl.add(value, None)
20 |
21 | def remove(self, value):
22 | return self._avl.remove(value)
23 |
24 | def contains(self, value):
25 | return self._avl.contains(value)
26 |
27 | def get_size(self):
28 | return self._avl.get_size()
29 |
30 | def is_empty(self):
31 | return self._avl.is_empty()
32 |
--------------------------------------------------------------------------------
/AVL/avl_tree.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--12--AVL树(平衡二叉树)
3 | 1. 定义:叶子节点之间的deepth差不大于1(对于任一节点,左子树和右子树的高度差不大于1)
4 | 2. 常见AVL树:满二叉树/完全二叉树/线段树/堆...
5 | 3. 平衡二叉树的高度和节点数量之间的关系为log2n
6 | 4. 平衡因子:左右子树的高度差
7 | '''
8 | import time
9 | from Binary_Search_Tree.BST import BST
10 |
11 | __author__ = 'Yan'
12 | __date__ = '2019/3/19 10:47'
13 |
14 |
15 | class AVLTree:
16 | '''
17 | 数据结构--12--AVL树
18 | '''
19 | class _Node:
20 | def __init__(self, key, value):
21 | self.key = key
22 | self.value = value
23 | self.left = None
24 | self.right = None
25 | self.height = 1
26 |
27 | def __init__(self):
28 | self._root = None
29 | self._size = 0
30 |
31 | def get_size(self):
32 | '''
33 | 获取AVL树中元素个数
34 | '''
35 | return self._size
36 |
37 | def is_empty(self):
38 | '''
39 | 判断AVL树是否为空
40 | '''
41 | return self._size == 0
42 |
43 | def is_banlanced(self):
44 | '''
45 | 判断该二叉树是否是一棵AVL树
46 | '''
47 | return self._is_banlanced(self._root)
48 |
49 | def _is_banlanced(self, node):
50 | '''
51 | 判断该二叉树是否是一棵AVL树,采用递归实现
52 | '''
53 | if node is None:
54 | return True
55 | banlance_factor = self._get_banlance_factor(node)
56 | if abs(banlance_factor) > 1:
57 | return False
58 | return self._is_banlanced(node.left) and self._is_banlanced(node.right)
59 |
60 | def is_bst(self):
61 | '''
62 | 判断该二叉树是否是一棵二分搜索树,二分搜索树的中序遍历得到的数据是有序的
63 | '''
64 | result = []
65 | self._in_order(self._root, result)
66 |
67 | for i in range(1, len(result)):
68 | if result[i - 1] > result[i]:
69 | return False
70 | return True
71 |
72 | def _in_order(self, node, result):
73 | '''
74 | 对该二叉树进行中序遍历
75 | '''
76 | if node is None:
77 | return
78 |
79 | self._in_order(node.left, result)
80 | result.append(node.key)
81 | self._in_order(node.right, result)
82 |
83 | def _get_height(self, node):
84 | '''
85 | 获取节点node的高度
86 | '''
87 | if node is None:
88 | return 0
89 | return node.height
90 |
91 | def _get_banlance_factor(self, node):
92 | '''
93 | 获取节点node的平衡因子
94 | '''
95 | if node is None:
96 | return 0
97 | return self._get_height(node.left) - self._get_height(node.right)
98 |
99 | def add(self, key, value):
100 | '''
101 | 向AVL树中添加一个元素(key, value)
102 | '''
103 | self._root = self._add(self._root, key, value)
104 |
105 | def _add(self, node, key, value):
106 | '''
107 | 向以node为根节点的AVL树中添加一个元素(key, value)
108 | '''
109 | if node is None:
110 | self._size += 1
111 | return self._Node(key, value)
112 |
113 | if key < node.key:
114 | node.left = self._add(node.left, key, value)
115 | elif key > node.key:
116 | node.right = self._add(node.right, key, value)
117 | else:
118 | node.value = value
119 |
120 | # 更新node.height
121 | node.height = 1 + max(self._get_height(node.left), self._get_height(node.right))
122 |
123 | # 计算平衡因子
124 | banlance_factor = self._get_banlance_factor(node)
125 |
126 | # 维护平衡
127 | # 插入的元素在左侧的左侧
128 | if banlance_factor > 1 and self._get_banlance_factor(node.left) >= 0:
129 | return self._right_rotate(node)
130 |
131 | # 插入的元素在右侧的右侧
132 | if banlance_factor < -1 and self._get_banlance_factor(node.right) <= 0:
133 | return self._left_rotate(node)
134 |
135 | # 插入的元素在左侧的右侧
136 | if banlance_factor > 1 and self._get_banlance_factor(node.left) < 0:
137 | node.left = self._left_rotate(node.left)
138 | return self._right_rotate(node)
139 |
140 | # 插入的元素在右侧的左侧
141 | if banlance_factor < -1 and self._get_banlance_factor(node.right) > 0:
142 | node.right = self._right_rotate(node.right)
143 | return self._left_rotate(node)
144 |
145 | return node
146 |
147 | def _right_rotate(self, node):
148 | '''
149 | 在y节点的左子树的左侧中加入一个元素后,导致不平衡 ---> 右旋转,维护平衡
150 |
151 | y x
152 | / \ / \
153 | x T4 向右旋转 (y) z y
154 | / \ - - - - - - - -> / \ / \
155 | z T3 T1 T2 T3 T4
156 | / \
157 | T1 T2
158 |
159 | 假设 T1 和 T2 子树的最大高度为 h --> 那么 z 的高度为 h+1 --> x 的高度为 h+2
160 | --> 因为 x 也是保持平衡的,所以 T3 的 高度为 h+1 或者 h
161 | --> y 打破平衡,由于 x 的高度为 h+2,所以 T4 的高度为 h
162 |
163 | 按照这样计算,旋转后的二分搜索树也是维持平衡的
164 | '''
165 | x = node.left
166 | T3 = x.right
167 | x.right = node
168 | node.left = T3
169 |
170 | # 更新height
171 | node.height = 1 + max(self._get_height(node.left), self._get_height(node.right))
172 | x.height = 1 + max(self._get_height(x.left), self._get_height(x.right))
173 |
174 | return x
175 |
176 | def _left_rotate(self, node):
177 | '''
178 | 在y节点的右子树的右侧中加入一个元素后,导致不平衡 --> 左旋转,维护平衡
179 |
180 | y x
181 | / \ / \
182 | T1 x 向左旋转 (y) y z
183 | / \ - - - - - - - -> / \ / \
184 | T2 z T1 T2 T3 T4
185 | / \
186 | T3 T4
187 | '''
188 | x = node.right
189 | T2 = x.left
190 | x.left = node
191 | node.right = T2
192 |
193 | # 更新height
194 | node.height = 1 + max(self._get_height(node.left), self._get_height(node.right))
195 | x.height = 1 + max(self._get_height(x.left), self._get_height(x.right))
196 |
197 | return x
198 |
199 | def _get_node(self, node, key):
200 | '''
201 | 返回以node为根节点的AVL树中,key所在的node
202 | '''
203 | if node is None:
204 | return None
205 |
206 | if key < node.key:
207 | return self._get_node(node.left, key)
208 | elif key > node.key:
209 | return self._get_node(node.right, key)
210 | else:
211 | return node
212 |
213 | def contains(self, key):
214 | '''
215 | 查询AVL树中是否存在键为key的节点
216 | '''
217 | ret = self._get_node(self._root, key)
218 | if ret is None:
219 | return False
220 | return True
221 |
222 | def getter(self, key):
223 | '''
224 | 获取AVL树中key对应的值
225 | '''
226 | ret = self._get_node(self._root, key)
227 | if ret is None:
228 | raise KeyError("AVL Tree has no key : {}".format(key))
229 | return ret.value
230 |
231 | def setter(self, key, value):
232 | '''
233 | 将AVL树中key对应的value修改为value,如果不存在key,则添加一个新node
234 | '''
235 | ret = self._get_node(self._root, key)
236 | if ret is None:
237 | self.add(key, value)
238 | return
239 | ret.value = value
240 |
241 | def remove(self, key):
242 | '''
243 | 删除AVL树中key所在的节点
244 | '''
245 | node = self._get_node(self._root, key)
246 | if node is not None:
247 | self._root = self._remove(self._root, key)
248 | return node.value
249 | return None
250 |
251 | def _remove(self, node, key):
252 | '''
253 | 删除以node为根节点的AVL树中key所在的节点
254 | '''
255 | ret_node = None
256 | if node is None:
257 | return None
258 |
259 | if node.key == key:
260 | if node.left is None:
261 | # 待删除的节点node左子树为空,先保存node的右子树
262 | right_node = node.right
263 | node.right = None
264 | self._size -= 1
265 | ret_node = right_node
266 | elif node.right is None:
267 | # 待删除的节点右子树为空,先保存node的左子树
268 | left_node = node.left
269 | node.left = None
270 | self._size -= 1
271 | ret_node = left_node
272 | else:
273 | # 待删除的节点node左子树和右子树均不为空
274 | # 1. 找到node的右子树的最小元素所在的节点,并赋给successor
275 | successor = self._minimum(node.right)
276 | # 2. 删除node的右子树的最小元素所在的节点,self._remove_min(node.right)返回的
277 | # 是以node.right为根节点的二分搜索树删除最小元素后的新二分搜索树的根节点,赋值
278 | # 给successor.right
279 | if successor is not None:
280 | successor.right = self._remove(node.right, successor.key)
281 | successor.left = node.left
282 | self._size -= 1
283 |
284 | node.left = None
285 | node.right = None
286 | ret_node = successor
287 |
288 | elif key < node.key:
289 | node.left = self._remove(node.left, key)
290 | else:
291 | node.right = self._remove(node.right, key)
292 |
293 | if ret_node is None:
294 | return None
295 |
296 | # 更新node.height
297 | ret_node.height = 1 + max(self._get_height(ret_node.left), self._get_height(ret_node.right))
298 |
299 | # 计算平衡因子
300 | banlance_factor = self._get_banlance_factor(ret_node)
301 |
302 | # 维护平衡
303 | # 插入的元素在左侧的左侧
304 | if banlance_factor > 1 and self._get_banlance_factor(ret_node.left) >= 0:
305 | return self._right_rotate(ret_node)
306 |
307 | # 插入的元素在右侧的右侧
308 | if banlance_factor < -1 and self._get_banlance_factor(ret_node.right) <= 0:
309 | return self._left_rotate(ret_node)
310 |
311 | # 插入的元素在左侧的右侧
312 | if banlance_factor > 1 and self._get_banlance_factor(ret_node.left) < 0:
313 | ret_node.left = self._left_rotate(ret_node.left)
314 | return self._right_rotate(ret_node)
315 |
316 | # 插入的元素在右侧的左侧
317 | if banlance_factor < -1 and self._get_banlance_factor(ret_node.right) > 0:
318 | ret_node.right = self._right_rotate(ret_node.right)
319 | return self._left_rotate(ret_node)
320 |
321 | return ret_node
322 |
323 | def minimum(self):
324 | '''
325 | 返回AVL树中最小key的node
326 | '''
327 | return self._minimum(self._root)
328 |
329 | def _minimum(self, node):
330 | '''
331 | 返回AVL树中最小key的node
332 | '''
333 | if node.left is None:
334 | return node
335 | self._minimum(node.left)
336 |
337 |
338 | def avl_tree_test(avl_tree, bst):
339 | '''
340 | 测试AVL树代码是否书写正确,以及性能测试
341 | '''
342 | with open('pride-and-prejudice.txt', 'r', encoding='utf-8') as f:
343 | words = f.read()
344 | words = words.split()
345 |
346 | # AVL树测试
347 | start_time = time.time()
348 | for word in words:
349 | if avl_tree.contains(word):
350 | avl_tree.setter(word, 1 + avl_tree.getter(word))
351 | else:
352 | avl_tree.add(word, 1)
353 |
354 | print("total words: ", avl_tree.get_size())
355 | print("frequency of pride: ", avl_tree.getter('pride'))
356 | print('frequency of prejudice: ', avl_tree.getter('prejudice'))
357 |
358 | # print("is BST: ", avl_tree.is_bst())
359 | # print("is Banlanced: ", avl_tree.is_banlanced())
360 |
361 | avl_tree.remove('pride')
362 | print("AVL spend time: ", time.time()-start_time)
363 | # print("is BST: ", avl_tree.is_bst())
364 | # print("is Banlanced: ", avl_tree.is_banlanced())
365 |
366 | # BST测试
367 | start_time = time.time()
368 | for word in words:
369 | bst.add(word)
370 |
371 | print("total words: ", bst.get_size())
372 |
373 | bst.remove('pride')
374 | print("BST spend time: ", time.time()-start_time)
375 |
376 |
377 | if __name__ == "__main__":
378 | avl_tree = AVLTree()
379 | bst = BST()
380 | avl_tree_test(avl_tree, bst)
381 |
--------------------------------------------------------------------------------
/Array/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Array/__init__.py
--------------------------------------------------------------------------------
/Array/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Array/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/Array/__pycache__/array.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Array/__pycache__/array.cpython-36.pyc
--------------------------------------------------------------------------------
/Array/array.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--01--数组
3 | '''
4 | __author__ = 'Yan'
5 | __date__ = '2018/11/19 16:13'
6 |
7 |
8 | class Array:
9 | '''
10 | 数据结构--01--数组
11 | '''
12 | def __init__(self, arr=None, capacity=10):
13 | if isinstance(arr, list):
14 | self._data = arr[:]
15 | self._size = len(arr)
16 | else:
17 | self._size = 0
18 | self._data = [None] * capacity
19 |
20 | def __getitem__(self, index):
21 | return self._data[index]
22 |
23 | def __setitem__(self, key, value):
24 | self.add_last(value)
25 |
26 | def get_capacity(self):
27 | '''
28 | 获取数组的容量
29 | '''
30 | return len(self._data)
31 |
32 | def get_size(self):
33 | '''
34 | 获取数组中的元素个数
35 | '''
36 | return self._size
37 |
38 | def is_empty(self):
39 | '''
40 | 判断数组是否为空
41 | '''
42 | return self._size == 0
43 |
44 | def add_last(self, value):
45 | '''
46 | 在数组末尾插入元素value
47 | '''
48 | self.add(self._size, value)
49 |
50 | def add_first(self, value):
51 | '''
52 | 在数组起始位置插入元素value
53 | '''
54 | self.add(0, value)
55 |
56 | def add(self, index, value):
57 | '''
58 | 在索引为index的位置插入元素value
59 | '''
60 |
61 | if index < 0 or index > self._size:
62 | raise IndexError("Add failed, Required index >= 0 and index <= size")
63 |
64 | # 如果数组full,那么扩容一倍
65 | if self._size == len(self._data):
66 | if self._size == 0:
67 | self._resize(1)
68 | else:
69 | self._resize(len(self._data) * 2)
70 |
71 | # index之后的元素往后移一位
72 | for i in range(self._size - 1, index - 1, -1):
73 | self._data[i + 1] = self._data[i]
74 |
75 | self._data[index] = value
76 | self._size += 1
77 |
78 | def get_first(self):
79 | '''
80 | 获取第0个元素的值
81 | '''
82 | return self.get(0)
83 |
84 | def get_last(self):
85 | '''
86 | 获取最后一个元素的值
87 | '''
88 | return self.get(self._size - 1)
89 |
90 | def get(self, index):
91 | '''
92 | 获取索引为index的值
93 | '''
94 | if index < 0 or index >= self._size:
95 | raise IndexError("get failed, Required index >= 0 and index <= size")
96 | return self._data[index]
97 |
98 | def set(self, index, value):
99 | '''
100 | 将索引为index的值改为value
101 | '''
102 | if index < 0 or index >= self._size:
103 | raise IndexError("set failed, Required index >= 0 and index <= size")
104 | self._data[index] = value
105 |
106 | def contains(self, value):
107 | '''
108 | 查看数组中是否包含元素value,包含则返回True,否则返回False
109 | '''
110 | for i in range(self._size):
111 | if self._data[i] == value:
112 | return True
113 | return False
114 |
115 | def find_index(self, value):
116 | '''
117 | 查找元素值为value在数组中的索引,如果不存在,则返回-1
118 | '''
119 | for i in range(self._size):
120 | if self._data[i] == value:
121 | return i
122 | return -1
123 |
124 | def remove_first(self):
125 | '''
126 | 移除数组中第一个元素
127 | '''
128 | return self.remove(0)
129 |
130 | def remove_last(self):
131 | '''
132 | 删除数组中最后一个元素
133 | '''
134 | return self.remove(self._size - 1)
135 |
136 | def remove_element(self, value):
137 | '''
138 | 删除数组中值为value的元素
139 | '''
140 | index = self.find_index(value)
141 | self.remove(index)
142 |
143 | def remove(self, index):
144 | '''
145 | 从数组中删除索引为index的元素,并返回删除的元素值
146 | '''
147 | if index < 0 or index > self._size:
148 | raise IndexError("remove failed, Required index >= 0 and index < size")
149 |
150 | ret = self._data[index]
151 |
152 | # index之后的元素往前移动一位
153 | for i in range(index + 1, self._size):
154 | self._data[i - 1] = self._data[i]
155 | self._size -= 1
156 |
157 | # 如果数组元素小于容量的1/4,则缩小容量至原有的1/2
158 | if self._size < len(self._data) // 4 and len(self._data) // 2 != 0:
159 | self._resize(len(self._data) // 2)
160 | return ret
161 |
162 | def _resize(self, new_capacity):
163 | '''
164 | 将数组空间的容量变成new_capacity的大小
165 | '''
166 | new_data = [None] * new_capacity
167 | for i in range(self._size):
168 | new_data[i] = self._data[i]
169 | self._data = new_data
170 |
171 | def swap(self, i, j):
172 | '''
173 | 交换索引为i和j两个位置的值
174 | '''
175 | if i < 0 or i >= self._size or j < 0 or j >= self._size:
176 | raise IndexError("index is illegal")
177 | self._data[i], self._data[j] = self._data[j], self._data[i]
178 |
179 |
180 | if __name__ == "__main__":
181 | array = Array()
182 | for i in range(10):
183 | array.add_last(i)
184 | print("capacity: %d" % array.get_capacity())
185 | print("size: %d" % array.get_size())
186 |
187 | array.add_last(10)
188 | print("capacity: %d" % array.get_capacity())
189 | print("size: %d" % array.get_size())
190 |
191 | array.add(4, "shiyue")
192 |
193 | print(array.find_index("shiyue"))
194 |
195 | for i in range(array.get_size()):
196 | print(array.get(i))
197 |
198 | for i in range(8):
199 | array.remove_last()
200 | print("capacity: %d" % array.get_capacity())
201 | print("size: %d" % array.get_size())
202 |
--------------------------------------------------------------------------------
/Binary_Search_Tree/BST.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--05--二分搜索树(基于ArrayQueue实现)
3 | 二分搜索树:
4 | 1. 每个节点的值都大于其左子树的所有节点的值
5 | 2. 每个节点的值都小于其右子树的所有节点的值
6 | 3. 每个节点的左子树和右子树都是一个二分搜索树(天然的递归)
7 | * 空也是一个二叉树,一个节点也是一个二叉树,二分搜索树就是一个二叉树
8 | '''
9 | from _Queue.array_queue import ArrayQueue
10 |
11 | __author__ = 'Yan'
12 | __date__ = '2018/11/19 22:54'
13 |
14 |
15 | class BST:
16 | '''
17 | 数据结构--05--二分搜索树(基于ArrayQueue实现),不包含重复元素
18 | '''
19 | class _Node:
20 | def __init__(self, value=None):
21 | self.value = value
22 | self.left = None
23 | self.right = None
24 |
25 | def __init__(self):
26 | self.root = None
27 | self.size = 0
28 |
29 | def get_size(self):
30 | '''
31 | 返回二分搜索树的节点个数
32 | '''
33 | return self.size
34 |
35 | def is_empty(self):
36 | '''
37 | 判断二分搜索树是否为空
38 | '''
39 | return self.size == 0
40 |
41 | def add(self, value):
42 | '''
43 | 用户真正调用的add方法,真正处理逻辑隐藏在_add方法中
44 | '''
45 | self.root = self._add(self.root, value)
46 |
47 | def _add(self, node, value):
48 | '''
49 | 向以node为根节点的二分搜索树种添加值为value的节点,采用递归算法
50 | '''
51 | add_node = self._Node(value)
52 |
53 | # 递归到底的情况
54 | if node is None:
55 | self.size += 1
56 | return add_node
57 |
58 | # 若value存在当前二分搜索树中,则不再添加,直接返回当前node
59 | if value < node.value:
60 | node.left = self._add(node.left, value)
61 | elif value > node.value:
62 | node.right = self._add(node.right, value)
63 |
64 | return node
65 |
66 | def contains(self, value):
67 | '''
68 | 用户真正调用的contains方法,真正处理逻辑隐藏在_contains方法中
69 | 查询二分搜索树中是否包含值为value的节点,如果包含则返回True,否则返回False
70 | '''
71 | return self._contains(self.root, value)
72 |
73 | def _contains(self, node, value):
74 | '''
75 | 查询以node为根节点的二分搜索树中是否存在值为value的节点,存在返回True,否则返回False
76 | 采用递归算法实现
77 | '''
78 | if node is None:
79 | return False
80 |
81 | if value == node.value:
82 | return True
83 | elif value < node.value:
84 | return self._contains(node.left, value)
85 | else:
86 | return self._contains(node.right, value)
87 |
88 | def pre_order(self):
89 | '''
90 | 前序遍历,用户真正调用的pre_order方法,真正的处理逻辑隐藏在_pre_order方法中
91 | '''
92 | self._pre_order(self.root)
93 |
94 | def _pre_order(self, node):
95 | '''
96 | 前序遍历(深度优先遍历)以node为根节点的二分搜索树,采用递归算法实现
97 | '''
98 | if node is None:
99 | return
100 |
101 | print(node.value)
102 | self._pre_order(node.left)
103 | self._pre_order(node.right)
104 |
105 | def in_order(self):
106 | '''
107 | 中序遍历,用户调用的in_order方法,真正处理逻辑隐藏在_in_order方法中
108 | '''
109 | self._in_order(self.root)
110 |
111 | def _in_order(self, node):
112 | '''
113 | 中序遍历以node为根节点的二分搜索树,采用递归算法实现
114 | '''
115 | if node is None:
116 | return
117 |
118 | self._in_order(node.left)
119 | print(node.value)
120 | self._in_order(node.right)
121 |
122 | def post_order(self):
123 | '''
124 | 后序遍历,用户调用的post_order方法,真正处理逻辑隐藏在_post_order方法中
125 | '''
126 | self._post_order(self.root)
127 |
128 | def _post_order(self, node):
129 | '''
130 | 后序遍历以node为根节点的二分搜索树,采用递归算法实现
131 | '''
132 | if node is None:
133 | return
134 |
135 | self._post_order(node.left)
136 | self._post_order(node.right)
137 | print(node.value)
138 |
139 | def level_order(self):
140 | '''
141 | 层序遍历(广度优先遍历),使用辅助数据结构队列ArrayQueue实现
142 | '''
143 | result = []
144 | queue = ArrayQueue()
145 | queue.enqueue(self.root)
146 |
147 | while not queue.is_empty():
148 | node = queue.get_front()
149 | result.append(queue.dequeue().value)
150 | if node.left:
151 | queue.enqueue(node.left)
152 | if node.right:
153 | queue.enqueue(node.right)
154 | print("level_order: ", ' '.join("%s" % value for value in result))
155 |
156 | def minimum(self):
157 | '''
158 | 返回二分搜索树的最小元素值,用户调用的minimum方法,真正处理逻辑在_minimum方法中
159 | '''
160 | if self.size == 0:
161 | raise IndexError("BST is empty")
162 |
163 | return self._minimum(self.root).value
164 |
165 | def _minimum(self, node):
166 | '''
167 | 返回以node为根节点中最小元素值的节点,最小元素值所在的节点在整棵树的最左下方
168 | '''
169 | if node.left is None:
170 | return node
171 |
172 | return self._minimum(node.left)
173 |
174 | # 寻找二分搜索树的最大元素
175 | def maximum(self):
176 | '''
177 | 返回二分搜索树的最大元素值,用户调用的maximum方法,真正处理逻辑在_maximum方法中
178 | '''
179 | if self.size == 0:
180 | raise IndexError("BST is empty")
181 |
182 | return self._maximum(self.root).value
183 |
184 | def _maximum(self, node):
185 | '''
186 | 返回以node为根节点中最大元素值的节点,最大元素值所在的节点在整棵树的最右下方
187 | '''
188 | if node.right is None:
189 | return node
190 |
191 | return self._maximum(node.right)
192 |
193 | def remove_min(self):
194 | '''
195 | 删除最小元素所在的节点,并返回最小值,用户调用的remove_min方法,真正处理逻辑在_remove_min方法中
196 | '''
197 | ret = self.minimum()
198 | self.root = self._remove_min(self.root)
199 | return ret
200 |
201 | def _remove_min(self, node):
202 | '''
203 | 删除以node为根节点的最小元素值所在节点,并返回新二分搜索树的根节点,采用递归算法实现
204 | 存在两种情况:
205 | 1. 最小元素值所在节点没有右子节点,直接remove即可
206 | 2. 最小元素值所在节点存在右子节点,需要先保存右子节点,并连接上最小元素值所在节点的父节点
207 | '''
208 | if node.left is None:
209 | right_node = node.right
210 | node.right = None
211 | self.size -= 1
212 | return right_node
213 |
214 | node.left = self._remove_min(node.left)
215 | return node
216 |
217 | def remove_max(self):
218 | '''
219 | 删除最大元素所在的节点,并返回最大值,用户调用的remove_max方法,真正处理逻辑在_remove_max方法中
220 | '''
221 | ret = self.maximum()
222 | self.root = self._remove_max(self.root)
223 | return ret
224 |
225 | def _remove_max(self, node):
226 | '''
227 | 删除以node为根节点的最大元素值所在节点,并返回新二分搜索树的根节点,采用递归算法实现
228 | 存在两种情况:
229 | 1. 最大元素值所在节点没有左子节点,直接remove即可
230 | 2. 最大元素值所在节点存在左子节点,需要先保存左子节点,并连接上最大元素值所在节点的父节点
231 | '''
232 | if node.right is None:
233 | left_node = node.left
234 | node.left = None
235 | self.size -= 1
236 | return left_node
237 |
238 | node.right = self._remove_max(node.right)
239 | return node
240 |
241 | def remove(self, value):
242 | '''
243 | 删除值为value的节点,用户调用的方法,真正处理逻辑隐藏在_remove方法中
244 | '''
245 | self.root = self._remove(self.root, value)
246 |
247 | def _remove(self, node, value):
248 | '''
249 | 删除以node为根节点的二分搜索树中值为value的节点,并返回新二分搜索树的根节点,采用递归算法实现
250 | '''
251 | if node is None:
252 | return None
253 |
254 | if node.value == value:
255 | if node.left is None:
256 | # 待删除的节点node左子树为空,先保存node的右子树
257 | right_node = node.right
258 | node.right = None
259 | self.size -= 1
260 | return right_node
261 | elif node.right is None:
262 | # 待删除的节点右子树为空,先保存node的左子树
263 | left_node = node.left
264 | node.left = None
265 | self.size -= 1
266 | return left_node
267 | else:
268 | # 待删除的节点node左子树和右子树均不为空
269 | # 1. 找到node的右子树的最小元素所在的节点,并赋给successor
270 | successor = self._minimum(node.right)
271 | # 2. 删除node的右子树的最小元素所在的节点,self._remove_min(node.right)返回的
272 | # 是以node.right为根节点的二分搜索树删除最小元素后的新二分搜索树的根节点,赋值
273 | # 给successor.right
274 | successor.right = self._remove_min(node.right)
275 | # 不用维护size,因为self._remove_min(node.right)中size已经-1了
276 | successor.left = node.left
277 |
278 | node.left = None
279 | node.right = None
280 | return successor
281 |
282 | elif value < node.value:
283 | node.left = self._remove(node.left, value)
284 | else:
285 | node.right = self._remove(node.right, value)
286 |
287 | return node
288 |
289 |
290 | def print_test(bst):
291 | '''
292 | print test
293 | '''
294 | print("pre_order: --------------")
295 | bst.pre_order()
296 | print("in_order: ---------------")
297 | bst.in_order()
298 | print("post_order: -------------")
299 | bst.post_order()
300 | bst.level_order()
301 | print("minimum: ", bst.minimum())
302 | print("maximum: ", bst.maximum())
303 |
304 |
305 | def bst_test():
306 | '''
307 | 测试BST代码是否书写正确
308 | '''
309 | bst = BST()
310 | bst.add(25)
311 | bst.add(20)
312 | bst.add(18)
313 | bst.add(19)
314 | bst.add(67)
315 | bst.add(30)
316 | print_test(bst)
317 |
318 | print("after remove min and max: -------- ")
319 | bst.remove_min()
320 | bst.remove_max()
321 | print_test(bst)
322 |
323 | print("after remove 25: -----------------")
324 | bst.remove(25)
325 | print_test(bst)
326 |
327 |
328 | if __name__ == "__main__":
329 | bst_test()
330 |
--------------------------------------------------------------------------------
/Binary_Search_Tree/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Binary_Search_Tree/__init__.py
--------------------------------------------------------------------------------
/Binary_Search_Tree/__pycache__/BST.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Binary_Search_Tree/__pycache__/BST.cpython-36.pyc
--------------------------------------------------------------------------------
/Binary_Search_Tree/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Binary_Search_Tree/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/Hash_Table/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Hash_Table/__init__.py
--------------------------------------------------------------------------------
/Hash_Table/hash_table.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--13--HashTable(哈希表)
3 | 1. 哈希表充分体现了算法设计领域的经典思想:空间换时间
4 | 2. 哈希表是时间和空间之间的平衡
5 | 3. 哈希函数的设计是很重要的
6 | 4. “键”通过哈希函数得到的“索引”分布越均匀越好
7 |
8 | 哈希函数的设计原则:
9 | 1. 一致性:如果a == b,那么hash(a) == hash(b)
10 | 2. 高效性:计算高效简便
11 | 3. 均匀性:哈希值均匀分布
12 |
13 | 哈希函数的设计:
14 | 1. 整数:
15 | 小整数 --> 直接用
16 | 大整数 --> 取模(对一个合理的素数取模)
17 | 2. 字符串 --> 转换成整型
18 | hash(code) = (c * B^3 + o * B^2 + d * B^1 + e * e^0) % M -->
19 | hasn(code) = ((((c * B) + o) * B + d) * B + e) % M -->
20 | hash(code) = ((((c % M * B) + o) % M * B + d) % M * B + e) % M
21 | '''
22 | import time
23 | from Array.array import Array
24 | from AVL.avl_map import AVLMap
25 | from AVL.avl_tree import AVLTree
26 | from Binary_Search_Tree.BST import BST
27 |
28 | __author__ = 'Yan'
29 | __date__ = '2019/3/19 20:29'
30 |
31 |
32 | class HashTable:
33 | '''
34 | 数据结构--13--HashTable(哈希表)
35 | '''
36 | def __init__(self, M):
37 | self._M = M
38 | self._size = 0
39 | self._hashtable = Array()
40 | for i in range(self._M):
41 | self._hashtable[i] = AVLMap()
42 |
43 | def get_size(self):
44 | '''
45 | 获取HashTable中元素的个数
46 | '''
47 | return self._size
48 |
49 | def _hash(self, key):
50 | '''
51 | hash函数,0x7fffffff表示将负数转换成正数
52 | '''
53 | return (hash(key) & 0x7fffffff) % self._M
54 |
55 | def add(self, key, value):
56 | '''
57 | 向HashTable中添加一个元素
58 | '''
59 | avl_map = self._hashtable[self._hash(key)]
60 | if avl_map.contains(key):
61 | avl_map.set(key, value)
62 | else:
63 | avl_map.add(key, value)
64 | self._size += 1
65 |
66 | def remove(self, key):
67 | '''
68 | 从HashTable中删除一个元素
69 | '''
70 | avl_map = self._hashtable[self._hash(key)]
71 | if avl_map.contains(key):
72 | value = avl_map.remove(key)
73 | self._size -= 1
74 | else:
75 | raise KeyError("key {} doesn't exist.".format(key))
76 |
77 | return value
78 |
79 | def get(self, key):
80 | '''
81 | 获取HashTable中key对应的value
82 | '''
83 | return self._hashtable[self._hash(key)].getter(key)
84 |
85 | def set(self, key, value):
86 | '''
87 | 将HashTable中key对应的值修改为value
88 | '''
89 | avl_map = self._hashtable[self._hash(key)]
90 | if avl_map.contains(key):
91 | avl_map.setter(key, value)
92 | else:
93 | raise KeyError("key {} doesn't exist.".format(key))
94 |
95 | def contains(self, key):
96 | '''
97 | 查询HashTable中是否存在key
98 | '''
99 | return self._hashtable[self._hash(key)].contains(key)
100 |
101 |
102 | def hash_table_test(hash_table, avl_tree, bst):
103 | with open('pride-and-prejudice.txt', 'r', encoding='utf-8') as f:
104 | words = f.read()
105 | words = words.split()
106 |
107 | # HashTable测试
108 | start_time = time.time()
109 | for word in words:
110 | if hash_table.contains(word):
111 | hash_table.set(word, 1 + hash_table.get(word))
112 | else:
113 | hash_table.add(word, 1)
114 | for word in words:
115 | hash_table.contains(word)
116 | print("HashTable test: ------------------")
117 | print("total words: ", hash_table.get_size())
118 | print("frequency of pride: ", hash_table.get('pride'))
119 | print('frequency of prejudice: ', hash_table.get('prejudice'))
120 | hash_table.remove('pride')
121 | print("HashTabel spend time: ", time.time()-start_time)
122 |
123 | # AVL树测试
124 | start_time = time.time()
125 | for word in words:
126 | if avl_tree.contains(word):
127 | avl_tree.setter(word, 1 + avl_tree.getter(word))
128 | else:
129 | avl_tree.add(word, 1)
130 | for word in words:
131 | avl_tree.contains(word)
132 | print("AVL test: ------------------")
133 | print("total words: ", avl_tree.get_size())
134 | print("frequency of pride: ", avl_tree.getter('pride'))
135 | print('frequency of prejudice: ', avl_tree.getter('prejudice'))
136 | avl_tree.remove('pride')
137 | print("AVL spend time: ", time.time()-start_time)
138 |
139 | # BST测试
140 | start_time = time.time()
141 | for word in words:
142 | bst.add(word)
143 | for word in words:
144 | bst.contains(word)
145 | print("BST test: ------------------")
146 | print("total words: ", bst.get_size())
147 | bst.remove('pride')
148 | print("BST spend time: ", time.time()-start_time)
149 |
150 |
151 | if __name__ == "__main__":
152 | hash_table = HashTable(131071)
153 | avl_tree = AVLTree()
154 | bst = BST()
155 | hash_table_test(hash_table, avl_tree, bst)
156 |
--------------------------------------------------------------------------------
/Linked_List/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Linked_List/__init__.py
--------------------------------------------------------------------------------
/Linked_List/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Linked_List/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/Linked_List/__pycache__/linked_list.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Linked_List/__pycache__/linked_list.cpython-36.pyc
--------------------------------------------------------------------------------
/Linked_List/linked_list.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--02--链表
3 | '''
4 | __author__ = 'Yan'
5 | __date__ = '2018/11/19 21:39'
6 |
7 |
8 | class LinkedList:
9 | '''
10 | 数据结构--02--链表
11 | '''
12 |
13 | class _Node:
14 | '''
15 | 表示链表中的每个节点
16 | '''
17 | def __init__(self, value=None, node_next=None):
18 | '''
19 | value : 当前节点的值
20 | node_next : 指向的下个节点
21 | '''
22 | self.value = value
23 | self.next = node_next
24 |
25 | def __init__(self):
26 | '''
27 | 构造函数,dummy_head : 虚拟头指针
28 | '''
29 | self.dummy_head = self._Node()
30 | self.size = 0
31 |
32 | def get_size(self):
33 | '''
34 | 获取链表的节点个数
35 | '''
36 | return self.size
37 |
38 | def is_empty(self):
39 | '''
40 | 判断链表是否为空
41 | '''
42 | return self.size == 0
43 |
44 | def add_first(self, value):
45 | '''
46 | 在链表首部添加一个元素,值为value
47 | '''
48 | self.add(0, value)
49 |
50 | def add_last(self, value):
51 | '''
52 | 在链表末尾添加一个元素,值为value
53 | '''
54 | self.add(self.size, value)
55 |
56 | def add(self, index, value):
57 | '''
58 | 在索引为index的位置添加一个元素,值为value
59 | '''
60 | if index < 0 or index > self.size:
61 | raise IndexError("Add failed, Required index >= 0 and index <= %s" % self.size)
62 |
63 | # 找到要插入的位置的前一个节点
64 | pre = self.dummy_head
65 | for i in range(index):
66 | pre = pre.next
67 |
68 | add_node = self._Node(value=value)
69 | add_node.next = pre.next
70 | pre.next = add_node
71 |
72 | self.size += 1
73 |
74 | def get(self, index):
75 | '''
76 | 获取索引为index的元素的值
77 | '''
78 | if self.size == 0:
79 | raise IndexError("linked_list is empty")
80 | if index < 0 or index >= self.size:
81 | raise IndexError("Add failed, Required index >= 0 and index < %s" % self.size)
82 |
83 | cur = self.dummy_head
84 | for i in range(index + 1):
85 | cur = cur.next
86 | return cur.value
87 |
88 | def get_first(self):
89 | '''
90 | 获取链表第一个元素的值
91 | '''
92 | return self.get(0)
93 |
94 | def get_last(self):
95 | '''
96 | 获取链表最后一个元素的值
97 | '''
98 | return self.get(self.size - 1)
99 |
100 | def set(self, index, value):
101 | '''
102 | 将链表索引为index位置的元素值修改为value
103 | '''
104 | if self.size == 0:
105 | raise IndexError("linked_list is empty")
106 | if index < 0 or index >= self.size:
107 | raise IndexError("Set failed, Required index >= 0 and index < %s" % self.size)
108 |
109 | cur = self.dummy_head
110 | for i in range(index + 1):
111 | cur = cur.next
112 | cur.value = value
113 |
114 | def contains(self, value):
115 | '''
116 | 查询链表中是否存在值为value的元素,如果不存在,则返回-1
117 | '''
118 | cur = self.dummy_head.next
119 | for i in range(self.size):
120 | if cur.value == value:
121 | return True
122 | cur = cur.next
123 | return False
124 |
125 | def remove(self, index):
126 | '''
127 | 删除链表中索引为index位置的节点,并返回节点的值
128 | '''
129 | if self.size == 0:
130 | raise IndexError("linked_list is empty")
131 | if index < 0 or index >= self.size:
132 | raise IndexError("Remove failed, Required index >= 0 and index < %s" % self.size)
133 |
134 | pre = self.dummy_head
135 | for i in range(index):
136 | pre = pre.next
137 |
138 | remove_node = pre.next
139 | ret = remove_node.value
140 | pre.next = remove_node.next
141 | remove_node.next = None
142 | self.size -= 1
143 |
144 | return ret
145 |
146 | def remove_first(self):
147 | '''
148 | 删除链表的第一个节点,并返回节点的值
149 | '''
150 | return self.remove(0)
151 |
152 | def remove_last(self):
153 | '''
154 | 删除链表的最后一个节点,并返回节点的值
155 | '''
156 | return self.remove(self.size - 1)
157 |
158 | def remove_element(self, value):
159 | '''
160 | 删除链表中值为value的节点
161 | '''
162 | cur = self.dummy_head
163 | for i in range(self.size):
164 | if cur.next is not None:
165 | cur = cur.next
166 | if cur.value == value:
167 | self.remove(i)
168 | break
169 | else:
170 | raise ValueError("The node whose value is {0} does not exist".format(value))
171 |
172 |
173 | def linked_list_print(linked_list):
174 | '''
175 | 打印链表中所有节点的值
176 | '''
177 | linked_list_value = []
178 | for i in range(linked_list.size):
179 | linked_list_value.append(linked_list.get(i))
180 |
181 | print(linked_list_value)
182 |
183 |
184 | if __name__ == "__main__":
185 | linked_list = LinkedList()
186 | for i in range(10):
187 | linked_list.add_last(i)
188 |
189 | linked_list_print(linked_list)
190 | linked_list.add(8, "shiyue")
191 | linked_list_print(linked_list)
192 |
193 | linked_list.remove_element(3)
194 | linked_list_print(linked_list)
195 |
196 | print(linked_list.contains("shiyue"))
197 | print(linked_list.contains("jiuyue"))
198 |
199 | linked_list.set(7, "liuyue")
200 | linked_list_print(linked_list)
201 |
202 | linked_list.remove_element("jiuyue")
203 | linked_list_print(linked_list)
204 |
--------------------------------------------------------------------------------
/Map/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Map/__init__.py
--------------------------------------------------------------------------------
/Map/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Map/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/Map/__pycache__/map_base.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Map/__pycache__/map_base.cpython-36.pyc
--------------------------------------------------------------------------------
/Map/bst_map.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--07--映射Map(基于二分搜索树BST实现)
3 | '''
4 | import time
5 | from Map.map_base import MapBase
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2018/3/17 15:48'
9 |
10 |
11 | class BSTMap(MapBase):
12 | '''
13 | 数据结构--07--映射Map(基于二分搜索树BST实现)
14 | '''
15 | class _Node:
16 | def __init__(self, key=None, value=None):
17 | self.key = key
18 | self.value = value
19 | self.left = None
20 | self.right = None
21 |
22 | def __init__(self):
23 | self.root = None
24 | self._size = 0
25 |
26 | def get_size(self):
27 | return self._size
28 |
29 | def is_empty(self):
30 | return self._size == 0
31 |
32 | def add(self, key, value):
33 | self.root = self._add(self.root, key, value)
34 |
35 | def _add(self, node, key, value):
36 | '''
37 | 向以node为根节点的二分搜索树中插入节点,节点的键为key,键对应的值为value,采用递归算法实现
38 | '''
39 | if node is None:
40 | self._size += 1
41 | return self._Node(key, value)
42 |
43 | if key < node.key:
44 | node.left = self._add(node.left, key, value)
45 | elif key > node.key:
46 | node.right = self._add(node.right, key, value)
47 | return node
48 |
49 | def remove(self, key):
50 | self.root = self._remove(self.root, key)
51 |
52 | def _remove(self, node, key):
53 | '''
54 | 从以node为根节点的二分搜索树中删除键为key的节点,采用递归算法实现
55 | '''
56 | if node is None:
57 | return None
58 |
59 | if key < node.key:
60 | node.left = self._remove(node.left, key)
61 | elif key > node.key:
62 | node.right = self._remove(node.right, key)
63 | else:
64 | if node.left is None:
65 | # node的左子树为空
66 | right_node = node.right
67 | node.right = None
68 | self._size -= 1
69 | return right_node
70 |
71 | elif node.right is None:
72 | # node的右子树为空
73 | left_node = node.left
74 | node.left = None
75 | self._size -= 1
76 | return left_node
77 | else:
78 | # node的左右子树均不为空
79 | successor = self._minimum(node.right)
80 | successor.left = node.left
81 | successor.right = self._remove_min(node.right)
82 | node.left = None
83 | node.right = None
84 | return successor
85 |
86 | def minimum(self):
87 | '''
88 | 返回二分搜索树的最小元素值,用户调用的minimum方法,真正处理逻辑在_minimum方法中
89 | '''
90 | if self._size == 0:
91 | raise IndexError("BSTMap is empty")
92 |
93 | return self._minimum(self.root).key
94 |
95 | def _minimum(self, node):
96 | '''
97 | 返回以node为根节点中最小元素值的节点,最小元素值所在的节点在整棵树的最左下方,采用递归实现
98 | '''
99 | if node.left is None:
100 | return node
101 |
102 | node = self._minimum(node.left)
103 | return node
104 |
105 | def remove_min(self):
106 | '''
107 | 删除最小元素所在的节点,并返回最小值,用户调用的remove_min方法,真正处理逻辑在_remove_min方法中
108 | '''
109 | ret = self._minimum(self.root)
110 | self.root = self._remove_min(self.root)
111 | return ret.key
112 |
113 | def _remove_min(self, node):
114 | '''
115 | 删除以node为根节点的最小元素值所在节点,并返回新二分搜索树的根节点,采用递归算法实现
116 | 存在两种情况:
117 | 1. 最小元素值所在节点没有右子节点,直接remove即可
118 | 2. 最小元素值所在节点存在右子节点,需要先保存右子节点,并连接上最小元素值所在节点的父节点
119 | '''
120 | if node.left is None:
121 | right_node = node.right
122 | node.right = None
123 | self._size -= 1
124 | return right_node
125 |
126 | node.left = self._remove_min(node.left)
127 | return node
128 |
129 | def find_node(self, node, key):
130 | '''
131 | 在以node为根节点的二分搜索树种查找键为key的节点,并返回,采用递归实现
132 | '''
133 | if node is None:
134 | raise IndexError("key {} is not exist".format(key))
135 |
136 | if key == node.key:
137 | return node
138 | elif key < node.key:
139 | result = self.find_node(node.left, key)
140 | else:
141 | result = self.find_node(node.right, key)
142 | return result
143 |
144 | def getter(self, key):
145 | node = self.find_node(self.root, key)
146 | return node.value
147 |
148 | def setter(self, key, value):
149 | try:
150 | node = self.find_node(self.root, key)
151 | node.value = value
152 | except IndexError:
153 | self.add(key, value)
154 |
155 | def contains(self, key):
156 | try:
157 | self.find_node(self.root, key)
158 | return True
159 | except IndexError:
160 | return False
161 |
162 |
163 | def bst_map_test(bst_map):
164 | '''
165 | 测试BSTMap代码书写是否正确
166 | '''
167 | with open('shakespeare.txt', 'r') as f:
168 | words = f.read()
169 | words = words.split()
170 |
171 | start_time = time.time()
172 | for word in words:
173 | if bst_map.contains(word):
174 | bst_map.setter(word, bst_map.getter(word)+1)
175 | else:
176 | bst_map.add(word, 1)
177 |
178 | print('total words: ', len(words))
179 | print("unique words: ", bst_map.get_size())
180 | print("contains word 'This': ", bst_map.contains('This'))
181 | print('total time: {} seconds'.format(time.time() - start_time))
182 |
183 | bst_map.remove("This")
184 | print("contains word 'This' after remove : ", bst_map.contains("This"))
185 | bst_map.setter("This", 200)
186 | print("the value of key is 'This' : ", bst_map.getter("This"))
187 |
188 |
189 | if __name__ == "__main__":
190 | bst_map = BSTMap()
191 | bst_map_test(bst_map)
192 |
--------------------------------------------------------------------------------
/Map/linked_list_map.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--07--映射Map(基于链表LinkedList实现)
3 | '''
4 | import time
5 | from Map.map_base import MapBase
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2018/3/17 15:48'
9 |
10 |
11 | class LinkedListMap(MapBase):
12 | '''
13 | 数据结构--07--映射Map(基于链表LinkedList实现)
14 | '''
15 | class _Node:
16 | def __init__(self, key=None, value=None, node_next=None):
17 | self.key = key
18 | self.value = value
19 | self.node_next = node_next
20 |
21 | def __init__(self):
22 | self._dummy_head = self._Node()
23 | self._size = 0
24 |
25 | def get_size(self):
26 | return self._size
27 |
28 | def is_empty(self):
29 | return self._size == 0
30 |
31 | def add(self, key, value):
32 | cur = self._dummy_head
33 | for i in range(self._size):
34 | cur = cur.node_next
35 |
36 | add_node = self._Node(key, value)
37 | cur.node_next = add_node
38 | self._size += 1
39 |
40 | def find_node(self, key):
41 | '''
42 | 在映射Map中找到key对应的节点node
43 | '''
44 | cur = self._dummy_head.node_next
45 | for i in range(self._size):
46 | if cur.key == key:
47 | node = cur
48 | break
49 | else:
50 | cur = cur.node_next
51 | else:
52 | raise IndexError("{} is not exist".format(key))
53 |
54 | return node
55 |
56 | def remove(self, key):
57 | pre = self._dummy_head
58 | for i in range(self._size):
59 | cur = pre.node_next
60 | if cur.key == key:
61 | pre.node_next = cur.node_next
62 | result = cur.value
63 | cur.node_next = None
64 | self._size -= 1
65 | break
66 | else:
67 | pre = pre.node_next
68 | else:
69 | raise IndexError("{} is not exist".format(key))
70 |
71 | return result
72 |
73 | def getter(self, key):
74 | node = self.find_node(key)
75 | return node.value
76 |
77 | def setter(self, key, value):
78 | try:
79 | node = self.find_node(key)
80 | node.value = value
81 | except IndexError:
82 | self.add(key, value)
83 |
84 | def contains(self, key):
85 | try:
86 | self.find_node(key)
87 | return True
88 | except IndexError:
89 | return False
90 |
91 |
92 | def linked_list_map_test(linked_list_map):
93 | '''
94 | 测试LinkedListMap代码书写是否有误
95 | '''
96 | with open('shakespeare.txt', 'r') as f:
97 | words = f.read()
98 | words = words.split()
99 |
100 | start_time = time.time()
101 | for word in words:
102 | if linked_list_map.contains(word):
103 | linked_list_map.setter(word, linked_list_map.getter(word)+1)
104 | else:
105 | linked_list_map.add(word, 1)
106 |
107 | print('total words: ', len(words))
108 | print("unique words: ", linked_list_map.get_size())
109 | print("contains word 'This': ", linked_list_map.contains('This'))
110 | print('total time: {} seconds'.format(time.time() - start_time))
111 |
112 | linked_list_map.add('qiyue', 23)
113 | linked_list_map.add('bayue', 28)
114 | linked_list_map.add('shiyue', 89)
115 | linked_list_map.remove('bayue')
116 | print(linked_list_map.getter('qiyue'))
117 | print(linked_list_map.get_size())
118 | print(linked_list_map.getter('shiyue'))
119 | linked_list_map.setter("bayue", 200)
120 | print(linked_list_map.getter('bayue'))
121 |
122 |
123 | if __name__ == "__main__":
124 | linked_list_map = LinkedListMap()
125 | linked_list_map_test(linked_list_map)
126 |
--------------------------------------------------------------------------------
/Map/map_base.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--07--映射Map需要实现的方法
3 | '''
4 | import abc
5 |
6 | __author__ = 'Yan'
7 | __date__ = '2018/3/17 15:48'
8 |
9 |
10 | class MapBase(metaclass=abc.ABCMeta):
11 | '''
12 | 继承MapBase需要实现的方法,即映射Map需要实现的方法
13 | '''
14 | @abc.abstractmethod
15 | def add(self, key, value):
16 | '''
17 | 向映射Map中添加键值对key: value
18 | '''
19 | pass
20 |
21 | @abc.abstractmethod
22 | def remove(self, key):
23 | '''
24 | 从映射Map中删除元素key
25 | '''
26 | pass
27 |
28 | @abc.abstractmethod
29 | def getter(self, key):
30 | '''
31 | 获取映射Map中key对应的value
32 | '''
33 | pass
34 |
35 | @abc.abstractmethod
36 | def setter(self, key, value):
37 | '''
38 | 将映射Map中key的值修改为value,如果key不存在,则添加一个新节点
39 | '''
40 | pass
41 |
42 | @abc.abstractmethod
43 | def contains(self, key):
44 | '''
45 | 查询映射Map中是否包含key,包含返回True,否则返回False
46 | '''
47 | pass
48 |
49 | @abc.abstractmethod
50 | def get_size(self):
51 | '''
52 | 返回映射Map中元素的个数
53 | '''
54 | pass
55 |
56 | @abc.abstractmethod
57 | def is_empty(self):
58 | '''
59 | 判断映射Map是否为空
60 | '''
61 | pass
62 |
--------------------------------------------------------------------------------
/MaxHeap/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/MaxHeap/__init__.py
--------------------------------------------------------------------------------
/MaxHeap/max_heap.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--08--最大堆(基于数组Array实现)
3 | 本次讨论的最大堆是一个二叉堆,具有以下几个特点:
4 | 1. 二叉堆是一个完全二叉树(把元素顺序排列成树的形状)
5 | 2. 其父节点的值总是大于等于子节点的值
6 | 3. 以i节点为例,其父节点为(i - 1) / 2,左子节点为 (2 * i + 1),右子节点为(2 * i + 2)
7 | 拓展:
8 | 1. D叉堆
9 | 2. 索引堆
10 | 3. 斐波那契堆
11 | 4. 二项堆
12 | '''
13 | from random import randint
14 | from Array.array import Array
15 |
16 | __author__ = 'Yan'
17 | __date__ = '2018/3/17 23:11'
18 |
19 |
20 | class MaxHeap:
21 | '''
22 | 数据结构--08--最大堆(基于数组Array实现)
23 | '''
24 | def __init__(self, array=None, capacity=None):
25 | if isinstance(array, Array):
26 | self._data = array
27 | for i in range(self._parent(array.get_size() - 1), -1, -1):
28 | self._sift_down(i)
29 | return
30 | if capacity is None:
31 | self._data = Array()
32 | else:
33 | self._data = Array(capacity=capacity)
34 |
35 | def get_size(self):
36 | '''
37 | 返回最大堆MaxHeap中元素个数
38 | '''
39 | return self._data.get_size()
40 |
41 | def is_empty(self):
42 | '''
43 | 判断最大堆MaxHeap是否为空
44 | '''
45 | return self._data.is_empty()
46 |
47 | def add(self, value):
48 | '''
49 | 向最大堆MaxHeap中添加值为value的元素,共分为两步:
50 | 1. 将元素添加在数组Array的末尾
51 | 2. 对末尾元素进行Sift UP操作
52 | '''
53 | self._data.add_last(value)
54 | self._sift_up(self.get_size() - 1)
55 |
56 | def _sift_up(self, index):
57 | '''
58 | Sift UP 上浮,若子节点的值大于父节点的值,则Sift UP
59 | '''
60 | while index > 0 and self._data.get(index) > self._data.get(self._parent(index)):
61 | self._data.swap(index, self._parent(index))
62 | index = self._parent(index)
63 |
64 | def _sift_down(self, index):
65 | '''
66 | Sift Down下沉,若父节点小于子节点的值,则Sift Down
67 | '''
68 | while self._left_child(index) < self.get_size():
69 | left_child_index = self._left_child(index)
70 | right_child_index = self._right_child(index)
71 |
72 | # 获取左子节点和右子节点中最大值所在的索引,为max_index
73 | max_index = left_child_index
74 | if right_child_index < self.get_size() and self._data.get(left_child_index) < self._data.get(right_child_index):
75 | max_index = right_child_index
76 |
77 | # 如果当前index的值大于左右子节点中的最大值,那么直接break
78 | if self._data.get(index) > self._data.get(max_index):
79 | break
80 |
81 | self._data.swap(index, max_index)
82 | index = max_index
83 |
84 | def find_max(self):
85 | '''
86 | 找到最大堆MaxHeap中的最大元素
87 | '''
88 | if self.is_empty():
89 | raise ValueError("can not find max, MaxHeap is Empty")
90 | return self._data.get_first()
91 |
92 | def extract_max(self):
93 | '''
94 | 取出最大堆MaxHeap中的最大元素,总共分两步:
95 | 1. 将第一个元素(最大值)于最后一个元素交换
96 | 2. 对交换后的第一个元素进行Sfit Down操作
97 | '''
98 | ret = self.find_max()
99 | self._data.swap(0, self.get_size()-1)
100 | self._data.remove_last()
101 | self._sift_down(0)
102 | return ret
103 |
104 | def replace(self, value):
105 | '''
106 | 取出最大堆MaxHeap中的最大元素,并放入一个新的元素(替换掉最大元素)
107 | '''
108 | ret = self.find_max()
109 | self._data.set(0, value)
110 | self._sift_down(0)
111 | return ret
112 |
113 | def _parent(self, index):
114 | '''
115 | 返回索引为index的父亲节点所在的索引
116 | '''
117 | if index == 0:
118 | raise ValueError("index 0 has no parent")
119 | return (index - 1) // 2
120 |
121 | def _left_child(self, index):
122 | '''
123 | 返回索引为index的左子节点所在的索引
124 | '''
125 | return 2 * index + 1
126 |
127 | def _right_child(self, index):
128 | '''
129 | 返回索引为index的右子节点所在的索引
130 | '''
131 | return 2 * index + 2
132 |
133 |
134 | def max_heap_test(max_heap):
135 | '''
136 | 测试MaxHeap代码书写是否正确
137 | '''
138 | for i in range(10):
139 | max_heap.add(randint(1, 100000))
140 |
141 | for data in max_heap._data:
142 | print(data, end=' ')
143 |
144 | print('\n' + '-------result--------')
145 | for i in range(max_heap.get_size()):
146 | print(max_heap.extract_max())
147 | print('-------end-----------')
148 |
149 |
150 | def max_heap_test2():
151 | '''
152 | 测试MaxHeap代码书写是否正确
153 | '''
154 | array = Array()
155 | for i in range(10):
156 | array.add_last(randint(1, 100000))
157 |
158 | max_heap = MaxHeap(array)
159 |
160 | for data in max_heap._data:
161 | print(data, end=' ')
162 |
163 | print('\n' + '-------result--------')
164 | for i in range(max_heap.get_size()):
165 | print(max_heap.extract_max())
166 | print('-------end-----------')
167 |
168 |
169 | if __name__ == '__main__':
170 | max_heap = MaxHeap()
171 | max_heap_test(max_heap)
172 | max_heap_test2()
173 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Python-DataStructur
2 |
3 | ### 主要包括以下数据结构(以下为数据结构与对应的文件名):
4 |
5 | 1. 数组 --> Array
6 | 2. 链表 --> LinkedList
7 | 3. 队列 --> _Queue
8 | 4. 栈 --> Stack
9 | 5. 二分搜索树 --> Binary_Search_Tree
10 | 6. 集合 --> Set
11 | 7. 映射 --> Map
12 | 8. 最大堆 --> MaxHeap
13 | 9. 线段树 --> SegmentTree
14 | 10. Trie --> Trie
15 | 11. 并查集 --> UnionFind
16 | 12. AVL树 --> AVL
17 | 13. 哈希表 --> Hash_Table
18 |
--------------------------------------------------------------------------------
/SegmentTree/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/SegmentTree/__init__.py
--------------------------------------------------------------------------------
/SegmentTree/segment_tree.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--09--线段树(区间树)
3 | 最经典的线段树问题:区间染色
4 | 另一类经典问题:区间查询
5 | '''
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2019/3/18 14:47'
9 |
10 |
11 | class SegmentTree:
12 | '''
13 | 数据结构--09--线段树(区间树)
14 | '''
15 | def __init__(self, arr, merger):
16 | if not arr or not isinstance(arr, list) or not merger:
17 | raise ValueError("arr and merger should be passed in.")
18 | self._data = arr[:]
19 | self._tree = [None] * (len(arr) * 4)
20 | self._merger = merger
21 | self._build_segment_tree(0, 0, len(self._data) - 1)
22 |
23 | def get_size(self):
24 | '''
25 | 获取形成线段树的list中元素个数
26 | '''
27 | return len(self._data)
28 |
29 | def get(self, index):
30 | '''
31 | 获取形成线段树的list中索引为index的值
32 | '''
33 | if index < 0 or index > len(self._data) - 1:
34 | raise IndexError("index is illegal")
35 | return self._data[index]
36 |
37 | def _left_child(self, index):
38 | '''
39 | 返回完全二叉树的list表示中,一个索引所表示的元素的左孩子节点的索引
40 | '''
41 | return 2 * index + 1
42 |
43 | def _right_child(self, index):
44 | '''
45 | 返回完全二叉树的list表示中,一个索引所表示的元素的右孩子节点的索引
46 | '''
47 | return 2 * index + 2
48 |
49 | def _build_segment_tree(self, tree_index, left, right):
50 | '''
51 | 在treeIndex的位置创建表示区间[left...right]的线段树,采用递归实现
52 | '''
53 | if left == right:
54 | self._tree[tree_index] = self._data[left]
55 | return
56 |
57 | left_tree_index = self._left_child(tree_index)
58 | right_tree_index = self._right_child(tree_index)
59 |
60 | mid = left + (right - left) // 2
61 | self._build_segment_tree(left_tree_index, left, mid)
62 | self._build_segment_tree(right_tree_index, mid+1, right)
63 |
64 | self._tree[tree_index] = self._merger(self._tree[left_tree_index], self._tree[right_tree_index])
65 |
66 | def query(self, query_left, query_right):
67 | '''
68 | 返回区间[queryL, queryR]的值
69 | '''
70 | if query_left < 0 or query_left > len(self._data) - 1 or query_right < 0 or query_right > len(self._data) - 1 or query_left > query_right:
71 | raise IndexError("query_left or query_right is illegal.")
72 |
73 | return self._query(0, 0, len(self._data) - 1, query_left, query_right)
74 |
75 | def _query(self, tree_index, left, right, query_left, query_right):
76 | '''
77 | 在以tree_index为根的线段树中[left...right]的范围里,搜索区间[query_left...query_right]的值
78 | '''
79 | if left == query_left and right == query_right:
80 | return self._tree[tree_index]
81 |
82 | left_tree_index = self._left_child(tree_index)
83 | right_tree_index = self._right_child(tree_index)
84 |
85 | mid = left + (right - left) // 2
86 |
87 | if query_left >= mid + 1:
88 | return self._query(right_tree_index, mid + 1, right, query_left, query_right)
89 | elif query_right <= mid:
90 | return self._query(left_tree_index, left, mid, query_left, query_right)
91 |
92 | left_result = self._query(left_tree_index, left, mid, query_left, mid)
93 | right_result = self._query(right_tree_index, mid + 1, right, mid + 1, query_right)
94 | return self._merger(left_result, right_result)
95 |
96 | def set(self, index, value):
97 | '''
98 | 将index位置的值更新为value
99 | '''
100 | if index < 0 or index > len(self._data) - 1:
101 | raise IndexError("index is illegal")
102 | self._data[index] = value
103 | self._set(0, 0, len(self._data) - 1, index, value)
104 |
105 | def _set(self, tree_index, left, right, index, value):
106 | '''
107 | 在以tree_index为根的线段树中更新index位置的值为value
108 | '''
109 | if left == right:
110 | self._tree[tree_index] = value
111 | return
112 |
113 | left_tree_index = self._left_child(tree_index)
114 | right_tree_index = self._right_child(tree_index)
115 |
116 | mid = left + (right - left) // 2
117 | if index >= mid + 1:
118 | self._set(right_tree_index, mid + 1, right, index, value)
119 | else:
120 | self._set(left_tree_index, left, mid, index, value)
121 |
122 | # 更新当前tree_index位置的值
123 | self._tree[tree_index] = self._merger(self._tree[left_tree_index], self._tree[right_tree_index])
124 |
125 | def __str__(self):
126 | result = []
127 | result.append('[')
128 | for i in range(len(self._tree)):
129 | result.append(str(self._tree[i]))
130 | if i < len(self._tree) - 1:
131 | result.append(', ')
132 | result.append(']')
133 | return ''.join(result)
134 |
135 |
136 | def merger(value1, value2):
137 | '''
138 | merger函数,返回value1和value2两数之和
139 | '''
140 | return value1 + value2
141 |
142 |
143 | def segmrent_tree_test(segment_tree):
144 | '''
145 | 测试SegmentTree代码书写是否正确
146 | '''
147 | print(segment_tree)
148 | print(segment_tree.query(3, 5))
149 | segment_tree.set(2, 10)
150 | print(segment_tree)
151 | print(segment_tree.query(2, 5))
152 |
153 |
154 | if __name__ == "__main__":
155 | data = [1, -2, 9, -4, 8, -3, -8]
156 | segment_tree = SegmentTree(data, merger)
157 | segmrent_tree_test(segment_tree)
158 |
--------------------------------------------------------------------------------
/Set/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Set/__init__.py
--------------------------------------------------------------------------------
/Set/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Set/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/Set/__pycache__/set_base.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Set/__pycache__/set_base.cpython-36.pyc
--------------------------------------------------------------------------------
/Set/bst_set.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--06--集合Set(基于二分搜索树BST实现)
3 | '''
4 | import time
5 | from Set.set_base import SetBase
6 | from Binary_Search_Tree.BST import BST
7 |
8 | __author__ = 'Yan'
9 | __date__ = '2018/3/17 15:42'
10 |
11 |
12 | class BSTSet(SetBase):
13 | '''
14 | 数据结构--06--集合Set(基于二分搜索树BST实现)
15 | '''
16 | def __init__(self):
17 | self.bst = BST()
18 |
19 | def get_size(self):
20 | return self.bst.get_size()
21 |
22 | def is_empty(self):
23 | return self.bst.is_empty()
24 |
25 | def add(self, value):
26 | self.bst.add(value)
27 |
28 | def remove(self, value):
29 | self.bst.remove(value)
30 |
31 | def contains(self, value):
32 | return self.bst.contains(value)
33 |
34 |
35 | def bst_set_test(bst_set):
36 | '''
37 | 测试BSTSet是否书写正确
38 | '''
39 | with open('shakespeare.txt', 'r') as f:
40 | words = f.read()
41 | words = words.split()
42 |
43 | start_time = time.time()
44 | for word in words:
45 | bst_set.add(word)
46 | print('total words: ', len(words))
47 | print("unique words: ", bst_set.get_size())
48 | print("contains word 'This': ", bst_set.contains('This'))
49 | print('total time: {} seconds'.format(time.time() - start_time))
50 |
51 |
52 | if __name__ == '__main__':
53 | bst_set = BSTSet()
54 | bst_set_test(bst_set)
55 |
--------------------------------------------------------------------------------
/Set/linked_list_set.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--06--集合Set(基于链表LinkedList实现)
3 | '''
4 | import time
5 | from Set.set_base import SetBase
6 | from Linked_List.linked_list import LinkedList
7 |
8 | __author__ = 'Yan'
9 | __date__ = '2018/3/17 15:42'
10 |
11 |
12 | class LinkedListSet(SetBase):
13 | '''
14 | 数据结构--06--集合Set(基于链表LinkedList实现)
15 | '''
16 | def __init__(self):
17 | self._list = LinkedList()
18 |
19 | def get_size(self):
20 | return self._list.get_size()
21 |
22 | def is_empty(self):
23 | return self._list.is_empty()
24 |
25 | def contains(self, value):
26 | return self._list.contains(value)
27 |
28 | def add(self, value):
29 | if self.contains(value):
30 | return
31 | self._list.add_first(value)
32 |
33 | def remove(self, value):
34 | self._list.remove_element(value)
35 |
36 |
37 | def linked_list_set_test(linked_list_set):
38 | '''
39 | 测试LinkedListSet是否书写正确
40 | '''
41 | with open('shakespeare.txt', 'r') as f:
42 | words = f.read()
43 | words = words.split()
44 |
45 | start_time = time.time()
46 | for word in words:
47 | linked_list_set.add(word)
48 | print('total words: ', len(words))
49 | print("unique words: ", linked_list_set.get_size())
50 | print("contains word 'This': ", linked_list_set.contains('This'))
51 | print('total time: {} seconds'.format(time.time() - start_time))
52 |
53 |
54 | if __name__ == '__main__':
55 | linked_list_set = LinkedListSet()
56 | linked_list_set_test(linked_list_set)
57 |
--------------------------------------------------------------------------------
/Set/set_base.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--06--集合Set需要实现的方法
3 | '''
4 | import abc
5 |
6 | __author__ = 'Yan'
7 | __date__ = '2018/3/17 15:42'
8 |
9 |
10 | class SetBase(metaclass=abc.ABCMeta):
11 | '''
12 | 继承SetBase需要实现的方法,即集合Set需要实现的方法
13 | '''
14 | @abc.abstractmethod
15 | def add(self, value):
16 | '''
17 | 向集合Set中添加元素value
18 | '''
19 | pass
20 |
21 | @abc.abstractmethod
22 | def remove(self, value):
23 | '''
24 | 从集合Set中删除元素value
25 | '''
26 | pass
27 |
28 | @abc.abstractmethod
29 | def contains(self, value):
30 | '''
31 | 查询集合Set中是否包含value,包含返回True,否则返回False
32 | '''
33 | pass
34 |
35 | @abc.abstractmethod
36 | def get_size(self):
37 | '''
38 | 返回集合Set中元素的个数
39 | '''
40 | pass
41 |
42 | @abc.abstractmethod
43 | def is_empty(self):
44 | '''
45 | 判断集合Set是否为空
46 | '''
47 | pass
48 |
--------------------------------------------------------------------------------
/Stack/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Stack/__init__.py
--------------------------------------------------------------------------------
/Stack/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Stack/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/Stack/__pycache__/stack_base.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Stack/__pycache__/stack_base.cpython-36.pyc
--------------------------------------------------------------------------------
/Stack/array_stack.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--04--栈(基于队列Array实现)
3 | '''
4 | from Array.array import Array
5 | from Stack.stack_base import StackBase
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2018/11/19 20:01'
9 |
10 |
11 | class ArrayStack(StackBase):
12 | '''
13 | 数据结构--03--栈(基于队列Array实现)
14 | '''
15 | def __init__(self, capacity=10):
16 | self.array = Array(capacity=capacity)
17 |
18 | def get_size(self):
19 | '''
20 | 获取栈中元素个数
21 | '''
22 | return self.array.get_size()
23 |
24 | def is_empty(self):
25 | '''
26 | 判断栈是否为空
27 | '''
28 | return self.array.is_empty()
29 |
30 | def push(self, value):
31 | '''
32 | 入栈,往栈中插入值为value的元素
33 | '''
34 | self.array.add_last(value)
35 |
36 | def pop(self):
37 | '''
38 | 出栈,从栈中删除栈顶元素
39 | '''
40 | return self.array.remove_last()
41 |
42 | def top(self):
43 | '''
44 | 返回栈顶元素的值
45 | '''
46 | return self.array.get_last()
47 |
48 | def get_capacity(self):
49 | '''
50 | 获取栈的空间容量
51 | '''
52 | return self.array.get_capacity()
53 |
54 |
55 | def array_stack_test():
56 | '''
57 | 测试栈代码是否正确
58 | '''
59 | stack = ArrayStack()
60 | print(stack.is_empty())
61 | for i in range(10):
62 | stack.push(i)
63 |
64 | print(stack.get_size())
65 | print(stack.get_capacity())
66 | print(stack.is_empty())
67 | print(stack.pop())
68 | print(stack.pop())
69 | print(stack.top())
70 | print(stack.get_size())
71 |
72 |
73 | if __name__ == "__main__":
74 | array_stack_test()
75 |
--------------------------------------------------------------------------------
/Stack/linked_list_stack.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--04--栈(基于LinkedList实现)
3 | '''
4 | from Linked_List.linked_list import LinkedList
5 | from Stack.stack_base import StackBase
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2018/11/19 22:49'
9 |
10 |
11 | class LinkedListStack(StackBase):
12 | '''
13 | 数据结构--03--栈(基于LinkedList实现)
14 | '''
15 | def __init__(self):
16 | self._linked_list = LinkedList()
17 |
18 | def get_size(self):
19 | return self._linked_list.size
20 |
21 | def is_empty(self):
22 | return self._linked_list.is_empty()
23 |
24 | def push(self, value):
25 | self._linked_list.add_last(value)
26 |
27 | def pop(self):
28 | return self._linked_list.remove_last()
29 |
30 | def top(self):
31 | return self._linked_list.get_last()
32 |
33 |
34 | def linked_list_stack_test():
35 | stack = LinkedListStack()
36 | print(stack.is_empty())
37 | for i in range(10):
38 | stack.push(i)
39 |
40 | print(stack.get_size())
41 | print(stack.is_empty())
42 | print(stack.pop())
43 | print(stack.pop())
44 | print(stack.top())
45 | print(stack.get_size())
46 |
47 |
48 | if __name__ == "__main__":
49 | linked_list_stack_test()
50 |
--------------------------------------------------------------------------------
/Stack/stack_base.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--04--栈需要实现的方法(利用metaclass)
3 | '''
4 | import abc
5 |
6 | __author__ = 'Yan'
7 | __date__ = '2018/11/19 22:41'
8 |
9 |
10 | class StackBase(metaclass=abc.ABCMeta):
11 | '''
12 | 继承StackBase需要实现的方法,即栈所需实现的方法
13 | '''
14 |
15 | @abc.abstractmethod
16 | def get_size(self):
17 | '''
18 | 获取栈中元素个数
19 | '''
20 | pass
21 |
22 | @abc.abstractmethod
23 | def is_empty(self):
24 | '''
25 | 判断栈是否为空
26 | '''
27 | pass
28 |
29 | @abc.abstractmethod
30 | def push(self, value):
31 | '''
32 | 入栈,往栈中插入值为value的元素
33 | '''
34 | pass
35 |
36 | @abc.abstractmethod
37 | def pop(self):
38 | '''
39 | 出栈,从栈中删除栈顶元素
40 | '''
41 | pass
42 |
43 | @abc.abstractmethod
44 | def top(self):
45 | '''
46 | 返回栈顶元素的值
47 | '''
48 | pass
49 |
--------------------------------------------------------------------------------
/Trie/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/Trie/__init__.py
--------------------------------------------------------------------------------
/Trie/trie.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--10--Trie(字典树/前缀树)
3 | '''
4 |
5 | __author__ = 'Yan'
6 | __date__ = '2019/3/18 16:47'
7 |
8 |
9 | class Trie:
10 | '''
11 | 数据结构--10--Trie(字典树/前缀树)
12 | '''
13 | class _Node:
14 | def __init__(self, is_word=False):
15 | self.is_word = is_word
16 | self.next = [None] * 26
17 |
18 | def __init__(self):
19 | self._root = self._Node()
20 | self._size = 0
21 |
22 | def get_size(self):
23 | '''
24 | 返回Trie中单词的个数
25 | '''
26 | return self._size
27 |
28 | def add(self, word):
29 | '''
30 | 向Trie中添加一个单词word
31 | '''
32 | cur = self._root
33 | for letter in word:
34 | # 获取字母letter在next中的index,next中包含26个字母
35 | index = ord(letter.lower()) - ord('a')
36 |
37 | # 如果letter所在的index为None,则新创建一个Node
38 | if cur.next[index] is None:
39 | cur.next[index] = self._Node()
40 | cur = cur.next[index]
41 |
42 | if cur.is_word is False:
43 | cur.is_word = True
44 | self._size += 1
45 |
46 | def contains(self, word):
47 | '''
48 | 查询Trie中是否包含单词word,包含则返回True,否则返回False
49 | '''
50 | cur = self._root
51 | for letter in word:
52 | index = ord(letter.lower()) - ord('a')
53 | if cur.next[index] is None:
54 | return False
55 | cur = cur.next[index]
56 |
57 | return cur.is_word
58 |
59 | def is_prefix(self, prefix):
60 | '''
61 | 查询Trie中是否存在单词是以prefix为前缀,存在返回True,否则返回False
62 | '''
63 | cur = self._root
64 | for letter in prefix:
65 | index = ord(letter.lower()) - ord('a')
66 | if cur.next[index] is None:
67 | return False
68 | cur = cur.next[index]
69 | return True
70 |
71 |
72 | def trie_test(trie):
73 | '''
74 | 测试Trie代码是否书写正确
75 | '''
76 | words = ['liuyue', 'qiyue', 'bayue', 'jiuyue', 'shiyue', 'bayuechangan']
77 | for word in words:
78 | trie.add(word)
79 |
80 | print("contains shiyue: ", trie.contains('shiyue'))
81 | print('contains shi: ', trie.contains('shi'))
82 | print('contains panda: ', trie.contains('panda'))
83 | print('contains prefix shi: ', trie.is_prefix('shi'))
84 |
85 |
86 | if __name__ == "__main__":
87 | trie = Trie()
88 | trie_test(trie)
89 |
--------------------------------------------------------------------------------
/UnionFind/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/UnionFind/__init__.py
--------------------------------------------------------------------------------
/UnionFind/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/UnionFind/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/UnionFind/__pycache__/unionfind_base.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/UnionFind/__pycache__/unionfind_base.cpython-36.pyc
--------------------------------------------------------------------------------
/UnionFind/unionfind.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--11--UnionFind(并查集)
3 | '''
4 | import time
5 | from random import randint
6 | from UnionFind.unionfind_base import UnionFindBase
7 |
8 | __author__ = 'Yan'
9 | __date__ = '2019/3/18 16:47'
10 |
11 |
12 | class UnionFind1(UnionFindBase):
13 | '''
14 | 数据结构--11--UnionFind(并查集)--> Quick Find
15 | '''
16 | def __init__(self, size):
17 | self._id = [i for i in range(size)]
18 |
19 | def is_connected(self, p, q):
20 | '''
21 | O(1)的时间复制度
22 | '''
23 | return self._find(p) == self._find(q)
24 |
25 | def union_elements(self, p, q):
26 | '''
27 | O(n)的时间复杂度
28 | '''
29 | pid = self._find(p)
30 | qid = self._find(q)
31 | if pid == qid:
32 | return
33 | for i in range(self.get_size()):
34 | if self._id[i] == pid:
35 | self._id[i] = qid
36 |
37 | def get_size(self):
38 | return len(self._id)
39 |
40 | def _find(self, p):
41 | '''
42 | 查找元素p所对应的集合编号,O(1)的时间复杂度
43 | '''
44 | if p < 0 or p >= self.get_size():
45 | raise IndexError("index is illegal.")
46 | return self._id[p]
47 |
48 |
49 | class UnionFind2(UnionFindBase):
50 | '''
51 | 数据结构--11--UnionFind(并查集)--> Quick Union(有可能会退化成链表)
52 | 是一棵棵树的形式,孩子指向父亲节点
53 | '''
54 | def __init__(self, size):
55 | '''
56 | parent[i] = j 表示 i 指向 j
57 | '''
58 | self._parent = [i for i in range(size)]
59 |
60 | def is_connected(self, p, q):
61 | return self._find(p) == self._find(q)
62 |
63 | def union_elements(self, p, q):
64 | '''
65 | O(h)的时间复杂度,h为p和q节点所在树的深度
66 | '''
67 | # p所在树的根节点为p_root
68 | p_root = self._find(p)
69 | # q所在树的根节点为q_root
70 | q_root = self._find(q)
71 |
72 | if p_root == q_root:
73 | return
74 | self._parent[p_root] = q_root
75 |
76 | def get_size(self):
77 | return len(self._parent)
78 |
79 | def _find(self, p):
80 | '''
81 | 查找元素p所对应的集合编号,O(h)的时间复杂度,h为p节点所在树的深度
82 | '''
83 | if p < 0 or p >= self.get_size():
84 | raise IndexError("index is illegal.")
85 |
86 | # 根节点的特点: parent[p] == p
87 | while p != self._parent[p]:
88 | # 不断去查询自己的父亲节点, 直到到达根节点
89 | p = self._parent[p]
90 |
91 | return p
92 |
93 |
94 | class UnionFind3(UnionFindBase):
95 | '''
96 | 数据结构--11--UnionFind(并查集)--> Size Optimize(对UnionFind3的优化,防止退化成链表)
97 | '''
98 | def __init__(self, size):
99 | '''
100 | parent[i] = j 表示 i 指向 j
101 | '''
102 | self._parent = [i for i in range(size)]
103 |
104 | # 维护一个字典,记录i节点所在树的元素个数
105 | self._count = {}
106 | for i in range(len(self._parent)):
107 | self._count[i] = 1
108 |
109 | def is_connected(self, p, q):
110 | return self._find(p) == self._find(q)
111 |
112 | def union_elements(self, p, q):
113 | '''
114 | O(h)的时间复杂度,h为p和q节点所在树的深度
115 | '''
116 | # p所在树的根节点为p_root
117 | p_root = self._find(p)
118 | # q所在树的根节点为q_root
119 | q_root = self._find(q)
120 |
121 | if p_root == q_root:
122 | return
123 |
124 | if self._count[p_root] < self._count[q_root]:
125 | self._parent[p_root] = q_root
126 | self._count[q_root] += self._count[p_root]
127 | del self._count[p_root]
128 | else:
129 | self._parent[q_root] = p_root
130 | self._count[p_root] += self._count[q_root]
131 | del self._count[q_root]
132 |
133 | def get_size(self):
134 | return len(self._parent)
135 |
136 | def _find(self, p):
137 | '''
138 | 查找元素p所对应的集合编号,O(h)的时间复杂度,h为p节点所在树的深度
139 | '''
140 | if p < 0 or p >= self.get_size():
141 | raise IndexError("index is illegal.")
142 |
143 | # 根节点的特点: parent[p] == p
144 | while p != self._parent[p]:
145 | # 不断去查询自己的父亲节点, 直到到达根节点
146 | p = self._parent[p]
147 |
148 | return p
149 |
150 |
151 | class UnionFind4(UnionFindBase):
152 | '''
153 | 数据结构--11--UnionFind(并查集)--> Rank Optimize(对UnionFind3的优化)
154 | '''
155 | def __init__(self, size):
156 | '''
157 | parent[i] = j 表示 i 指向 j
158 | '''
159 | self._parent = [i for i in range(size)]
160 |
161 | # 维护一个字典,记录i节点所在树的深度h
162 | self._rank = {}
163 | for i in range(len(self._parent)):
164 | self._rank[i] = 1
165 |
166 | def is_connected(self, p, q):
167 | return self._find(p) == self._find(q)
168 |
169 | def union_elements(self, p, q):
170 | '''
171 | O(h)的时间复杂度,h为p和q节点所在树的深度
172 | '''
173 | # p所在树的根节点为p_root
174 | p_root = self._find(p)
175 | # q所在树的根节点为q_root
176 | q_root = self._find(q)
177 |
178 | if p_root == q_root:
179 | return
180 |
181 | if self._rank[p_root] < self._rank[q_root]:
182 | self._parent[p_root] = q_root
183 | elif self._rank[p_root] > self._rank[q_root]:
184 | self._parent[q_root] = p_root
185 | else:
186 | self._parent[p_root] = q_root
187 | self._rank[q_root] += 1
188 |
189 | def get_size(self):
190 | return len(self._parent)
191 |
192 | def _find(self, p):
193 | '''
194 | 查找元素p所对应的集合编号,O(h)的时间复杂度,h为p节点所在树的深度
195 | '''
196 | if p < 0 or p >= self.get_size():
197 | raise IndexError("index is illegal.")
198 |
199 | # 根节点的特点: parent[p] == p
200 | while p != self._parent[p]:
201 | # 不断去查询自己的父亲节点, 直到到达根节点
202 | p = self._parent[p]
203 |
204 | return p
205 |
206 |
207 | class UnionFind5(UnionFindBase):
208 | '''
209 | 数据结构--11--UnionFind(并查集)--> Path Compression(路径压缩,对UnionFind4的优化)
210 | '''
211 | def __init__(self, size):
212 | '''
213 | parent[i] = j 表示 i 指向 j
214 | '''
215 | self._parent = [i for i in range(size)]
216 |
217 | # 维护一个字典,记录i节点所在树的深度h
218 | self._rank = {}
219 | for i in range(len(self._parent)):
220 | self._rank[i] = 1
221 |
222 | def is_connected(self, p, q):
223 | return self._find(p) == self._find(q)
224 |
225 | def union_elements(self, p, q):
226 | '''
227 | O(h)的时间复杂度,h为p和q节点所在树的深度
228 | '''
229 | # p所在树的根节点为p_root
230 | p_root = self._find(p)
231 | # q所在树的根节点为q_root
232 | q_root = self._find(q)
233 |
234 | if p_root == q_root:
235 | return
236 |
237 | if self._rank[p_root] < self._rank[q_root]:
238 | self._parent[p_root] = q_root
239 | elif self._rank[p_root] > self._rank[q_root]:
240 | self._parent[q_root] = p_root
241 | else:
242 | self._parent[p_root] = q_root
243 | self._rank[q_root] += 1
244 |
245 | def get_size(self):
246 | return len(self._parent)
247 |
248 | def _find(self, p):
249 | '''
250 | 查找元素p所对应的集合编号,O(h)的时间复杂度,h为p节点所在树的深度
251 | '''
252 | if p < 0 or p >= self.get_size():
253 | raise IndexError("index is illegal.")
254 |
255 | # 根节点的特点: parent[p] == p
256 | while p != self._parent[p]:
257 | # 路径压缩
258 | self._parent[p] = self._parent[self._parent[p]]
259 | # 不断去查询自己的父亲节点, 直到到达根节点
260 | p = self._parent[p]
261 |
262 | return p
263 |
264 |
265 | class UnionFind6(UnionFindBase):
266 | '''
267 | 数据结构--11--UnionFind(并查集)--> Path Compression(路径压缩,对UnionFind5的优化)
268 | '''
269 | def __init__(self, size):
270 | '''
271 | parent[i] = j 表示 i 指向 j
272 | '''
273 | self._parent = [i for i in range(size)]
274 |
275 | # 维护一个字典,记录i节点所在树的深度h
276 | self._rank = {}
277 | for i in range(len(self._parent)):
278 | self._rank[i] = 1
279 |
280 | def is_connected(self, p, q):
281 | return self._find(p) == self._find(q)
282 |
283 | def union_elements(self, p, q):
284 | '''
285 | O(h)的时间复杂度,h为p和q节点所在树的深度
286 | '''
287 | # p所在树的根节点为p_root
288 | p_root = self._find(p)
289 | # q所在树的根节点为q_root
290 | q_root = self._find(q)
291 |
292 | if p_root == q_root:
293 | return
294 |
295 | if self._rank[p_root] < self._rank[q_root]:
296 | self._parent[p_root] = q_root
297 | elif self._rank[p_root] > self._rank[q_root]:
298 | self._parent[q_root] = p_root
299 | else:
300 | self._parent[p_root] = q_root
301 | self._rank[q_root] += 1
302 |
303 | def get_size(self):
304 | return len(self._parent)
305 |
306 | def _find(self, p):
307 | '''
308 | 查找元素p所对应的集合编号,O(h)的时间复杂度,h为p节点所在树的深度
309 | '''
310 | if p < 0 or p >= self.get_size():
311 | raise IndexError("index is illegal.")
312 |
313 | # 根节点的特点: parent[p] == p
314 | if p != self._parent[p]:
315 | # 使用递归实现路径压缩,使得所有节点的深度最大为2
316 | self._parent[p] = self._find(self._parent[p])
317 |
318 | return self._parent[p]
319 |
320 |
321 | def union_find_test(union_find, size, m):
322 | '''
323 | 测试UnionFind代码是否书写正确,以及性能测试
324 | '''
325 | start_time = time.time()
326 | for i in range(m):
327 | a = randint(0, size-1)
328 | b = randint(0, size-1)
329 | union_find.union_elements(a, b)
330 |
331 | for i in range(m):
332 | a = randint(0, size-1)
333 | b = randint(0, size-1)
334 | union_find.is_connected(a, b)
335 |
336 | print("UnionFind: ", time.time() - start_time)
337 |
338 |
339 | if __name__ == "__main__":
340 | size = 10000
341 | m = 10000
342 | union_find1 = UnionFind1(size)
343 | union_find2 = UnionFind2(size)
344 | union_find3 = UnionFind3(size)
345 | union_find4 = UnionFind4(size)
346 | union_find5 = UnionFind5(size)
347 | union_find6 = UnionFind6(size)
348 | union_find_test(union_find1, size, m)
349 | union_find_test(union_find2, size, m)
350 | union_find_test(union_find3, size, m)
351 | union_find_test(union_find4, size, m)
352 | union_find_test(union_find5, size, m)
353 | union_find_test(union_find6, size, m)
354 |
--------------------------------------------------------------------------------
/UnionFind/unionfind_base.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--11--UnionFind(并查集)
3 | '''
4 | import abc
5 |
6 | __author__ = 'Yan'
7 | __date__ = '2019/3/18 16:47'
8 |
9 |
10 | class UnionFindBase(metaclass=abc.ABCMeta):
11 | '''
12 | 数据结构--11--UnionFind(并查集)
13 | '''
14 | @abc.abstractmethod
15 | def is_connected(self, p, q):
16 | '''
17 | 判断元素p和q是否相连
18 | '''
19 | pass
20 |
21 | def union_elements(self, p, q):
22 | '''
23 | 将两个元素p和q相连接
24 | '''
25 | pass
26 |
27 | def get_size(self):
28 | '''
29 | 返回UnionFind中的元素个数
30 | '''
31 | pass
32 |
--------------------------------------------------------------------------------
/_Queue/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/_Queue/__init__.py
--------------------------------------------------------------------------------
/_Queue/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/_Queue/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/_Queue/__pycache__/array_queue.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/_Queue/__pycache__/array_queue.cpython-36.pyc
--------------------------------------------------------------------------------
/_Queue/__pycache__/queue_base.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yanxueshan/Python-DataStructur/376ef084f57148b2953bb65f27bbf8a928f09837/_Queue/__pycache__/queue_base.cpython-36.pyc
--------------------------------------------------------------------------------
/_Queue/array_queue.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--03--队列(基于数组Array实现)
3 | '''
4 | from Array.array import Array
5 | from _Queue.queue_base import QueueBase
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2018/11/19 20:26'
9 |
10 |
11 | class ArrayQueue(QueueBase):
12 | '''
13 | 数据结构--03--队列(基于数组Array实现)
14 | '''
15 | def __init__(self, capacity=10):
16 | self._array = Array(capacity=capacity)
17 |
18 | def get_size(self):
19 | '''
20 | 获取队列中元素个数
21 | '''
22 | return self._array.get_size()
23 |
24 | def is_empty(self):
25 | '''
26 | 判断队列是否为空
27 | '''
28 | return self._array.is_empty()
29 |
30 | def enqueue(self, value):
31 | '''
32 | 入队,往队列中插入值为value的元素
33 | '''
34 | self._array.add_last(value)
35 |
36 | def dequeue(self):
37 | '''
38 | 出队,从队列中删除队首元素,并返回队首元素的值
39 | '''
40 | return self._array.remove_first()
41 |
42 | def get_front(self):
43 | '''
44 | 获取队首的元素值
45 | '''
46 | return self._array.get_first()
47 |
48 | def get_capacity(self):
49 | '''
50 | 返回队列的空间容量
51 | '''
52 | return self._array.get_capacity()
53 |
54 |
55 | def array_queue_test():
56 | '''
57 | 测试队列代码是否正确
58 | '''
59 | queue = ArrayQueue()
60 | for i in range(10):
61 | queue.enqueue(i)
62 | print(queue.get_size())
63 | print(queue.dequeue())
64 | print(queue.dequeue())
65 | print(queue.get_front())
66 |
67 |
68 | if __name__ == "__main__":
69 | array_queue_test()
70 |
--------------------------------------------------------------------------------
/_Queue/linked_list_queue.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--03--队列(基于链表LinkedList实现)
3 | '''
4 | from Linked_List.linked_list import LinkedList
5 | from _Queue.queue_base import QueueBase
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2018/11/19 22:39'
9 |
10 |
11 | class LinkedListQueue(QueueBase):
12 | '''
13 | 数据结构--03--队列(基于链表LinkedList实现)
14 | '''
15 | def __init__(self):
16 | self._linked_list = LinkedList()
17 |
18 | def get_size(self):
19 | return self._linked_list.size
20 |
21 | def is_empty(self):
22 | return self._linked_list.is_empty()
23 |
24 | def enqueue(self, value):
25 | self._linked_list.add_last(value)
26 |
27 | def dequeue(self):
28 | return self._linked_list.remove_first()
29 |
30 | def get_front(self):
31 | return self._linked_list.get_first()
32 |
33 |
34 | def linked_list_queue_test():
35 | '''
36 | 测试队列代码是否正确
37 | '''
38 | queue = LinkedListQueue()
39 | for i in range(10):
40 | queue.enqueue(i)
41 | print(queue.get_size())
42 | print(queue.dequeue())
43 | print(queue.dequeue())
44 | print(queue.get_front())
45 |
46 |
47 | if __name__ == "__main__":
48 | linked_list_queue_test()
49 |
--------------------------------------------------------------------------------
/_Queue/loop_queue.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--03--循环队列
3 | '''
4 | from _Queue.queue_base import QueueBase
5 |
6 | __author__ = 'Yan'
7 | __date__ = '2018/11/19 20:26'
8 |
9 |
10 | class LoopQueue(QueueBase):
11 | '''
12 | 数据结构--03--循环队列
13 | '''
14 | # capacity = 10时,size最大为9,会浪费一个空间
15 | def __init__(self, capacity=10):
16 | self._data = [None] * (capacity + 1)
17 | self.front = 0
18 | self.tail = 0
19 | self.size = 0
20 |
21 | def get_size(self):
22 | return self.size
23 |
24 | def is_empty(self):
25 | '''
26 | 当self.front == self.tail时循环队列也为空
27 | '''
28 | return self.size == 0
29 |
30 | # 入队,当front == tail时,队列为空;当(tail + 1) % capacity == front时为满
31 | # tail 指向队尾最后一个空的位置
32 | # front 指向队首
33 | def enqueue(self, value):
34 | if (self.tail + 1) % len(self._data) == self.front:
35 | self._resize(2 * self.get_capacity())
36 |
37 | self._data[self.tail] = value
38 | self.tail = (self.tail + 1) % len(self._data)
39 | self.size += 1
40 |
41 | def dequeue(self):
42 | if self.size == 0:
43 | raise ValueError("dequeue failed, queue is empty")
44 |
45 | ret = self._data[self.front]
46 | self._data[self.front] = None
47 | self.front = (self.front + 1) % len(self._data)
48 | self.size -= 1
49 |
50 | if self.size < self.get_capacity() // 4 and self.get_capacity() // 2 != 0:
51 | self._resize(self.get_capacity() // 2)
52 |
53 | return ret
54 |
55 | def get_front(self):
56 | if self.size == 0:
57 | raise ValueError("dequeue failed, queue is empty")
58 | return self._data[self.front]
59 |
60 | def get_capacity(self):
61 | '''
62 | 获取队列的空间容量
63 | '''
64 | return len(self._data) - 1
65 |
66 | def _resize(self, new_capacity):
67 | '''
68 | 将队列的容量设置为new_capacity
69 | '''
70 | new_data = [None] * (new_capacity + 1)
71 | for i in range(self.size):
72 | new_data[i] = self._data[(self.front + i) % len(self._data)]
73 | self._data = new_data
74 | self.front = 0
75 | self.tail = self.size
76 |
77 |
78 | def loop_queue_test():
79 | '''
80 | 测试循环队列代码是否正确
81 | '''
82 | queue = LoopQueue()
83 | for i in range(10):
84 | queue.enqueue(i)
85 | print("capacity: %d" % queue.get_capacity())
86 | print("size: %d" % queue.get_size())
87 | queue.enqueue("a")
88 | print("capacity: %d" % queue.get_capacity())
89 | print("size: %d" % queue.get_size())
90 | print(queue.dequeue())
91 | print(queue.dequeue())
92 | print(queue.get_front())
93 |
94 | for i in range(8):
95 | queue.dequeue()
96 | print("capacity: %d" % queue.get_capacity())
97 | print("size: %d" % queue.get_size())
98 |
99 |
100 | if __name__ == "__main__":
101 | loop_queue_test()
102 |
--------------------------------------------------------------------------------
/_Queue/priority_queue.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--03--优先级队列(基于最大堆MaxHeap实现)
3 | '''
4 | from _Queue.queue_base import QueueBase
5 | from MaxHeap.max_heap import MaxHeap
6 |
7 | __author__ = 'Yan'
8 | __date__ = '2019/3/18 14:41'
9 |
10 |
11 | class PriorityQueue(QueueBase):
12 | '''
13 | 数据结构--03--优先级队列(基于最大堆MaxHeap实现)
14 | '''
15 | def __init__(self):
16 | self._data = MaxHeap()
17 |
18 | def get_size(self):
19 | return self._data.get_size()
20 |
21 | def is_empty(self):
22 | return self._data.is_empty()
23 |
24 | def enqueue(self, value):
25 | self._data.add(value)
26 |
27 | def dequeue(self):
28 | return self._data.extract_max()
29 |
30 | def get_front(self):
31 | return self._data.find_max()
32 |
--------------------------------------------------------------------------------
/_Queue/queue_base.py:
--------------------------------------------------------------------------------
1 | '''
2 | 数据结构--03--队列需要实现的方法(利用metaclass)
3 | '''
4 | import abc
5 |
6 | __author__ = 'Yan'
7 | __date__ = '2018/11/19 22:39'
8 |
9 |
10 | class QueueBase(metaclass=abc.ABCMeta):
11 | '''
12 | 继承QueueBase需要实现的方法,即队列所需实现的方法
13 | '''
14 |
15 | @abc.abstractmethod
16 | def get_size(self):
17 | '''
18 | 获取队列中元素个数
19 | '''
20 | pass
21 |
22 | @abc.abstractmethod
23 | def is_empty(self):
24 | '''
25 | 判断队列是否为空
26 | '''
27 | pass
28 |
29 | @abc.abstractmethod
30 | def enqueue(self, value):
31 | '''
32 | 入队,往队列中插入值为value的元素
33 | '''
34 | pass
35 |
36 | @abc.abstractmethod
37 | def dequeue(self):
38 | '''
39 | 出队,从队列中删除队首元素
40 | '''
41 | pass
42 |
43 | @abc.abstractmethod
44 | def get_front(self):
45 | '''
46 | 获取队首的元素值
47 | '''
48 | pass
49 |
--------------------------------------------------------------------------------