From 56efd99d897c2262417d656fcf297c50439b89df Mon Sep 17 00:00:00 2001 From: shengshijun Date: Wed, 4 Mar 2015 16:18:27 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=E6=9C=80=E8=BF=91=E5=A4=8D=E4=B9=A0?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E7=9A=84=E6=97=B6=E5=80=99=EF=BC=8C=E5=8F=91?= =?UTF-8?q?=E7=8E=B0=E6=9C=89=E4=B8=8D=E5=B0=91=E5=9C=B0=E6=96=B9=E6=98=AF?= =?UTF-8?q?=E6=9C=89=E9=97=AE=E9=A2=98=E7=9A=84=E3=80=82=E6=89=80=E4=BB=A5?= =?UTF-8?q?=E6=88=91=E6=89=93=E7=AE=97=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- {clrs => src/clrs}/9/9-2(b).py | 0 {clrs => src/clrs}/9/9-2(c).py | 0 {divide_conquer => src/clrs/9}/__init__.py | 0 {dynamic => src/clrs}/__init__.py | 0 .../fabo => src/divide_conquer}/__init__.py | 0 .../divide_conquer}/find_max_sublist.py | 0 .../find_max_sublist_without_ recursion.py | 0 .../divide_conquer}/power.py | 0 .../divide_conquer}/yong_matrix.py | 0 {dynamic/lcs => src/dynamic}/__init__.py | 0 .../task => src/dynamic/fabo}/__init__.py | 0 {dynamic => src/dynamic}/fabo/fabo_loop.py | 0 {dynamic => src/dynamic}/fabo/fabo_math.py | 0 {dynamic => src/dynamic}/fabo/fabo_up_down.py | 0 {graph => src/dynamic/lcs}/__init__.py | 0 {dynamic => src/dynamic}/lcs/down_up.py | 0 {dynamic => src/dynamic}/lcs/up_down.py | 0 {dynamic => src/dynamic}/lps/__init__.py | 0 {dynamic => src/dynamic}/lps/down_up.py | 0 {dynamic => src/dynamic}/lps/up_down.py | 0 {greedy => src/dynamic/task}/__init__.py | 0 .../dynamic}/task/max_weighted_action.py | 0 {heap => src/graph}/__init__.py | 0 {graph => src/graph}/general_graph.py | 0 {graph => src/graph}/weighted_graph.py | 0 {lib => src/greedy}/__init__.py | 0 {greedy => src/greedy}/max_task_count.py | 0 {hashtable => src/hashtable}/HashMap.py | 0 .../hashtable}/OpenAddressMap.py | 0 {list => src/hashtable}/__init__.py | 0 {matrix => src/heap}/__init__.py | 0 {heap => src/heap}/max_heap.py | 0 {heap => src/heap}/max_queue.py | 0 {number_theory => src/lib}/__init__.py | 0 {lib => src/lib}/queue.py | 0 {lib => src/lib}/set.py | 0 {lib => src/lib}/stack.py | 0 {string => src/list}/__init__.py | 0 {list => src/list}/linked_list.py | 0 {list => src/list}/mutiarray_linkedlist.py | 0 {list => src/list}/skip_list.py | 0 {list => src/list}/stack.py | 0 {tree => src/matrix}/__init__.py | 0 {matrix => src/matrix}/strassen_matrix.py | 0 src/number_theory/__init__.py | 3 + {number_theory => src/number_theory}/gcd.py | 0 src/queue/__init__.py | 3 + {queue => src/queue}/fifo_queue.py | 0 {queue => src/queue}/list_queue.py | 0 {search => src/search}/__init__.py | 0 {search => src/search}/binary_search.py | 0 .../search}/find_kth_with_middle.py | 0 .../find_middle_of_two_sorted_array.py | 0 {search => src/search}/find_min_max.py | 0 {search => src/search}/find_sum_equals.py | 0 {search => src/search}/random_loop_section.py | 0 {search => src/search}/random_selection.py | 0 {search => src/search}/split_nth.py | 0 ...4\347\244\272\346\204\217\345\233\276.png" | Bin {sort => src/sort}/__init__.py | 0 {sort => src/sort}/bubble_sort.py | 0 {sort => src/sort}/bucketsort.png | Bin {sort => src/sort}/counting_sort.py | 0 {sort => src/sort}/countingsort.png | Bin {sort => src/sort}/fuzzy_space_quick_sort.py | 0 {sort => src/sort}/heap_sort.py | 0 {sort => src/sort}/hoare_quick_sort.py | 0 .../sort}/improve_fuzzy_space_quick_sort.py | 0 {sort => src/sort}/insert_sort.py | 0 {sort => src/sort}/merge_sort.py | 0 {sort => src/sort}/quick_sort.py | 0 {sort => src/sort}/random_quick_sort.py | 0 .../sort}/random_two_partition_quick_sort.py | 0 {sort => src/sort}/recursive_insert_sort.py | 0 {sort => src/sort}/select_sort.py | 0 src/string/__init__.py | 3 + {string => src/string}/kmp.py | 0 {string => src/string}/rabin-karp.py | 0 {string => src/string}/simple.py | 0 {tree => src/tree}/BTree.py | 0 src/tree/__init__.py | 3 + tree/AVLTree.py => src/tree/avltree.py | 0 {tree => src/tree}/binarystree.py | 0 {tree => src/tree}/binarytree.py | 0 {tree => src/tree}/interval_tree.py | 0 {tree => src/tree}/lchild_rbro_tree.py | 0 {tree => src/tree}/order_statistic_tree.py | 0 {tree => src/tree}/red_black_tree.py | 53 +++++++++--------- tree/Tries.py => src/tree/tries.py | 0 89 files changed, 39 insertions(+), 26 deletions(-) rename {clrs => src/clrs}/9/9-2(b).py (100%) rename {clrs => src/clrs}/9/9-2(c).py (100%) rename {divide_conquer => src/clrs/9}/__init__.py (100%) rename {dynamic => src/clrs}/__init__.py (100%) rename {dynamic/fabo => src/divide_conquer}/__init__.py (100%) rename {divide_conquer => src/divide_conquer}/find_max_sublist.py (100%) rename {divide_conquer => src/divide_conquer}/find_max_sublist_without_ recursion.py (100%) rename {divide_conquer => src/divide_conquer}/power.py (100%) rename {divide_conquer => src/divide_conquer}/yong_matrix.py (100%) rename {dynamic/lcs => src/dynamic}/__init__.py (100%) rename {dynamic/task => src/dynamic/fabo}/__init__.py (100%) rename {dynamic => src/dynamic}/fabo/fabo_loop.py (100%) rename {dynamic => src/dynamic}/fabo/fabo_math.py (100%) rename {dynamic => src/dynamic}/fabo/fabo_up_down.py (100%) rename {graph => src/dynamic/lcs}/__init__.py (100%) rename {dynamic => src/dynamic}/lcs/down_up.py (100%) rename {dynamic => src/dynamic}/lcs/up_down.py (100%) rename {dynamic => src/dynamic}/lps/__init__.py (100%) rename {dynamic => src/dynamic}/lps/down_up.py (100%) rename {dynamic => src/dynamic}/lps/up_down.py (100%) rename {greedy => src/dynamic/task}/__init__.py (100%) rename {dynamic => src/dynamic}/task/max_weighted_action.py (100%) rename {heap => src/graph}/__init__.py (100%) rename {graph => src/graph}/general_graph.py (100%) rename {graph => src/graph}/weighted_graph.py (100%) rename {lib => src/greedy}/__init__.py (100%) rename {greedy => src/greedy}/max_task_count.py (100%) rename {hashtable => src/hashtable}/HashMap.py (100%) rename {hashtable => src/hashtable}/OpenAddressMap.py (100%) rename {list => src/hashtable}/__init__.py (100%) rename {matrix => src/heap}/__init__.py (100%) rename {heap => src/heap}/max_heap.py (100%) rename {heap => src/heap}/max_queue.py (100%) rename {number_theory => src/lib}/__init__.py (100%) rename {lib => src/lib}/queue.py (100%) rename {lib => src/lib}/set.py (100%) rename {lib => src/lib}/stack.py (100%) rename {string => src/list}/__init__.py (100%) rename {list => src/list}/linked_list.py (100%) rename {list => src/list}/mutiarray_linkedlist.py (100%) rename {list => src/list}/skip_list.py (100%) rename {list => src/list}/stack.py (100%) rename {tree => src/matrix}/__init__.py (100%) rename {matrix => src/matrix}/strassen_matrix.py (100%) create mode 100644 src/number_theory/__init__.py rename {number_theory => src/number_theory}/gcd.py (100%) create mode 100644 src/queue/__init__.py rename {queue => src/queue}/fifo_queue.py (100%) rename {queue => src/queue}/list_queue.py (100%) rename {search => src/search}/__init__.py (100%) rename {search => src/search}/binary_search.py (100%) rename {search => src/search}/find_kth_with_middle.py (100%) rename {search => src/search}/find_middle_of_two_sorted_array.py (100%) rename {search => src/search}/find_min_max.py (100%) rename {search => src/search}/find_sum_equals.py (100%) rename {search => src/search}/random_loop_section.py (100%) rename {search => src/search}/random_selection.py (100%) rename {search => src/search}/split_nth.py (100%) rename "search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" => "src/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" (100%) rename {sort => src/sort}/__init__.py (100%) rename {sort => src/sort}/bubble_sort.py (100%) rename {sort => src/sort}/bucketsort.png (100%) rename {sort => src/sort}/counting_sort.py (100%) rename {sort => src/sort}/countingsort.png (100%) rename {sort => src/sort}/fuzzy_space_quick_sort.py (100%) rename {sort => src/sort}/heap_sort.py (100%) rename {sort => src/sort}/hoare_quick_sort.py (100%) rename {sort => src/sort}/improve_fuzzy_space_quick_sort.py (100%) rename {sort => src/sort}/insert_sort.py (100%) rename {sort => src/sort}/merge_sort.py (100%) rename {sort => src/sort}/quick_sort.py (100%) rename {sort => src/sort}/random_quick_sort.py (100%) rename {sort => src/sort}/random_two_partition_quick_sort.py (100%) rename {sort => src/sort}/recursive_insert_sort.py (100%) rename {sort => src/sort}/select_sort.py (100%) create mode 100644 src/string/__init__.py rename {string => src/string}/kmp.py (100%) rename {string => src/string}/rabin-karp.py (100%) rename {string => src/string}/simple.py (100%) rename {tree => src/tree}/BTree.py (100%) create mode 100644 src/tree/__init__.py rename tree/AVLTree.py => src/tree/avltree.py (100%) rename {tree => src/tree}/binarystree.py (100%) rename {tree => src/tree}/binarytree.py (100%) rename {tree => src/tree}/interval_tree.py (100%) rename {tree => src/tree}/lchild_rbro_tree.py (100%) rename {tree => src/tree}/order_statistic_tree.py (100%) rename {tree => src/tree}/red_black_tree.py (88%) rename tree/Tries.py => src/tree/tries.py (100%) diff --git a/clrs/9/9-2(b).py b/src/clrs/9/9-2(b).py similarity index 100% rename from clrs/9/9-2(b).py rename to src/clrs/9/9-2(b).py diff --git a/clrs/9/9-2(c).py b/src/clrs/9/9-2(c).py similarity index 100% rename from clrs/9/9-2(c).py rename to src/clrs/9/9-2(c).py diff --git a/divide_conquer/__init__.py b/src/clrs/9/__init__.py similarity index 100% rename from divide_conquer/__init__.py rename to src/clrs/9/__init__.py diff --git a/dynamic/__init__.py b/src/clrs/__init__.py similarity index 100% rename from dynamic/__init__.py rename to src/clrs/__init__.py diff --git a/dynamic/fabo/__init__.py b/src/divide_conquer/__init__.py similarity index 100% rename from dynamic/fabo/__init__.py rename to src/divide_conquer/__init__.py diff --git a/divide_conquer/find_max_sublist.py b/src/divide_conquer/find_max_sublist.py similarity index 100% rename from divide_conquer/find_max_sublist.py rename to src/divide_conquer/find_max_sublist.py diff --git a/divide_conquer/find_max_sublist_without_ recursion.py b/src/divide_conquer/find_max_sublist_without_ recursion.py similarity index 100% rename from divide_conquer/find_max_sublist_without_ recursion.py rename to src/divide_conquer/find_max_sublist_without_ recursion.py diff --git a/divide_conquer/power.py b/src/divide_conquer/power.py similarity index 100% rename from divide_conquer/power.py rename to src/divide_conquer/power.py diff --git a/divide_conquer/yong_matrix.py b/src/divide_conquer/yong_matrix.py similarity index 100% rename from divide_conquer/yong_matrix.py rename to src/divide_conquer/yong_matrix.py diff --git a/dynamic/lcs/__init__.py b/src/dynamic/__init__.py similarity index 100% rename from dynamic/lcs/__init__.py rename to src/dynamic/__init__.py diff --git a/dynamic/task/__init__.py b/src/dynamic/fabo/__init__.py similarity index 100% rename from dynamic/task/__init__.py rename to src/dynamic/fabo/__init__.py diff --git a/dynamic/fabo/fabo_loop.py b/src/dynamic/fabo/fabo_loop.py similarity index 100% rename from dynamic/fabo/fabo_loop.py rename to src/dynamic/fabo/fabo_loop.py diff --git a/dynamic/fabo/fabo_math.py b/src/dynamic/fabo/fabo_math.py similarity index 100% rename from dynamic/fabo/fabo_math.py rename to src/dynamic/fabo/fabo_math.py diff --git a/dynamic/fabo/fabo_up_down.py b/src/dynamic/fabo/fabo_up_down.py similarity index 100% rename from dynamic/fabo/fabo_up_down.py rename to src/dynamic/fabo/fabo_up_down.py diff --git a/graph/__init__.py b/src/dynamic/lcs/__init__.py similarity index 100% rename from graph/__init__.py rename to src/dynamic/lcs/__init__.py diff --git a/dynamic/lcs/down_up.py b/src/dynamic/lcs/down_up.py similarity index 100% rename from dynamic/lcs/down_up.py rename to src/dynamic/lcs/down_up.py diff --git a/dynamic/lcs/up_down.py b/src/dynamic/lcs/up_down.py similarity index 100% rename from dynamic/lcs/up_down.py rename to src/dynamic/lcs/up_down.py diff --git a/dynamic/lps/__init__.py b/src/dynamic/lps/__init__.py similarity index 100% rename from dynamic/lps/__init__.py rename to src/dynamic/lps/__init__.py diff --git a/dynamic/lps/down_up.py b/src/dynamic/lps/down_up.py similarity index 100% rename from dynamic/lps/down_up.py rename to src/dynamic/lps/down_up.py diff --git a/dynamic/lps/up_down.py b/src/dynamic/lps/up_down.py similarity index 100% rename from dynamic/lps/up_down.py rename to src/dynamic/lps/up_down.py diff --git a/greedy/__init__.py b/src/dynamic/task/__init__.py similarity index 100% rename from greedy/__init__.py rename to src/dynamic/task/__init__.py diff --git a/dynamic/task/max_weighted_action.py b/src/dynamic/task/max_weighted_action.py similarity index 100% rename from dynamic/task/max_weighted_action.py rename to src/dynamic/task/max_weighted_action.py diff --git a/heap/__init__.py b/src/graph/__init__.py similarity index 100% rename from heap/__init__.py rename to src/graph/__init__.py diff --git a/graph/general_graph.py b/src/graph/general_graph.py similarity index 100% rename from graph/general_graph.py rename to src/graph/general_graph.py diff --git a/graph/weighted_graph.py b/src/graph/weighted_graph.py similarity index 100% rename from graph/weighted_graph.py rename to src/graph/weighted_graph.py diff --git a/lib/__init__.py b/src/greedy/__init__.py similarity index 100% rename from lib/__init__.py rename to src/greedy/__init__.py diff --git a/greedy/max_task_count.py b/src/greedy/max_task_count.py similarity index 100% rename from greedy/max_task_count.py rename to src/greedy/max_task_count.py diff --git a/hashtable/HashMap.py b/src/hashtable/HashMap.py similarity index 100% rename from hashtable/HashMap.py rename to src/hashtable/HashMap.py diff --git a/hashtable/OpenAddressMap.py b/src/hashtable/OpenAddressMap.py similarity index 100% rename from hashtable/OpenAddressMap.py rename to src/hashtable/OpenAddressMap.py diff --git a/list/__init__.py b/src/hashtable/__init__.py similarity index 100% rename from list/__init__.py rename to src/hashtable/__init__.py diff --git a/matrix/__init__.py b/src/heap/__init__.py similarity index 100% rename from matrix/__init__.py rename to src/heap/__init__.py diff --git a/heap/max_heap.py b/src/heap/max_heap.py similarity index 100% rename from heap/max_heap.py rename to src/heap/max_heap.py diff --git a/heap/max_queue.py b/src/heap/max_queue.py similarity index 100% rename from heap/max_queue.py rename to src/heap/max_queue.py diff --git a/number_theory/__init__.py b/src/lib/__init__.py similarity index 100% rename from number_theory/__init__.py rename to src/lib/__init__.py diff --git a/lib/queue.py b/src/lib/queue.py similarity index 100% rename from lib/queue.py rename to src/lib/queue.py diff --git a/lib/set.py b/src/lib/set.py similarity index 100% rename from lib/set.py rename to src/lib/set.py diff --git a/lib/stack.py b/src/lib/stack.py similarity index 100% rename from lib/stack.py rename to src/lib/stack.py diff --git a/string/__init__.py b/src/list/__init__.py similarity index 100% rename from string/__init__.py rename to src/list/__init__.py diff --git a/list/linked_list.py b/src/list/linked_list.py similarity index 100% rename from list/linked_list.py rename to src/list/linked_list.py diff --git a/list/mutiarray_linkedlist.py b/src/list/mutiarray_linkedlist.py similarity index 100% rename from list/mutiarray_linkedlist.py rename to src/list/mutiarray_linkedlist.py diff --git a/list/skip_list.py b/src/list/skip_list.py similarity index 100% rename from list/skip_list.py rename to src/list/skip_list.py diff --git a/list/stack.py b/src/list/stack.py similarity index 100% rename from list/stack.py rename to src/list/stack.py diff --git a/tree/__init__.py b/src/matrix/__init__.py similarity index 100% rename from tree/__init__.py rename to src/matrix/__init__.py diff --git a/matrix/strassen_matrix.py b/src/matrix/strassen_matrix.py similarity index 100% rename from matrix/strassen_matrix.py rename to src/matrix/strassen_matrix.py diff --git a/src/number_theory/__init__.py b/src/number_theory/__init__.py new file mode 100644 index 0000000..fb57e2f --- /dev/null +++ b/src/number_theory/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/number_theory/gcd.py b/src/number_theory/gcd.py similarity index 100% rename from number_theory/gcd.py rename to src/number_theory/gcd.py diff --git a/src/queue/__init__.py b/src/queue/__init__.py new file mode 100644 index 0000000..fb57e2f --- /dev/null +++ b/src/queue/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/queue/fifo_queue.py b/src/queue/fifo_queue.py similarity index 100% rename from queue/fifo_queue.py rename to src/queue/fifo_queue.py diff --git a/queue/list_queue.py b/src/queue/list_queue.py similarity index 100% rename from queue/list_queue.py rename to src/queue/list_queue.py diff --git a/search/__init__.py b/src/search/__init__.py similarity index 100% rename from search/__init__.py rename to src/search/__init__.py diff --git a/search/binary_search.py b/src/search/binary_search.py similarity index 100% rename from search/binary_search.py rename to src/search/binary_search.py diff --git a/search/find_kth_with_middle.py b/src/search/find_kth_with_middle.py similarity index 100% rename from search/find_kth_with_middle.py rename to src/search/find_kth_with_middle.py diff --git a/search/find_middle_of_two_sorted_array.py b/src/search/find_middle_of_two_sorted_array.py similarity index 100% rename from search/find_middle_of_two_sorted_array.py rename to src/search/find_middle_of_two_sorted_array.py diff --git a/search/find_min_max.py b/src/search/find_min_max.py similarity index 100% rename from search/find_min_max.py rename to src/search/find_min_max.py diff --git a/search/find_sum_equals.py b/src/search/find_sum_equals.py similarity index 100% rename from search/find_sum_equals.py rename to src/search/find_sum_equals.py diff --git a/search/random_loop_section.py b/src/search/random_loop_section.py similarity index 100% rename from search/random_loop_section.py rename to src/search/random_loop_section.py diff --git a/search/random_selection.py b/src/search/random_selection.py similarity index 100% rename from search/random_selection.py rename to src/search/random_selection.py diff --git a/search/split_nth.py b/src/search/split_nth.py similarity index 100% rename from search/split_nth.py rename to src/search/split_nth.py diff --git "a/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" "b/src/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" similarity index 100% rename from "search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" rename to "src/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" diff --git a/sort/__init__.py b/src/sort/__init__.py similarity index 100% rename from sort/__init__.py rename to src/sort/__init__.py diff --git a/sort/bubble_sort.py b/src/sort/bubble_sort.py similarity index 100% rename from sort/bubble_sort.py rename to src/sort/bubble_sort.py diff --git a/sort/bucketsort.png b/src/sort/bucketsort.png similarity index 100% rename from sort/bucketsort.png rename to src/sort/bucketsort.png diff --git a/sort/counting_sort.py b/src/sort/counting_sort.py similarity index 100% rename from sort/counting_sort.py rename to src/sort/counting_sort.py diff --git a/sort/countingsort.png b/src/sort/countingsort.png similarity index 100% rename from sort/countingsort.png rename to src/sort/countingsort.png diff --git a/sort/fuzzy_space_quick_sort.py b/src/sort/fuzzy_space_quick_sort.py similarity index 100% rename from sort/fuzzy_space_quick_sort.py rename to src/sort/fuzzy_space_quick_sort.py diff --git a/sort/heap_sort.py b/src/sort/heap_sort.py similarity index 100% rename from sort/heap_sort.py rename to src/sort/heap_sort.py diff --git a/sort/hoare_quick_sort.py b/src/sort/hoare_quick_sort.py similarity index 100% rename from sort/hoare_quick_sort.py rename to src/sort/hoare_quick_sort.py diff --git a/sort/improve_fuzzy_space_quick_sort.py b/src/sort/improve_fuzzy_space_quick_sort.py similarity index 100% rename from sort/improve_fuzzy_space_quick_sort.py rename to src/sort/improve_fuzzy_space_quick_sort.py diff --git a/sort/insert_sort.py b/src/sort/insert_sort.py similarity index 100% rename from sort/insert_sort.py rename to src/sort/insert_sort.py diff --git a/sort/merge_sort.py b/src/sort/merge_sort.py similarity index 100% rename from sort/merge_sort.py rename to src/sort/merge_sort.py diff --git a/sort/quick_sort.py b/src/sort/quick_sort.py similarity index 100% rename from sort/quick_sort.py rename to src/sort/quick_sort.py diff --git a/sort/random_quick_sort.py b/src/sort/random_quick_sort.py similarity index 100% rename from sort/random_quick_sort.py rename to src/sort/random_quick_sort.py diff --git a/sort/random_two_partition_quick_sort.py b/src/sort/random_two_partition_quick_sort.py similarity index 100% rename from sort/random_two_partition_quick_sort.py rename to src/sort/random_two_partition_quick_sort.py diff --git a/sort/recursive_insert_sort.py b/src/sort/recursive_insert_sort.py similarity index 100% rename from sort/recursive_insert_sort.py rename to src/sort/recursive_insert_sort.py diff --git a/sort/select_sort.py b/src/sort/select_sort.py similarity index 100% rename from sort/select_sort.py rename to src/sort/select_sort.py diff --git a/src/string/__init__.py b/src/string/__init__.py new file mode 100644 index 0000000..fb57e2f --- /dev/null +++ b/src/string/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/string/kmp.py b/src/string/kmp.py similarity index 100% rename from string/kmp.py rename to src/string/kmp.py diff --git a/string/rabin-karp.py b/src/string/rabin-karp.py similarity index 100% rename from string/rabin-karp.py rename to src/string/rabin-karp.py diff --git a/string/simple.py b/src/string/simple.py similarity index 100% rename from string/simple.py rename to src/string/simple.py diff --git a/tree/BTree.py b/src/tree/BTree.py similarity index 100% rename from tree/BTree.py rename to src/tree/BTree.py diff --git a/src/tree/__init__.py b/src/tree/__init__.py new file mode 100644 index 0000000..fb57e2f --- /dev/null +++ b/src/tree/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/tree/AVLTree.py b/src/tree/avltree.py similarity index 100% rename from tree/AVLTree.py rename to src/tree/avltree.py diff --git a/tree/binarystree.py b/src/tree/binarystree.py similarity index 100% rename from tree/binarystree.py rename to src/tree/binarystree.py diff --git a/tree/binarytree.py b/src/tree/binarytree.py similarity index 100% rename from tree/binarytree.py rename to src/tree/binarytree.py diff --git a/tree/interval_tree.py b/src/tree/interval_tree.py similarity index 100% rename from tree/interval_tree.py rename to src/tree/interval_tree.py diff --git a/tree/lchild_rbro_tree.py b/src/tree/lchild_rbro_tree.py similarity index 100% rename from tree/lchild_rbro_tree.py rename to src/tree/lchild_rbro_tree.py diff --git a/tree/order_statistic_tree.py b/src/tree/order_statistic_tree.py similarity index 100% rename from tree/order_statistic_tree.py rename to src/tree/order_statistic_tree.py diff --git a/tree/red_black_tree.py b/src/tree/red_black_tree.py similarity index 88% rename from tree/red_black_tree.py rename to src/tree/red_black_tree.py index 88f3143..bc193dc 100644 --- a/tree/red_black_tree.py +++ b/src/tree/red_black_tree.py @@ -268,46 +268,47 @@ def __delete_fixup(self, node): parent = cur_node.parent if parent.left is cur_node: # 判断是左支还是右支,仅仅是实现所限 - uncle = parent.right - if uncle.is_red(): - # 情况一:叔节点是红色,则重新设色并左旋 - uncle.color = False + brother = parent.right + if brother.is_red(): + # 情况一:兄弟节点是红色,则重新设色并左旋 + brother.color = False parent.color = True self.__left_rotate(parent) - elif uncle.left.is_black() and uncle.right.is_black(): - # 情况二(1):叔节点和其两个子节点都是黑色.则设置叔节点为红色,这个时候如果parent是红色,那么循环就会退出 - uncle.color = True + cur_node = brother + elif brother.left.is_black() and brother.right.is_black(): + # 情况二(1):兄弟节点和其两个子节点都是黑色.则设置兄弟节点为红色,这个时候如果parent是红色,那么循环就会退出 + brother.color = True cur_node = parent - elif uncle.right.is_black(): - uncle.color = True - uncle.left.color = False - # 情况二(2):叔节点红和其右节点是黑色,那么意味着叔节点的左节点是红色,这个时候叔节点右旋并且父子节点交换颜色 - self.__right_rotate(uncle) + elif brother.right.is_black(): + brother.color = True + brother.left.color = False + # 情况二(2):兄弟节点红和其右节点是黑色,那么意味着兄弟节点的左节点是红色,这个时候兄弟节点右旋并且父子节点交换颜色 + self.__right_rotate(brother) else: - # 情况二(3):叔节点是黑色,其右节点红色(可以由前面的转换而来),这个时候叔节点设红,其父节点和右子节点设黑并且父节点左旋 + # 情况二(3):兄弟节点是黑色,其右节点红色(可以由前面的转换而来),这个时候兄弟节点设红,其父节点和右子节点设黑并且父节点左旋 parent.color = False - uncle.color = True - uncle.right.color = False + brother.color = True + brother.right.color = False self.__left_rotate(parent) # 退出情况 cur_node = self.__root else: - uncle = parent.left - if uncle.is_red(): - uncle.color = False + brother = parent.left + if brother.is_red(): + brother.color = False parent.color = True self.__right_rotate(parent) - elif uncle.left.is_black() and uncle.right.is_black(): - uncle.color = True + elif brother.left.is_black() and brother.right.is_black(): + brother.color = True cur_node = parent - elif uncle.left.is_black(): - uncle.color = True - uncle.right.color = False - self.__left_rotate(uncle) + elif brother.left.is_black(): + brother.color = True + brother.right.color = False + self.__left_rotate(brother) else: parent.color = False - uncle.color = True - uncle.left.color = False + brother.color = True + brother.left.color = False self.__right_rotate(parent) cur_node = self.__root cur_node.color = False diff --git a/tree/Tries.py b/src/tree/tries.py similarity index 100% rename from tree/Tries.py rename to src/tree/tries.py From 429b3deec9213f1de6db050a830579a8732f1b67 Mon Sep 17 00:00:00 2001 From: shengshijun Date: Sun, 19 Jul 2015 20:57:01 +0800 Subject: [PATCH 02/23] =?UTF-8?q?reformat=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/clrs/9/9-2(b).py | 4 ++-- src/clrs/9/9-2(c).py | 7 +++--- src/divide_conquer/find_max_sublist.py | 6 ++--- .../find_max_sublist_without_ recursion.py | 4 ++-- src/divide_conquer/power.py | 2 +- src/divide_conquer/yong_matrix.py | 9 ++++---- src/dynamic/fabo/fabo_loop.py | 3 ++- src/dynamic/fabo/fabo_up_down.py | 2 +- src/dynamic/lcs/down_up.py | 2 +- src/dynamic/lcs/up_down.py | 2 +- src/dynamic/lps/__init__.py | 2 -- src/dynamic/lps/down_up.py | 2 +- src/dynamic/lps/up_down.py | 2 -- src/dynamic/task/max_weighted_action.py | 1 - src/graph/general_graph.py | 23 ------------------- src/greedy/max_task_count.py | 2 -- src/hashtable/HashMap.py | 3 --- src/hashtable/OpenAddressMap.py | 1 - src/heap/max_heap.py | 11 ++++----- src/heap/max_queue.py | 15 +++++------- src/lib/queue.py | 1 + src/lib/set.py | 3 +-- src/list/linked_list.py | 12 ++++++---- src/list/mutiarray_linkedlist.py | 16 ++++++------- src/list/skip_list.py | 6 ----- src/matrix/strassen_matrix.py | 4 +--- src/number_theory/gcd.py | 1 - src/queue/fifo_queue.py | 17 ++++++-------- src/queue/list_queue.py | 3 --- src/search/binary_search.py | 2 +- src/search/find_kth_with_middle.py | 4 ++-- src/search/find_middle_of_two_sorted_array.py | 2 +- src/search/find_min_max.py | 8 +++---- src/search/find_sum_equals.py | 8 +++---- src/search/random_loop_section.py | 3 +-- src/search/random_selection.py | 6 ++--- src/search/split_nth.py | 8 +++---- src/sort/bubble_sort.py | 2 -- src/sort/counting_sort.py | 2 +- src/sort/fuzzy_space_quick_sort.py | 3 +-- src/sort/heap_sort.py | 10 ++++---- src/sort/hoare_quick_sort.py | 2 +- src/sort/improve_fuzzy_space_quick_sort.py | 7 +++--- src/sort/insert_sort.py | 17 ++++++-------- src/sort/merge_sort.py | 8 +++---- src/sort/quick_sort.py | 2 +- src/sort/random_two_partition_quick_sort.py | 2 +- src/sort/recursive_insert_sort.py | 10 ++++---- src/sort/select_sort.py | 2 +- src/string/kmp.py | 4 ---- src/tree/BTree.py | 21 +++++++++-------- src/tree/binarytree.py | 12 ++++------ src/tree/interval_tree.py | 13 +---------- src/tree/lchild_rbro_tree.py | 5 ++-- src/tree/order_statistic_tree.py | 1 - src/tree/tries.py | 1 - 56 files changed, 123 insertions(+), 208 deletions(-) diff --git a/src/clrs/9/9-2(b).py b/src/clrs/9/9-2(b).py index 773af40..92a8226 100644 --- a/src/clrs/9/9-2(b).py +++ b/src/clrs/9/9-2(b).py @@ -14,8 +14,8 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 使用随机元素元素作为分割点并且把随机元素放在列表最后 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] diff --git a/src/clrs/9/9-2(c).py b/src/clrs/9/9-2(c).py index 79fc512..aaa513c 100644 --- a/src/clrs/9/9-2(c).py +++ b/src/clrs/9/9-2(c).py @@ -7,8 +7,8 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 使用随机元素元素作为分割点并且把随机元素放在列表最后 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] @@ -27,7 +27,7 @@ def partition(li, start, end): def selection(li, start, end, kth): - #一定会找到一个元素,因此这儿直接返回是对的。 + # 一定会找到一个元素,因此这儿直接返回是对的。 if start == end: return start mid_index = partition(li, start, end) @@ -88,4 +88,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/src/divide_conquer/find_max_sublist.py b/src/divide_conquer/find_max_sublist.py index cea6537..8d46eca 100755 --- a/src/divide_conquer/find_max_sublist.py +++ b/src/divide_conquer/find_max_sublist.py @@ -39,7 +39,7 @@ def find_max_sublist(li): def find_max_in_middle(li, middle): li_len = len(li) left_max_index, right_max_index = 0, middle - #这里有一个bug,如果列表里面所有的数据都是负的,那么就找不到最小值了 + # 这里有一个bug,如果列表里面所有的数据都是负的,那么就找不到最小值了 left_max_sum, cur_sum, right_max_sum = li[middle - 1], 0, li[middle] for x in reversed(xrange(0, middle)): cur_sum += li[x] @@ -52,7 +52,7 @@ def find_max_in_middle(li, middle): if cur_sum > right_max_sum: right_max_sum = cur_sum right_max_index = x - #这里并没有判断一端结果为负的情况,因为这个时候可以在其中一端的列表中得到最大子数列 + # 这里并没有判断一端结果为负的情况,因为这个时候可以在其中一端的列表中得到最大子数列 return (left_max_index, right_max_index, right_max_sum + left_max_sum) @@ -61,4 +61,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/divide_conquer/find_max_sublist_without_ recursion.py b/src/divide_conquer/find_max_sublist_without_ recursion.py index e537d77..91810a9 100755 --- a/src/divide_conquer/find_max_sublist_without_ recursion.py +++ b/src/divide_conquer/find_max_sublist_without_ recursion.py @@ -13,7 +13,7 @@ def find_max_sublist(li): right = x max_sum = b - return (left, right, max_sum) + return left, right, max_sum def main(): @@ -21,4 +21,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/divide_conquer/power.py b/src/divide_conquer/power.py index 72522dd..caf5d42 100755 --- a/src/divide_conquer/power.py +++ b/src/divide_conquer/power.py @@ -17,4 +17,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/divide_conquer/yong_matrix.py b/src/divide_conquer/yong_matrix.py index ede339c..909d31b 100644 --- a/src/divide_conquer/yong_matrix.py +++ b/src/divide_conquer/yong_matrix.py @@ -13,7 +13,7 @@ def extract_min(matrix, w, h): left = empty_index + w right = empty_index + 1 # 1,矩阵碰到右边界的时候 - #2,右边的值是None,表示没有元素 + # 2,右边的值是None,表示没有元素 print "left :", left print "right :", right if left > (w * h - 1) and right % w is 0: @@ -23,12 +23,12 @@ def extract_min(matrix, w, h): if left <= (w * h - 1) and (right % w is 0 or matrix[right] is None or matrix[left] <= matrix[right]): matrix[empty_index] = matrix[left] empty_index = left - #1,判断矩阵碰到左边界的时候 - #2,左边的值是None,表示值是None + # 1,判断矩阵碰到左边界的时候 + # 2,左边的值是None,表示值是None elif left > (w * h - 1) or matrix[left] is None or matrix[left] > matrix[right]: matrix[empty_index] = matrix[right] empty_index = right - #到最终节点的时候 + # 到最终节点的时候 else: matrix[empty_index] = None break @@ -47,4 +47,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/src/dynamic/fabo/fabo_loop.py b/src/dynamic/fabo/fabo_loop.py index 98c32e8..0792576 100755 --- a/src/dynamic/fabo/fabo_loop.py +++ b/src/dynamic/fabo/fabo_loop.py @@ -4,6 +4,7 @@ 使用循环实现的斐波那契数列其实就是自底向上方式实现的动态规划 """ + def loop_fibonacci(n): this = 0 next = 1 @@ -25,4 +26,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/dynamic/fabo/fabo_up_down.py b/src/dynamic/fabo/fabo_up_down.py index 82efbd9..0427c7a 100644 --- a/src/dynamic/fabo/fabo_up_down.py +++ b/src/dynamic/fabo/fabo_up_down.py @@ -24,4 +24,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/src/dynamic/lcs/down_up.py b/src/dynamic/lcs/down_up.py index 78bb0d9..3c28ec7 100644 --- a/src/dynamic/lcs/down_up.py +++ b/src/dynamic/lcs/down_up.py @@ -70,4 +70,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/src/dynamic/lcs/up_down.py b/src/dynamic/lcs/up_down.py index 1fd070f..30fee5d 100644 --- a/src/dynamic/lcs/up_down.py +++ b/src/dynamic/lcs/up_down.py @@ -67,4 +67,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/src/dynamic/lps/__init__.py b/src/dynamic/lps/__init__.py index 414d02d..fb57e2f 100644 --- a/src/dynamic/lps/__init__.py +++ b/src/dynamic/lps/__init__.py @@ -1,5 +1,3 @@ #!/usr/bin/env python # -*- coding:UTF-8 __author__ = 'shenshijun' - - diff --git a/src/dynamic/lps/down_up.py b/src/dynamic/lps/down_up.py index a7b341c..cdedf2a 100644 --- a/src/dynamic/lps/down_up.py +++ b/src/dynamic/lps/down_up.py @@ -50,4 +50,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/src/dynamic/lps/up_down.py b/src/dynamic/lps/up_down.py index 2990adc..ca88437 100644 --- a/src/dynamic/lps/up_down.py +++ b/src/dynamic/lps/up_down.py @@ -56,5 +56,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/src/dynamic/task/max_weighted_action.py b/src/dynamic/task/max_weighted_action.py index d44e39a..923fb32 100644 --- a/src/dynamic/task/max_weighted_action.py +++ b/src/dynamic/task/max_weighted_action.py @@ -79,4 +79,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/src/graph/general_graph.py b/src/graph/general_graph.py index 5af1532..e1b6e1f 100644 --- a/src/graph/general_graph.py +++ b/src/graph/general_graph.py @@ -188,26 +188,3 @@ def main(): if __name__ == "__main__": main() - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/greedy/max_task_count.py b/src/greedy/max_task_count.py index 70f82cd..b889be4 100644 --- a/src/greedy/max_task_count.py +++ b/src/greedy/max_task_count.py @@ -26,5 +26,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/src/hashtable/HashMap.py b/src/hashtable/HashMap.py index 82a1478..9e831fd 100644 --- a/src/hashtable/HashMap.py +++ b/src/hashtable/HashMap.py @@ -154,6 +154,3 @@ def main(): if __name__ == "__main__": main() - - - diff --git a/src/hashtable/OpenAddressMap.py b/src/hashtable/OpenAddressMap.py index a15e83a..7d075bd 100644 --- a/src/hashtable/OpenAddressMap.py +++ b/src/hashtable/OpenAddressMap.py @@ -156,4 +156,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/src/heap/max_heap.py b/src/heap/max_heap.py index 3387a4b..e61f556 100644 --- a/src/heap/max_heap.py +++ b/src/heap/max_heap.py @@ -34,14 +34,14 @@ def heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] self.heapify(largest) @@ -56,14 +56,14 @@ def loop_heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] parent = largest @@ -88,7 +88,6 @@ def __deep_walk_through(self, func, start=0): self.__deep_walk_through(func, left) self.__deep_walk_through(func, right) - def __str__(self): title = "Heap Length: %s\n" % self.length content_list = [title] @@ -116,4 +115,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/heap/max_queue.py b/src/heap/max_queue.py index 80e997f..b06fecf 100644 --- a/src/heap/max_queue.py +++ b/src/heap/max_queue.py @@ -31,14 +31,14 @@ def heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] self.heapify(largest) @@ -52,14 +52,14 @@ def loop_heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] parent = largest @@ -84,7 +84,6 @@ def __deep_walk_through(self, func, start=0): self.__deep_walk_through(func, left) self.__deep_walk_through(func, right) - def __str__(self): title = "Heap Length: %s\n" % self.length content_list = [title] @@ -102,7 +101,7 @@ def append(self, value): insert_index = self.length while True: parent = (insert_index - 1) / 2 - #这儿需要判断使得parent不会越界 + # 这儿需要判断使得parent不会越界 if parent >= 0 and self.__array[insert_index] > self.__array[parent]: self.__array[parent], self.__array[insert_index] = self.__array[insert_index], self.__array[parent] insert_index = parent @@ -119,7 +118,7 @@ def append_with_one_assign(self, value): insert_index = self.length while True: parent = (insert_index - 1) / 2 - #这儿需要判断使得parent不会越界 + # 这儿需要判断使得parent不会越界 if parent >= 0 and value > self.__array[parent]: self.__array[insert_index] = self.__array[parent] insert_index = parent @@ -128,7 +127,6 @@ def append_with_one_assign(self, value): self.__array[insert_index] = value self.length += 1 - def __setitem__(self, index, value): self.__array[index] = value @@ -220,7 +218,6 @@ def __setitem__(self, key, value): node = MaxQueue.Node(key, value) self.__heap.append_with_one_assign(node) - def __str__(self): return str(self.__heap) diff --git a/src/lib/queue.py b/src/lib/queue.py index 67c2711..28e699a 100644 --- a/src/lib/queue.py +++ b/src/lib/queue.py @@ -3,6 +3,7 @@ __author__ = 'shenshijun' import copy + class Queue(object): """ 使用Python的list快速实现一个队列 diff --git a/src/lib/set.py b/src/lib/set.py index 997a408..40fecd9 100644 --- a/src/lib/set.py +++ b/src/lib/set.py @@ -46,6 +46,7 @@ def __iter__(self): def __str__(self): return ",".join(map(lambda node: str(node), iter(self))) + def main(): test_set = Set() test_set.add(10) @@ -56,5 +57,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/src/list/linked_list.py b/src/list/linked_list.py index 0fc4e6f..a9278f8 100644 --- a/src/list/linked_list.py +++ b/src/list/linked_list.py @@ -5,6 +5,7 @@ 实现一个带哨兵的双向循环链表。一个哨兵是一个空对象,在双向链表实现中简化了改变链接的时候需要判断None的情况。 实现这个链表的过程时刻记得更新插入和删除节点的前后节点的指针 """ +from __builtin__ import object class LinkedList(object): @@ -47,10 +48,11 @@ def insert(self, index, value): def append(self, value): last_node = self.__nil.prev node = LinkedList.Node(value, last_node, self.__nil) - last_node.next = node #现在结尾的节点指向新加的结尾点 + # 现在结尾的节点指向新加的结尾点 + last_node.next = node self.__nil.prev = node self.__length += 1 - #处理空链表的情况 + # 处理空链表的情况 if self.__nil.next is self.__nil: self.__nil.next = node return node @@ -59,7 +61,7 @@ def prepend(self, value): node = LinkedList.Node(value, self.__nil, self.__nil.next) self.__nil.next = node self.__nil.next.prev = node - #处理空链表的情况 + # 处理空链表的情况 if self.__nil.prev is self.__nil: self.__nil.prev = node self.__length += 1 @@ -75,7 +77,7 @@ def delete(self, value): cur_node = self.__nil.next while cur_node is not self.__nil and cur_node.key != value: cur_node = cur_node.next - #如果不是空链表,那么就是查找到了相应的元素 + # 如果不是空链表,那么就是查找到了相应的元素 if cur_node is not self.__nil: cur_node.prev.next = cur_node.next cur_node.next.prev = cur_node.prev @@ -107,4 +109,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/list/mutiarray_linkedlist.py b/src/list/mutiarray_linkedlist.py index f2f988d..3b638a9 100644 --- a/src/list/mutiarray_linkedlist.py +++ b/src/list/mutiarray_linkedlist.py @@ -20,13 +20,13 @@ def __init__(self, length): self.__lenght = 0 self.__key = [self.__empty for x in xrange(0, length + 1)] self.__prev = [-1 for x in xrange(0, length + 1)] - self.__next = [x + 1 for x in xrange(0, length + 1)] #next数组在节点为空的时候存储的是下一个空节点的位置 - self.__free = 1 #第一个空元素位置 - #设置哨兵元素 + self.__next = [x + 1 for x in xrange(0, length + 1)] # next数组在节点为空的时候存储的是下一个空节点的位置 + self.__free = 1 # 第一个空元素位置 + # 设置哨兵元素 self.__key[0] = self.__empty self.__prev[0] = 0 self.__next[0] = 0 - self.__full = 0 #第一个元素位置 + self.__full = 0 # 第一个元素位置 def prepend(self, value): first_node = self.__next[0] @@ -41,16 +41,16 @@ def prepend(self, value): def append(self, value): last_node = self.__prev[0] - #创建新节点 + # 创建新节点 self.__key[self.__free] = value self.__prev[self.__free] = last_node next_free = self.__next[self.__free] self.__next[self.__free] = 0 - #设置上一个节点 + # 设置上一个节点 self.__next[last_node] = self.__free - #设置起始节点 + # 设置起始节点 self.__prev[0] = self.__free - #设置空链表 + # 设置空链表 self.__free = next_free self.__full = self.__next[0] diff --git a/src/list/skip_list.py b/src/list/skip_list.py index b86e519..939e0b2 100644 --- a/src/list/skip_list.py +++ b/src/list/skip_list.py @@ -132,7 +132,6 @@ def __search(self, value): # 既不能右行也不能下行的时候查询失败 return None - @classmethod def __insert_node(cls, prev_node, down_node, node): next_node = prev_node.next @@ -206,8 +205,3 @@ def main(): if __name__ == "__main__": main() - - - - - diff --git a/src/matrix/strassen_matrix.py b/src/matrix/strassen_matrix.py index 0193ef3..b19da92 100755 --- a/src/matrix/strassen_matrix.py +++ b/src/matrix/strassen_matrix.py @@ -103,9 +103,8 @@ def __combine_matrix(cls, m11, m12, m21, m22): result[x].extend(temp) return Matrix(m11.__weight + m12.__weight, m11.__height + m21.__height, result) - def __strassen_method(self, other): - #首先需要保证矩阵可以分割 + # 首先需要保证矩阵可以分割 a11, a12, a21, a22 = Matrix.__divide_matrix(self) b11, b12, b21, b22 = Matrix.__divide_matrix(other) # print b11 @@ -150,4 +149,3 @@ def main(): if __name__ == '__main__': main() - \ No newline at end of file diff --git a/src/number_theory/gcd.py b/src/number_theory/gcd.py index 85203fb..e19879b 100644 --- a/src/number_theory/gcd.py +++ b/src/number_theory/gcd.py @@ -17,4 +17,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/src/queue/fifo_queue.py b/src/queue/fifo_queue.py index 2a27ee5..6330077 100644 --- a/src/queue/fifo_queue.py +++ b/src/queue/fifo_queue.py @@ -31,14 +31,14 @@ def heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] self.heapify(largest) @@ -52,14 +52,14 @@ def loop_heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] parent = largest @@ -84,7 +84,6 @@ def __deep_walk_through(self, func, start=0): self.__deep_walk_through(func, left) self.__deep_walk_through(func, right) - def __str__(self): title = "Heap Length: %s\n" % self.length content_list = [title] @@ -102,7 +101,7 @@ def append(self, value): insert_index = self.length while True: parent = (insert_index - 1) / 2 - #这儿需要判断使得parent不会越界 + # 这儿需要判断使得parent不会越界 if parent >= 0 and self.__array[insert_index] > self.__array[parent]: self.__array[parent], self.__array[insert_index] = self.__array[insert_index], self.__array[parent] insert_index = parent @@ -119,7 +118,7 @@ def append_with_one_assign(self, value): insert_index = self.length while True: parent = (insert_index - 1) / 2 - #这儿需要判断使得parent不会越界 + # 这儿需要判断使得parent不会越界 if parent >= 0 and value > self.__array[parent]: self.__array[insert_index] = self.__array[parent] insert_index = parent @@ -128,7 +127,6 @@ def append_with_one_assign(self, value): self.__array[insert_index] = value self.length += 1 - def __setitem__(self, index, value): self.__array[index] = value @@ -221,7 +219,6 @@ def __setitem__(self, key, value): node = MaxQueue.Node(key, value) self.__heap.append_with_one_assign(node) - def __str__(self): return str(self.__heap) @@ -258,4 +255,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/queue/list_queue.py b/src/queue/list_queue.py index aacddae..ee37e58 100644 --- a/src/queue/list_queue.py +++ b/src/queue/list_queue.py @@ -33,7 +33,6 @@ def enter(self, x): if self.__tail >= self.__cap: self.__tail = 0 - def exit(self): if self.__tail == self.__head and self.__value[self.__head] is self.__empty: raise IndexError("queue is empty") @@ -53,5 +52,3 @@ def __len__(self): return 0 else: return self.__cap - - diff --git a/src/search/binary_search.py b/src/search/binary_search.py index 397a474..30830b3 100755 --- a/src/search/binary_search.py +++ b/src/search/binary_search.py @@ -35,4 +35,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/search/find_kth_with_middle.py b/src/search/find_kth_with_middle.py index 80d931c..1137fa8 100644 --- a/src/search/find_kth_with_middle.py +++ b/src/search/find_kth_with_middle.py @@ -1,4 +1,4 @@ # /usr/bin/env python -#-*- coding:uft-8 +# -*- coding:uft-8 +""" """ -""" \ No newline at end of file diff --git a/src/search/find_middle_of_two_sorted_array.py b/src/search/find_middle_of_two_sorted_array.py index 18baf76..021a7b8 100644 --- a/src/search/find_middle_of_two_sorted_array.py +++ b/src/search/find_middle_of_two_sorted_array.py @@ -27,4 +27,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/search/find_min_max.py b/src/search/find_min_max.py index ad442e0..9dcc1e3 100644 --- a/src/search/find_min_max.py +++ b/src/search/find_min_max.py @@ -1,5 +1,5 @@ # /usr/bin/env python -#-*- coding:utf-8 -*- +# -*- coding:utf-8 -*- """ 同时找出一个列表中的最大和最小的值,算法实现的时候分别记录 了到当前的最大值和最小值。并且每次比较都对一对输入元素进行比较。 @@ -21,7 +21,7 @@ def find_min_max(li): li_max = li[0] start = 2 - #处理奇数的情况 + # 处理奇数的情况 if li_len / 2 is 1 and li_len >= 3: start += 1 if li[3] < li_min: @@ -30,7 +30,7 @@ def find_min_max(li): li_max = li[3] for x in xrange(start, li_len, 2): - #默认first是小的 + # 默认first是小的 first = li[x] second = li[x + 1] if first > second: @@ -51,5 +51,3 @@ def main(): if __name__ == '__main__': main() - - diff --git a/src/search/find_sum_equals.py b/src/search/find_sum_equals.py index fc559ad..0b13319 100755 --- a/src/search/find_sum_equals.py +++ b/src/search/find_sum_equals.py @@ -31,7 +31,7 @@ def binary_search(sorted_list, value): def __merge_sort__(llist, rlist): llen = len(llist) rlen = len(rlist) - #递归结束时间:[]和[ele] + # 递归结束时间:[]和[ele] if llen + rlen < 2: return llist + rlist lrst = __merge_sort__(llist[:llen / 2], llist[llen / 2:]) @@ -39,7 +39,7 @@ def __merge_sort__(llist, rlist): lcursor, rcursor = 0, 0 result = [] min_len = min(llen, rlen) - #从小到大排序 + # 从小到大排序 while lcursor < llen and rcursor < rlen: if lrst[lcursor] < rrst[rcursor]: result.append(lrst[lcursor]) @@ -47,7 +47,7 @@ def __merge_sort__(llist, rlist): else: result.append(rrst[rcursor]) rcursor += 1 - #把没有合并的数据合并起来。 + # 把没有合并的数据合并起来。 result.extend(lrst[lcursor:]) result.extend(rrst[rcursor:]) return result @@ -75,4 +75,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/search/random_loop_section.py b/src/search/random_loop_section.py index 16b9a25..aa61598 100644 --- a/src/search/random_loop_section.py +++ b/src/search/random_loop_section.py @@ -8,7 +8,7 @@ def partition(li, start, end): if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") # 使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] @@ -53,4 +53,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/src/search/random_selection.py b/src/search/random_selection.py index 1afcc75..2abd7c2 100644 --- a/src/search/random_selection.py +++ b/src/search/random_selection.py @@ -7,8 +7,8 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 使用随机元素元素作为分割点并且把随机元素放在列表最后 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] @@ -27,7 +27,7 @@ def partition(li, start, end): def selection(li, start, end, kth): - #一定会找到一个元素,因此这儿直接返回是对的。 + # 一定会找到一个元素,因此这儿直接返回是对的。 if start == end: return li[start] mid_index = partition(li, start, end) diff --git a/src/search/split_nth.py b/src/search/split_nth.py index 696907e..ea062c6 100644 --- a/src/search/split_nth.py +++ b/src/search/split_nth.py @@ -7,8 +7,8 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 使用随机元素元素作为分割点并且把随机元素放在列表最后 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] @@ -27,7 +27,7 @@ def partition(li, start, end): def selection(li, start, end, kth): - #一定会找到一个元素,因此这儿直接返回是对的。 + # 一定会找到一个元素,因此这儿直接返回是对的。 if start == end: return start mid_index = partition(li, start, end) @@ -55,7 +55,7 @@ def split_even_nth(li, start, end, k, kth_list): return kth_list if k % 2 is 1: return split_odd_nth(li, start, end, k, kth_list) - middle_index = selection(li, start, end, (end - start - 1) / 2) #必须要减一,分割的点是中间元素的前一个 + middle_index = selection(li, start, end, (end - start - 1) / 2) # 必须要减一,分割的点是中间元素的前一个 print "start:%s,end:%s,mid_index:%s" % (start, end, middle_index) kth_list.append(li[middle_index]) split_even_nth(li, start, middle_index, k / 2, kth_list) diff --git a/src/sort/bubble_sort.py b/src/sort/bubble_sort.py index 825adf6..285e0c4 100755 --- a/src/sort/bubble_sort.py +++ b/src/sort/bubble_sort.py @@ -24,5 +24,3 @@ def main(): if __name__ == '__main__': main() - - diff --git a/src/sort/counting_sort.py b/src/sort/counting_sort.py index 8d48e42..9f493d6 100644 --- a/src/sort/counting_sort.py +++ b/src/sort/counting_sort.py @@ -32,4 +32,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/sort/fuzzy_space_quick_sort.py b/src/sort/fuzzy_space_quick_sort.py index 24b9916..e7a3aef 100644 --- a/src/sort/fuzzy_space_quick_sort.py +++ b/src/sort/fuzzy_space_quick_sort.py @@ -1,6 +1,5 @@ #!/usr/bin/env python # -*- coding:utf-8 -*- -from math import * """ 模糊空间排序唯一需要考虑的问题就是空间的合并。 @@ -43,7 +42,7 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用最后一个元素作为分割点 + # 使用最后一个元素作为分割点 key = li[end] middle_index = start for x in xrange(start, end + 1): diff --git a/src/sort/heap_sort.py b/src/sort/heap_sort.py index 02aae02..86ad116 100644 --- a/src/sort/heap_sort.py +++ b/src/sort/heap_sort.py @@ -31,14 +31,14 @@ def heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] self.heapify(largest) @@ -52,14 +52,14 @@ def loop_heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] parent = largest @@ -84,7 +84,6 @@ def __deep_walk_through(self, func, start=0): self.__deep_walk_through(func, left) self.__deep_walk_through(func, right) - def __str__(self): title = "Heap Length: %s\n" % self.length content_list = [title] @@ -103,7 +102,6 @@ def __deepcopy__(self): newone.__dict__[x] = copy.deepcopy(self.__dict__[x]) return newone - @classmethod def heap_sort(cls, list): """ diff --git a/src/sort/hoare_quick_sort.py b/src/sort/hoare_quick_sort.py index 4b12114..ddd3f58 100644 --- a/src/sort/hoare_quick_sort.py +++ b/src/sort/hoare_quick_sort.py @@ -36,4 +36,4 @@ def main(): # print quick_sort(li,0,11) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/sort/improve_fuzzy_space_quick_sort.py b/src/sort/improve_fuzzy_space_quick_sort.py index e579116..d8f81dc 100644 --- a/src/sort/improve_fuzzy_space_quick_sort.py +++ b/src/sort/improve_fuzzy_space_quick_sort.py @@ -1,6 +1,5 @@ #!/usr/bin/env python # -*- coding:utf-8 -*- -from math import * """ 模糊空间排序唯一需要考虑的问题就是空间的合并。 @@ -45,7 +44,7 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用最后一个元素作为分割点 + # 使用最后一个元素作为分割点 print "end:", end key = li[end] middle_index = start @@ -54,7 +53,7 @@ def partition(li, start, end): li[middle_index], li[x] = li[x], li[middle_index] middle_index += 1 li[end], li[middle_index] = li[middle_index], li[end] - #处理middle_index:middle_index有两种情况,一是被合并,二是合并其他元素。 + # 处理middle_index:middle_index有两种情况,一是被合并,二是合并其他元素。 result = [] for i in xrange(start, end + 1): x = li[i] @@ -93,4 +92,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/sort/insert_sort.py b/src/sort/insert_sort.py index 29201fb..d2bc385 100755 --- a/src/sort/insert_sort.py +++ b/src/sort/insert_sort.py @@ -4,17 +4,17 @@ def main(): print reverse_insert_sort([2, 13, 4, 1919, 1, 1100, 1, 2, 3, 373737, 0]) -#从小到大排序 +# 从小到大排序 def insert_sort(li): list_len = len(li) if list_len < 2: return li for x in xrange(1, list_len): cursor = li[x] - #算法不是从头开始比较的,而是从Cursor的上一个元素比较的,否则必须使用多个循环。 + # 算法不是从头开始比较的,而是从Cursor的上一个元素比较的,否则必须使用多个循环。 for y in reversed(xrange(0, x)): - if cursor < li[y]: #一个重要的细节:如果两个元素相等,那么它们的顺序不会变 - #忽略了一个边界条件cursor=1,而li[0]=2的时候,需要li[0]=cursor + if cursor < li[y]: # 一个重要的细节:如果两个元素相等,那么它们的顺序不会变 + # 忽略了一个边界条件cursor=1,而li[0]=2的时候,需要li[0]=cursor li[y + 1], li[y] = li[y], cursor else: li[y + 1] = cursor @@ -28,10 +28,10 @@ def reverse_insert_sort(li): return li for x in xrange(1, list_len): cursor = li[x] - #算法不是从头开始比较的,而是从Cursor的上一个元素比较的,负责必须使用多个循环。 + # 算法不是从头开始比较的,而是从Cursor的上一个元素比较的,负责必须使用多个循环。 for y in reversed(xrange(0, x)): - if cursor > li[y]: #一个重要的细节:如果两个元素相等,那么它们的顺序不会变 - #忽略了一个边界条件cursor=1,而li[0]=2的时候,需要li[0]=cursor + if cursor > li[y]: # 一个重要的细节:如果两个元素相等,那么它们的顺序不会变 + # 忽略了一个边界条件cursor=1,而li[0]=2的时候,需要li[0]=cursor li[y + 1], li[y] = li[y], cursor else: li[y + 1] = cursor @@ -41,6 +41,3 @@ def reverse_insert_sort(li): if __name__ == '__main__': main() - - - diff --git a/src/sort/merge_sort.py b/src/sort/merge_sort.py index 8066b26..aa9bd4d 100755 --- a/src/sort/merge_sort.py +++ b/src/sort/merge_sort.py @@ -14,7 +14,7 @@ def main(): def merge_sort(llist, rlist): llen = len(llist) rlen = len(rlist) - #递归结束时间:[]和[ele] + # 递归结束时间:[]和[ele] if llen + rlen < 2: return llist + rlist lrst = merge_sort(llist[:llen / 2], llist[llen / 2:]) @@ -22,7 +22,7 @@ def merge_sort(llist, rlist): lcursor, rcursor = 0, 0 result = [] min_len = min(llen, rlen) - #从小到大排序 + # 从小到大排序 while lcursor < llen and rcursor < rlen: if lrst[lcursor] < rrst[rcursor]: result.append(lrst[lcursor]) @@ -30,11 +30,11 @@ def merge_sort(llist, rlist): else: result.append(rrst[rcursor]) rcursor += 1 - #把没有合并的数据合并起来。 + # 把没有合并的数据合并起来。 result.extend(lrst[lcursor:]) result.extend(rrst[rcursor:]) return result if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/sort/quick_sort.py b/src/sort/quick_sort.py index b0705d5..ec28543 100644 --- a/src/sort/quick_sort.py +++ b/src/sort/quick_sort.py @@ -5,7 +5,7 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用最后一个元素作为分割点 + # 使用最后一个元素作为分割点 key = li[end] middle_index = start for x in xrange(start, end): diff --git a/src/sort/random_two_partition_quick_sort.py b/src/sort/random_two_partition_quick_sort.py index 6482cc5..13cb4ef 100644 --- a/src/sort/random_two_partition_quick_sort.py +++ b/src/sort/random_two_partition_quick_sort.py @@ -36,4 +36,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/sort/recursive_insert_sort.py b/src/sort/recursive_insert_sort.py index 627d5fa..e290b6f 100755 --- a/src/sort/recursive_insert_sort.py +++ b/src/sort/recursive_insert_sort.py @@ -12,15 +12,15 @@ def recursive_insert_sort(li): li_len = len(li) if li_len < 2: return li - first = li[0] #取出第一个元素 - sorted_li = recursive_insert_sort(li[1:]) #默认从小到大 + first = li[0] # 取出第一个元素 + sorted_li = recursive_insert_sort(li[1:]) # 默认从小到大 for x in xrange(0, li_len - 1): if first > sorted_li[x]: li[x] = sorted_li[x] else: - #由于Python列表切片的规则,这个地方不用判断列表的索引是不是 - #超过了列表的大小,因为如果在切片中超出列表大小,返回的是一个 - #空列表 + # 由于Python列表切片的规则,这个地方不用判断列表的索引是不是 + # 超过了列表的大小,因为如果在切片中超出列表大小,返回的是一个 + # 空列表 li[x] = first li[x + 1:] = sorted_li[x:] break diff --git a/src/sort/select_sort.py b/src/sort/select_sort.py index f045f26..25b0afa 100755 --- a/src/sort/select_sort.py +++ b/src/sort/select_sort.py @@ -25,4 +25,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/string/kmp.py b/src/string/kmp.py index cb2bcb1..e92a8f0 100644 --- a/src/string/kmp.py +++ b/src/string/kmp.py @@ -20,7 +20,6 @@ def build_next(): origin_index, pattern_index = 0, 0 next_list = build_next() - print(next_list) while origin_index < origin_len: # while需要放在前面,如果放在后面的话且有匹配的情况下pattern[pattern_index]就会越界 while pattern_index > 0 and origin[origin_index] != pattern[pattern_index]: @@ -39,6 +38,3 @@ def main(): if __name__ == "__main__": main() - - - diff --git a/src/tree/BTree.py b/src/tree/BTree.py index f860d3e..b2c704e 100644 --- a/src/tree/BTree.py +++ b/src/tree/BTree.py @@ -24,7 +24,7 @@ def __init__(self, is_leaf, keys, childs=None, parent=None): def __str__(self): return "".join(['Node(keys=', ",".join(map(lambda key: str(key), self.keys)), ',leaf' if self.is_leaf else ',not leaf', - ',childs num=', str(len(self.childs)) ,')\n']) + ',childs num=', str(len(self.childs)), ')\n']) def __len__(self): return self.__size @@ -94,18 +94,20 @@ def insert(self, key): def __split(self, node): if self.full(node): parent_node = node.parent - middle_key = node.keys[self.__load_factor-1] + middle_key = node.keys[self.__load_factor - 1] if parent_node is None: # 处理根节点 self.__root = Node(False, []) parent_node = self.__root parent_middle_index = parent_node.append(middle_key) - left_node = Node(node.is_leaf, node.keys[:self.__load_factor-1], node.childs[:self.__load_factor], parent_node) - #注意设定分裂节点的子节点的父指针 + left_node = Node(node.is_leaf, node.keys[:self.__load_factor - 1], node.childs[:self.__load_factor], + parent_node) + # 注意设定分裂节点的子节点的父指针 for child in left_node.childs: if child is not None: child.parent = left_node - right_node = Node(node.is_leaf, node.keys[self.__load_factor:], node.childs[self.__load_factor:], parent_node) + right_node = Node(node.is_leaf, node.keys[self.__load_factor:], node.childs[self.__load_factor:], + parent_node) for child in right_node.childs: if child is not None: child.parent = right_node @@ -164,12 +166,12 @@ def midorder(self, f): if cur_node.is_leaf: # 到叶节点了,开始把叶节点的所有关键字都遍历掉 result.extend(map(f, cur_node.keys)) - #开始从栈中取元素,遍历下一个节点叶节点 + # 开始从栈中取元素,遍历下一个节点叶节点 if stack.empty(): return result cur_node, i = stack.pop() result.append(f(cur_node.keys[i])) - if i < len(cur_node)-1: + if i < len(cur_node) - 1: stack.push((cur_node, i + 1)) cur_node = cur_node.childs[i + 1] else: @@ -188,7 +190,8 @@ def test(self): def main(): - btree = BTree(3, 'A', 'B', 'C', 'D', 'E', 'F', 'G','H','I','J','K','L','M','N','O','P','R','S','T','U','V','X','Y','Z') + btree = BTree(3, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', + 'V', 'X', 'Y', 'Z') print btree print btree.max() print btree.min() @@ -196,5 +199,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/src/tree/binarytree.py b/src/tree/binarytree.py index b2459cb..978eb59 100644 --- a/src/tree/binarytree.py +++ b/src/tree/binarytree.py @@ -1,5 +1,5 @@ # /usr/bin/env python -#-*- coding:utf-8 -*- +# -*- coding:utf-8 -*- import Queue @@ -10,8 +10,8 @@ class Stack(object): def __init__(self, cap): super(Stack, self).__init__() - self.__cap = cap #栈大小 - self.__length = 0 #栈长度 + self.__cap = cap # 栈大小 + self.__length = 0 # 栈长度 if self.__cap < 0: raise ValueError("length of Stack can not be negtive") self.__values = [0 for x in xrange(0, self.__cap)] @@ -94,7 +94,7 @@ def breadth_walk(self, f): while not q.empty(): cur_node = q.get() result.append(f(cur_node.key)) - #注意:这儿的顺序比较讲究,不能调换 + # 注意:这儿的顺序比较讲究,不能调换 if cur_node.left is not None: q.put(cur_node.left) @@ -115,7 +115,3 @@ def main(): if __name__ == '__main__': main() - - - - \ No newline at end of file diff --git a/src/tree/interval_tree.py b/src/tree/interval_tree.py index 550ede7..f878471 100644 --- a/src/tree/interval_tree.py +++ b/src/tree/interval_tree.py @@ -45,7 +45,7 @@ def restore_max(self): self.sub_max = max([self.left.sub_max, self.right.sub_max]) def not_empty(self): - return self.left is not None and self.right is not None + return self.left is not None and self.right is not None @property def key(self): @@ -57,7 +57,6 @@ class IntervalTree(object): 用红黑树实现区间树 """ - def __init__(self, *vargs): """ @@ -72,7 +71,6 @@ def __len__(self): return self.__size - def __left_rotate(self, node): """ @@ -103,7 +101,6 @@ def __left_rotate(self, node): node.restore_max() right_child.restore_max() - def __right_rotate(self, node): """ 二叉搜索树右旋操作 @@ -134,7 +131,6 @@ def __right_rotate(self, node): node.restore_max() left_child.restore_max() - def insert(self, key): cur_node = self.__root node = Node(key[0], key[1], key[1], self.Nil, self.Nil, self.Nil, True) @@ -159,7 +155,6 @@ def insert(self, key): node.parent = parent_node self.__insert_fixup(node) - def __insert_fixup(self, node): # 首先判断节点是不是根节点或者父节点是不是根节点 @@ -269,7 +264,6 @@ def __find(self, key): cur_node = cur_node.left return cur_node - def __successor(self, value): find_node = self.__find(value) if find_node is self.Nil: @@ -301,12 +295,10 @@ def __min(self, root): cur_node = cur_node.left return cur_node - def min(self): min_node = self.__min(self.__root) return min_node.value if min_node is not None else None - def __delete_fixup(self, node): cur_node = node while cur_node is not self.__root and cur_node.is_black(): @@ -357,7 +349,6 @@ def __delete_fixup(self, node): cur_node = self.__root cur_node.color = False - def midorder(self, f): """ 中序遍历 @@ -380,7 +371,6 @@ def midorder(self, f): cur_node = cur_node.right return result - def print_tree(self): """ 打印树的结构 @@ -419,4 +409,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/src/tree/lchild_rbro_tree.py b/src/tree/lchild_rbro_tree.py index 38ef247..8cf0398 100644 --- a/src/tree/lchild_rbro_tree.py +++ b/src/tree/lchild_rbro_tree.py @@ -1,5 +1,5 @@ #!/usr/bin/env -#!-*- coding:utf-8 -*- +# !-*- coding:utf-8 -*- import Queue @@ -86,7 +86,6 @@ def depth_walk(self, f): stack.push(cur_node.child) return result - def breadth_walk(self, f): """ 使用队列实现广度遍历的思路是类似的,在访问到一个父节点的时候把所有的子节点都依次放到队列中 @@ -116,4 +115,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/tree/order_statistic_tree.py b/src/tree/order_statistic_tree.py index 0de4b09..122369e 100644 --- a/src/tree/order_statistic_tree.py +++ b/src/tree/order_statistic_tree.py @@ -450,4 +450,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/src/tree/tries.py b/src/tree/tries.py index 9caf5d0..1dc2140 100644 --- a/src/tree/tries.py +++ b/src/tree/tries.py @@ -11,4 +11,3 @@ class Tries(object): def __init__(self): """""" pass - From 09420aa7362b2e0056255499f4605bd6c4589379 Mon Sep 17 00:00:00 2001 From: shengshijun Date: Sun, 19 Jul 2015 21:06:15 +0800 Subject: [PATCH 03/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9linked=5Flist=E7=9A=84t?= =?UTF-8?q?oString=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/list/linked_list.py | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/list/linked_list.py b/src/list/linked_list.py index a9278f8..c9813b3 100644 --- a/src/list/linked_list.py +++ b/src/list/linked_list.py @@ -19,13 +19,13 @@ def __init__(self, key, prev, next): self.next = next def __str__(self): - return "".join([str(self.key), "-->"]) + return str(self.key) def __init__(self, *arg): super(LinkedList, self).__init__() - self.__nil = LinkedList.Node(None, None, None) - self.__nil.prev = self.__nil - self.__nil.next = self.__nil + self.__dump = LinkedList.Node(None, None, None) + self.__dump.prev = self.__dump + self.__dump.next = self.__dump self.__length = 0 for key in arg: self.append(key) @@ -34,7 +34,7 @@ def insert(self, index, value): if index > self.__length: raise IndexError("can not insert beyond the list") cur_pos = 0 - cur_node = self.__nil + cur_node = self.__dump while cur_pos < index: cur_node = cur_node.next cur_pos += 1 @@ -46,39 +46,39 @@ def insert(self, index, value): return node def append(self, value): - last_node = self.__nil.prev - node = LinkedList.Node(value, last_node, self.__nil) + last_node = self.__dump.prev + node = LinkedList.Node(value, last_node, self.__dump) # 现在结尾的节点指向新加的结尾点 last_node.next = node - self.__nil.prev = node + self.__dump.prev = node self.__length += 1 # 处理空链表的情况 - if self.__nil.next is self.__nil: - self.__nil.next = node + if self.__dump.next is self.__dump: + self.__dump.next = node return node def prepend(self, value): - node = LinkedList.Node(value, self.__nil, self.__nil.next) - self.__nil.next = node - self.__nil.next.prev = node + node = LinkedList.Node(value, self.__dump, self.__dump.next) + self.__dump.next = node + self.__dump.next.prev = node # 处理空链表的情况 - if self.__nil.prev is self.__nil: - self.__nil.prev = node + if self.__dump.prev is self.__dump: + self.__dump.prev = node self.__length += 1 return node def search(self, value): - cur_node = self.__nil.next - while cur_node is not self.__nil and cur_node.key != value: + cur_node = self.__dump.next + while cur_node is not self.__dump and cur_node.key != value: cur_node = cur_node.next return cur_node.key def delete(self, value): - cur_node = self.__nil.next - while cur_node is not self.__nil and cur_node.key != value: + cur_node = self.__dump.next + while cur_node is not self.__dump and cur_node.key != value: cur_node = cur_node.next # 如果不是空链表,那么就是查找到了相应的元素 - if cur_node is not self.__nil: + if cur_node is not self.__dump: cur_node.prev.next = cur_node.next cur_node.next.prev = cur_node.prev @@ -88,12 +88,12 @@ def __len__(self): return self.__length def __str__(self): - cur_node = self.__nil.next + cur_node = self.__dump.next li = [] - while cur_node is not self.__nil: + while cur_node is not self.__dump: li.append(str(cur_node)) cur_node = cur_node.next - return "".join(li) + return '[' + ", ".join(li) + ']' def main(): From c59d1dfa977e06d21217ab054e385a46e475b242 Mon Sep 17 00:00:00 2001 From: shengshijun Date: Sun, 19 Jul 2015 21:38:10 +0800 Subject: [PATCH 04/23] =?UTF-8?q?1,=20=E4=BF=AE=E6=94=B9=E5=8F=8C=E5=90=91?= =?UTF-8?q?=E9=93=BE=E8=A1=A8=E4=B8=AD=E7=9A=84bug.=202,=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9readme,=E5=88=B6=E5=AE=9A=E4=B8=8B=E4=B8=80=E6=AD=A5?= =?UTF-8?q?=E8=AE=A1=E5=88=92.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++- src/list/linked_list.py | 82 ++++++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 23f6a41..01c11be 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ algorithm 在阅读算法导论的时候。我用Python写的一些算法,这些算法大部分使用list来作为底层存储数据的结构。但是python的list用的是链表实现,因此有些操作性能不高。 #算法 -------------- ##排序算法:sort文件夹下面 1. 冒泡排序 2. 插入排序 @@ -91,5 +90,14 @@ algorithm 3. Set +未来计划 +===================== +#在学习redis源码的过程中修改各个数据结构的实现,目的是使用更加精细的规则去提高数据结构的性能 +#添加更多注释并且格式化代码,注释中注重于设计的思考 +#添加算法导论中其他高级的数据结构 +#计划完成一些在线的题库 + + + diff --git a/src/list/linked_list.py b/src/list/linked_list.py index c9813b3..052676d 100644 --- a/src/list/linked_list.py +++ b/src/list/linked_list.py @@ -2,7 +2,8 @@ # -*- coding:utf-8 -*- """ -实现一个带哨兵的双向循环链表。一个哨兵是一个空对象,在双向链表实现中简化了改变链接的时候需要判断None的情况。 +实现一个带哨兵的双向循环链表。一个哨兵是一个空对象 +在双向链表实现中简化了改变链接的时候需要判断None的情况。 实现这个链表的过程时刻记得更新插入和删除节点的前后节点的指针 """ from __builtin__ import object @@ -12,36 +13,45 @@ class LinkedList(object): class Node(object): """docstring for LinkedList.Node""" - def __init__(self, key, prev, next): + def __init__(self, value, prev, next_node): super(LinkedList.Node, self).__init__() - self.key = key + self.value = value self.prev = prev - self.next = next + self.next_node = next_node def __str__(self): - return str(self.key) + return str(self.value) def __init__(self, *arg): + """ + 创建一个链表 + :param arg: 可变参数,是列表的初始元素 + :return: + """ super(LinkedList, self).__init__() + # dump对象的prev指针始终指向列表的尾巴 + # 而列表的最后一个元素的next指针则始终指向列表开头,整个列表就是一个环 self.__dump = LinkedList.Node(None, None, None) self.__dump.prev = self.__dump - self.__dump.next = self.__dump + self.__dump.next_node = self.__dump self.__length = 0 - for key in arg: - self.append(key) + for value in arg: + self.append(value) def insert(self, index, value): if index > self.__length: raise IndexError("can not insert beyond the list") + cur_pos = 0 cur_node = self.__dump while cur_pos < index: - cur_node = cur_node.next + cur_node = cur_node.next_node cur_pos += 1 + prev_node = cur_node.prev node = LinkedList.Node(value, prev_node, cur_node) cur_node.prev = node - prev_node.next = node + prev_node.next_node = node self.__length += 1 return node @@ -49,50 +59,46 @@ def append(self, value): last_node = self.__dump.prev node = LinkedList.Node(value, last_node, self.__dump) # 现在结尾的节点指向新加的结尾点 - last_node.next = node + last_node.next_node = node self.__dump.prev = node self.__length += 1 - # 处理空链表的情况 - if self.__dump.next is self.__dump: - self.__dump.next = node return node def prepend(self, value): - node = LinkedList.Node(value, self.__dump, self.__dump.next) - self.__dump.next = node - self.__dump.next.prev = node - # 处理空链表的情况 - if self.__dump.prev is self.__dump: - self.__dump.prev = node + node = LinkedList.Node(value, self.__dump, self.__dump.next_node) + self.__dump.next_node.prev = node + self.__dump.next_node = node self.__length += 1 return node def search(self, value): - cur_node = self.__dump.next - while cur_node is not self.__dump and cur_node.key != value: - cur_node = cur_node.next - return cur_node.key + cur_node = self.__dump.next_node + while cur_node is not self.__dump and cur_node.value != value: + cur_node = cur_node.next_node + return cur_node.value def delete(self, value): - cur_node = self.__dump.next - while cur_node is not self.__dump and cur_node.key != value: - cur_node = cur_node.next + cur_node = self.__dump.next_node + while cur_node is not self.__dump and cur_node.value != value: + cur_node = cur_node.next_node + # 如果不是空链表,那么就是查找到了相应的元素 if cur_node is not self.__dump: - cur_node.prev.next = cur_node.next - cur_node.next.prev = cur_node.prev + cur_node.prev.next_node = cur_node.next_node + cur_node.next_node.prev = cur_node.prev + self.__length -= 1 - return cur_node.key + return cur_node.value def __len__(self): return self.__length def __str__(self): - cur_node = self.__dump.next + cur_node = self.__dump.next_node li = [] while cur_node is not self.__dump: li.append(str(cur_node)) - cur_node = cur_node.next + cur_node = cur_node.next_node return '[' + ", ".join(li) + ']' @@ -103,10 +109,20 @@ def main(): li.delete(5050) print li li = LinkedList() - for x in xrange(1, 10): + for x in range(1, 10): li.insert(0, x) print li + li = LinkedList() + for x in range(1, 10): + li.append(x) + print li + + li = LinkedList() + for x in range(1, 10): + li.prepend(x) + print li + if __name__ == '__main__': main() From 75b666584618d1616d009dbe82e1754c8c083820 Mon Sep 17 00:00:00 2001 From: shengshijun Date: Sun, 19 Jul 2015 21:48:06 +0800 Subject: [PATCH 05/23] =?UTF-8?q?1,=20=E5=8F=8C=E5=90=91=E9=93=BE=E8=A1=A8?= =?UTF-8?q?=E4=B8=AD=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A.=202,=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hashtable/__init__.py | 3 -- src/list/__init__.py | 4 +++ src/list/linked_list.py | 32 +++++++++++++++++-- src/map/__init__.py | 6 ++++ src/{hashtable/HashMap.py => map/hash_map.py} | 0 .../open_address_map.py} | 0 6 files changed, 39 insertions(+), 6 deletions(-) delete mode 100644 src/hashtable/__init__.py create mode 100644 src/map/__init__.py rename src/{hashtable/HashMap.py => map/hash_map.py} (100%) rename src/{hashtable/OpenAddressMap.py => map/open_address_map.py} (100%) diff --git a/src/hashtable/__init__.py b/src/hashtable/__init__.py deleted file mode 100644 index fb57e2f..0000000 --- a/src/hashtable/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -__author__ = 'shenshijun' diff --git a/src/list/__init__.py b/src/list/__init__.py index fb57e2f..6417397 100644 --- a/src/list/__init__.py +++ b/src/list/__init__.py @@ -1,3 +1,7 @@ #!/usr/bin/env python # -*- coding:UTF-8 __author__ = 'shenshijun' +from linked_list import LinkedList +from mutiarray_linkedlist import MultiArrayLinkedList +from skip_list import SkipList +from stack import Stack diff --git a/src/list/linked_list.py b/src/list/linked_list.py index 052676d..ff4cbd7 100644 --- a/src/list/linked_list.py +++ b/src/list/linked_list.py @@ -39,6 +39,12 @@ def __init__(self, *arg): self.append(value) def insert(self, index, value): + """ + 在列表的中间插入一个元素 + :param index: 要插入的位置 + :param value: 要插入的值 + :return: 插入值之后列表的大小 + """ if index > self.__length: raise IndexError("can not insert beyond the list") @@ -53,31 +59,51 @@ def insert(self, index, value): cur_node.prev = node prev_node.next_node = node self.__length += 1 - return node + return self.__length def append(self, value): + """ + 在列表的结尾插入一个元素 + :param value:要插入的元素 + :return: 插入之后列表的大小 + """ last_node = self.__dump.prev node = LinkedList.Node(value, last_node, self.__dump) # 现在结尾的节点指向新加的结尾点 last_node.next_node = node self.__dump.prev = node self.__length += 1 - return node + return self.__length def prepend(self, value): + """ + 在列表的最前面插入一个值 + :param value: 要插入的元素 + :return: 插入之后列表的大小 + """ node = LinkedList.Node(value, self.__dump, self.__dump.next_node) self.__dump.next_node.prev = node self.__dump.next_node = node self.__length += 1 - return node + return self.__length def search(self, value): + """ + 寻找一个元素是否存在于列表中 + :param value: 要寻找的元素 + :return: 如果没有,返回None;如果有,则返回找到的值 + """ cur_node = self.__dump.next_node while cur_node is not self.__dump and cur_node.value != value: cur_node = cur_node.next_node return cur_node.value def delete(self, value): + """ + 删除一个值 + :param value: 要删除的元素 + :return: 被删除的值 + """ cur_node = self.__dump.next_node while cur_node is not self.__dump and cur_node.value != value: cur_node = cur_node.next_node diff --git a/src/map/__init__.py b/src/map/__init__.py new file mode 100644 index 0000000..eee6022 --- /dev/null +++ b/src/map/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + +from hash_map import HashMap +from open_address_map import OpenAddressMap diff --git a/src/hashtable/HashMap.py b/src/map/hash_map.py similarity index 100% rename from src/hashtable/HashMap.py rename to src/map/hash_map.py diff --git a/src/hashtable/OpenAddressMap.py b/src/map/open_address_map.py similarity index 100% rename from src/hashtable/OpenAddressMap.py rename to src/map/open_address_map.py From 53510bfc8e67462fd01bfdb8944aaf6599aa0988 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sun, 20 Sep 2015 19:25:09 +0800 Subject: [PATCH 06/23] =?UTF-8?q?1,=20=E5=8F=8C=E5=90=91=E9=93=BE=E8=A1=A8?= =?UTF-8?q?=E4=B8=AD=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A.=202,=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++---- src/list/mutiarray_linkedlist.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 01c11be..d3a5605 100644 --- a/README.md +++ b/README.md @@ -92,10 +92,10 @@ algorithm 未来计划 ===================== -#在学习redis源码的过程中修改各个数据结构的实现,目的是使用更加精细的规则去提高数据结构的性能 -#添加更多注释并且格式化代码,注释中注重于设计的思考 -#添加算法导论中其他高级的数据结构 -#计划完成一些在线的题库 +* 在学习redis源码的过程中修改各个数据结构的实现,目的是使用更加精细的规则去提高数据结构的性能 +* 添加更多注释并且格式化代码,注释中注重于设计的思考 +* 添加算法导论中其他高级的数据结构 +* 计划完成一些在线的题库 diff --git a/src/list/mutiarray_linkedlist.py b/src/list/mutiarray_linkedlist.py index 3b638a9..265c6d0 100644 --- a/src/list/mutiarray_linkedlist.py +++ b/src/list/mutiarray_linkedlist.py @@ -17,7 +17,7 @@ def __init__(self, length): super(MultiArrayLinkedList, self).__init__() self.__empty = self.EmptyNode() self.__cap = length - self.__lenght = 0 + self.__length = 0 self.__key = [self.__empty for x in xrange(0, length + 1)] self.__prev = [-1 for x in xrange(0, length + 1)] self.__next = [x + 1 for x in xrange(0, length + 1)] # next数组在节点为空的时候存储的是下一个空节点的位置 From 36d87744bf4c9911f50c10f9a820dbec63455dfd Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sun, 20 Sep 2015 21:55:14 +0800 Subject: [PATCH 07/23] =?UTF-8?q?=E5=AE=8C=E6=88=90leecode=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E4=B8=A4=E4=B8=AA=E9=A2=98=E7=9B=AE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/leecode/__init__.py | 3 ++ src/leecode/add_two_numbers.py | 75 ++++++++++++++++++++++++++++++++++ src/leecode/two_sum.py | 68 ++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 src/leecode/__init__.py create mode 100644 src/leecode/add_two_numbers.py create mode 100644 src/leecode/two_sum.py diff --git a/README.md b/README.md index d3a5605..c4e58ec 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ algorithm * 在学习redis源码的过程中修改各个数据结构的实现,目的是使用更加精细的规则去提高数据结构的性能 * 添加更多注释并且格式化代码,注释中注重于设计的思考 * 添加算法导论中其他高级的数据结构 -* 计划完成一些在线的题库 +* 计划完成一些在线的题库,比如leecode和projecteuler diff --git a/src/leecode/__init__.py b/src/leecode/__init__.py new file mode 100644 index 0000000..286f8de --- /dev/null +++ b/src/leecode/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +#-*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/src/leecode/add_two_numbers.py b/src/leecode/add_two_numbers.py new file mode 100644 index 0000000..60b3d17 --- /dev/null +++ b/src/leecode/add_two_numbers.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. + +Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) +Output: 7 -> 0 -> 8 +""" + + +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + + +class Solution(object): + def __addUpDigit(self, node, up_digit): + last_node = None + while node is not None and up_digit > 0: + node.val += up_digit + if node.val >= 10: + node.val -= 10 + up_digit = 1 + else: + up_digit = 0 + last_node = node + node = node.next + if up_digit > 0 and last_node: + last_node.next = ListNode(up_digit) + + def addTwoNumbers(self, l1, l2): + """ + :type l1: ListNode + :type l2: ListNode + :rtype: ListNode + """ + cur_l1 = l1 + cur_l2 = l2 + last_l1 = None + last_up_digit = 0 + while cur_l1 is not None and cur_l2 is not None: + this_val = cur_l1.val + cur_l2.val + last_up_digit + if this_val >= 10: + cur_l1.val = this_val - 10 + last_up_digit = 1 + else: + cur_l1.val = this_val + last_up_digit = 0 + last_l1 = cur_l1 + cur_l1 = cur_l1.next + cur_l2 = cur_l2.next + + if cur_l1 is None and cur_l2 is None and last_up_digit > 0 and last_l1 is not None: + last_l1.next = ListNode(last_up_digit) + self.__addUpDigit(cur_l1, last_up_digit) + self.__addUpDigit(cur_l2, last_up_digit) + + # 如果l1比较短,需要把l2长的部分合并到l1后面 + if cur_l2 is not None: + if last_l1 is None: + return l2 + else: + last_l1.next = cur_l2 + + return l1 + + +def main(): + pass + + +if __name__ == "__main__": + main() diff --git a/src/leecode/two_sum.py b/src/leecode/two_sum.py new file mode 100644 index 0000000..3808b47 --- /dev/null +++ b/src/leecode/two_sum.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +""" +Given an array of integers, find two numbers such that they add up to a specific target number. +The function twoSum should return indices of the two numbers such that they add up to the target, +where index1 must be less than index2.Please note that your returned answers (both index1 and index2) are not zero-based. + +You may assume that each input would have exactly one solution. + +Input: numbers={2, 7, 11, 15}, target=9 +Output: index1=1, index2=2 +""" + +__author__ = 'shenshijun' + +""" +本题有两个思路: +一: 利用排序和二分查找 +先排序得到一个排序的数列,复杂度是O(nlgn),然后遍历数列,每遍历到一个元素的时候使用二分查询查找另外一个数字是否存在,复杂度仍然是O(nlgn) + +二: 使用hash表 +思路一为了快速查找而把数据都排了序,为了查找,显然可以使用hash表.而hash表是更高效的实现.一遍完成,因此复杂度是O(n) +""" + + +class Solution(object): + def twoSum(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + d = {} + for ind, num in enumerate(nums): + # 为了防止列表中出现重复的数,并且保证列表前面的index比后面的index小 + if num in d: + if type(d[num]) is list: + d[num].append(ind) + else: + d[num] = [d[num], ind] + else: + d[num] = ind + + for num, ind in d.iteritems(): + # 注意:要同时考虑ind和d[other_part]都为list的情况 + # 还要考虑,找到的index不能是同一个,并且不能重复 + this_indexs = ind if type(ind) == list else [ind] + other_part = target - num + for this_index in this_indexs: + if other_part in d: + if type(d[other_part]) == list: + for other_index in d[other_part]: + if other_index != this_index: + return [min(other_index, this_index) + 1, max(other_index, this_index) + 1] + elif d[other_part] != this_index: + return [min(d[other_part], this_index) + 1, max(d[other_part], this_index) + 1] + + return [-1, -1] + + +def main(): + print(Solution().twoSum([0, 4, 3, 0], 0)) + print(Solution().twoSum([2, 7, 11, 15], 9)) + print(Solution().twoSum([-3, 4, 3, 90], 0)) + + +if __name__ == "__main__": + main() From 3a21bea02feeb81051a86c4223f8c5ab85c3b230 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Thu, 24 Sep 2015 09:14:47 +0800 Subject: [PATCH 08/23] =?UTF-8?q?1,=E5=AE=8C=E6=88=90leecode=E7=9A=84?= =?UTF-8?q?=E7=AC=AC=E4=B8=89=E9=A2=98=EF=BC=8C=E7=AC=AC=E5=9B=9B=E9=A2=98?= =?UTF-8?q?=E8=BF=98=E6=9C=89bug=202,=E6=8A=8A=E6=89=80=E6=9C=89=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=94=BE=E5=9C=A8ssj=E5=8C=85=E4=B8=8B?= =?UTF-8?q?=EF=BC=8C=E5=9B=A0=E4=B8=BA=E4=B8=80=E4=BA=9B=E5=8C=85=E7=9A=84?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E8=B7=9Fpython=E8=87=AA=E5=B8=A6=E5=BA=93?= =?UTF-8?q?=E6=98=8E=E5=90=8D=E9=87=8D=E5=A4=8D=EF=BC=8C=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E4=BC=9A=E5=87=BA=E7=8E=B0=E4=B8=80=E4=BA=9B=E6=84=8F=E6=83=B3?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/{leecode => ssj}/__init__.py | 0 src/{ => ssj}/clrs/9/9-2(b).py | 0 src/{ => ssj}/clrs/9/9-2(c).py | 0 src/{ => ssj}/clrs/9/__init__.py | 0 src/{ => ssj}/clrs/__init__.py | 0 src/{ => ssj}/divide_conquer/__init__.py | 0 .../divide_conquer/find_max_sublist.py | 10 +- .../find_max_sublist_without_ recursion.py | 0 src/{ => ssj}/divide_conquer/power.py | 0 src/{ => ssj}/divide_conquer/yong_matrix.py | 0 src/{ => ssj}/dynamic/__init__.py | 0 src/{ => ssj}/dynamic/fabo/__init__.py | 0 src/{ => ssj}/dynamic/fabo/fabo_loop.py | 0 src/{ => ssj}/dynamic/fabo/fabo_math.py | 0 src/{ => ssj}/dynamic/fabo/fabo_up_down.py | 0 src/{ => ssj}/dynamic/lcs/__init__.py | 0 src/{ => ssj}/dynamic/lcs/down_up.py | 0 src/{ => ssj}/dynamic/lcs/up_down.py | 0 src/{ => ssj}/dynamic/lps/__init__.py | 0 src/{ => ssj}/dynamic/lps/down_up.py | 0 src/{ => ssj}/dynamic/lps/up_down.py | 0 src/{ => ssj}/dynamic/task/__init__.py | 0 .../dynamic/task/max_weighted_action.py | 0 src/{ => ssj}/graph/__init__.py | 0 src/{ => ssj}/graph/general_graph.py | 4 +- src/{ => ssj}/graph/weighted_graph.py | 2 +- src/{ => ssj}/greedy/__init__.py | 0 src/{ => ssj}/greedy/max_task_count.py | 0 src/{ => ssj}/heap/__init__.py | 0 src/{ => ssj}/heap/max_heap.py | 0 src/{ => ssj}/heap/max_queue.py | 0 src/{string => ssj/leecode}/__init__.py | 2 +- src/{ => ssj}/leecode/add_two_numbers.py | 0 src/ssj/leecode/find_median_sorted_arrays.py | 86 ++++ src/ssj/leecode/longest_substring.py | 58 +++ src/{ => ssj}/leecode/two_sum.py | 0 src/{ => ssj}/lib/__init__.py | 0 src/{ => ssj}/lib/queue.py | 0 src/{ => ssj}/lib/set.py | 0 src/{ => ssj}/lib/stack.py | 0 src/{ => ssj}/list/__init__.py | 0 src/{ => ssj}/list/linked_list.py | 0 src/{ => ssj}/list/mutiarray_linkedlist.py | 0 src/{ => ssj}/list/skip_list.py | 0 src/{ => ssj}/list/stack.py | 0 src/{ => ssj}/map/__init__.py | 0 src/{ => ssj}/map/hash_map.py | 2 +- src/{ => ssj}/map/open_address_map.py | 0 src/{ => ssj}/matrix/__init__.py | 0 src/{ => ssj}/matrix/strassen_matrix.py | 0 src/{ => ssj}/number_theory/__init__.py | 0 src/{ => ssj}/number_theory/gcd.py | 0 src/{ => ssj}/queue/__init__.py | 0 src/{ => ssj}/queue/fifo_queue.py | 0 src/{ => ssj}/queue/list_queue.py | 0 src/{ => ssj}/search/__init__.py | 0 src/{ => ssj}/search/binary_search.py | 0 src/{ => ssj}/search/find_kth_with_middle.py | 0 .../search/find_middle_of_two_sorted_array.py | 0 src/{ => ssj}/search/find_min_max.py | 0 src/{ => ssj}/search/find_sum_equals.py | 0 src/{ => ssj}/search/random_loop_section.py | 0 src/{ => ssj}/search/random_selection.py | 0 src/{ => ssj}/search/split_nth.py | 0 ...4\347\244\272\346\204\217\345\233\276.png" | Bin src/{ => ssj}/sort/__init__.py | 0 src/{ => ssj}/sort/bubble_sort.py | 0 src/{ => ssj}/sort/bucketsort.png | Bin src/{ => ssj}/sort/counting_sort.py | 0 src/{ => ssj}/sort/countingsort.png | Bin src/{ => ssj}/sort/fuzzy_space_quick_sort.py | 0 src/{ => ssj}/sort/heap_sort.py | 0 src/{ => ssj}/sort/hoare_quick_sort.py | 0 .../sort/improve_fuzzy_space_quick_sort.py | 0 src/{ => ssj}/sort/insert_sort.py | 0 src/{ => ssj}/sort/merge_sort.py | 0 src/{ => ssj}/sort/quick_sort.py | 0 src/{ => ssj}/sort/random_quick_sort.py | 0 .../sort/random_two_partition_quick_sort.py | 0 src/{ => ssj}/sort/recursive_insert_sort.py | 0 src/{ => ssj}/sort/select_sort.py | 0 src/string/kmp.py | 40 -- src/string/rabin-karp.py | 46 -- src/string/simple.py | 30 -- src/tree/BTree.py | 201 -------- src/tree/__init__.py | 3 - src/tree/avltree.py | 11 - src/tree/binarystree.py | 252 ---------- src/tree/binarytree.py | 117 ----- src/tree/interval_tree.py | 411 ---------------- src/tree/lchild_rbro_tree.py | 118 ----- src/tree/order_statistic_tree.py | 452 ------------------ src/tree/red_black_tree.py | 375 --------------- src/tree/tries.py | 13 - 94 files changed, 154 insertions(+), 2079 deletions(-) rename src/{leecode => ssj}/__init__.py (100%) rename src/{ => ssj}/clrs/9/9-2(b).py (100%) rename src/{ => ssj}/clrs/9/9-2(c).py (100%) rename src/{ => ssj}/clrs/9/__init__.py (100%) rename src/{ => ssj}/clrs/__init__.py (100%) rename src/{ => ssj}/divide_conquer/__init__.py (100%) rename src/{ => ssj}/divide_conquer/find_max_sublist.py (90%) rename src/{ => ssj}/divide_conquer/find_max_sublist_without_ recursion.py (100%) rename src/{ => ssj}/divide_conquer/power.py (100%) rename src/{ => ssj}/divide_conquer/yong_matrix.py (100%) rename src/{ => ssj}/dynamic/__init__.py (100%) rename src/{ => ssj}/dynamic/fabo/__init__.py (100%) rename src/{ => ssj}/dynamic/fabo/fabo_loop.py (100%) rename src/{ => ssj}/dynamic/fabo/fabo_math.py (100%) rename src/{ => ssj}/dynamic/fabo/fabo_up_down.py (100%) rename src/{ => ssj}/dynamic/lcs/__init__.py (100%) rename src/{ => ssj}/dynamic/lcs/down_up.py (100%) rename src/{ => ssj}/dynamic/lcs/up_down.py (100%) rename src/{ => ssj}/dynamic/lps/__init__.py (100%) rename src/{ => ssj}/dynamic/lps/down_up.py (100%) rename src/{ => ssj}/dynamic/lps/up_down.py (100%) rename src/{ => ssj}/dynamic/task/__init__.py (100%) rename src/{ => ssj}/dynamic/task/max_weighted_action.py (100%) rename src/{ => ssj}/graph/__init__.py (100%) rename src/{ => ssj}/graph/general_graph.py (99%) rename src/{ => ssj}/graph/weighted_graph.py (99%) rename src/{ => ssj}/greedy/__init__.py (100%) rename src/{ => ssj}/greedy/max_task_count.py (100%) rename src/{ => ssj}/heap/__init__.py (100%) rename src/{ => ssj}/heap/max_heap.py (100%) rename src/{ => ssj}/heap/max_queue.py (100%) rename src/{string => ssj/leecode}/__init__.py (71%) rename src/{ => ssj}/leecode/add_two_numbers.py (100%) create mode 100644 src/ssj/leecode/find_median_sorted_arrays.py create mode 100644 src/ssj/leecode/longest_substring.py rename src/{ => ssj}/leecode/two_sum.py (100%) rename src/{ => ssj}/lib/__init__.py (100%) rename src/{ => ssj}/lib/queue.py (100%) rename src/{ => ssj}/lib/set.py (100%) rename src/{ => ssj}/lib/stack.py (100%) rename src/{ => ssj}/list/__init__.py (100%) rename src/{ => ssj}/list/linked_list.py (100%) rename src/{ => ssj}/list/mutiarray_linkedlist.py (100%) rename src/{ => ssj}/list/skip_list.py (100%) rename src/{ => ssj}/list/stack.py (100%) rename src/{ => ssj}/map/__init__.py (100%) rename src/{ => ssj}/map/hash_map.py (98%) rename src/{ => ssj}/map/open_address_map.py (100%) rename src/{ => ssj}/matrix/__init__.py (100%) rename src/{ => ssj}/matrix/strassen_matrix.py (100%) rename src/{ => ssj}/number_theory/__init__.py (100%) rename src/{ => ssj}/number_theory/gcd.py (100%) rename src/{ => ssj}/queue/__init__.py (100%) rename src/{ => ssj}/queue/fifo_queue.py (100%) rename src/{ => ssj}/queue/list_queue.py (100%) rename src/{ => ssj}/search/__init__.py (100%) rename src/{ => ssj}/search/binary_search.py (100%) rename src/{ => ssj}/search/find_kth_with_middle.py (100%) rename src/{ => ssj}/search/find_middle_of_two_sorted_array.py (100%) rename src/{ => ssj}/search/find_min_max.py (100%) rename src/{ => ssj}/search/find_sum_equals.py (100%) rename src/{ => ssj}/search/random_loop_section.py (100%) rename src/{ => ssj}/search/random_selection.py (100%) rename src/{ => ssj}/search/split_nth.py (100%) rename "src/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" => "src/ssj/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" (100%) rename src/{ => ssj}/sort/__init__.py (100%) rename src/{ => ssj}/sort/bubble_sort.py (100%) rename src/{ => ssj}/sort/bucketsort.png (100%) rename src/{ => ssj}/sort/counting_sort.py (100%) rename src/{ => ssj}/sort/countingsort.png (100%) rename src/{ => ssj}/sort/fuzzy_space_quick_sort.py (100%) rename src/{ => ssj}/sort/heap_sort.py (100%) rename src/{ => ssj}/sort/hoare_quick_sort.py (100%) rename src/{ => ssj}/sort/improve_fuzzy_space_quick_sort.py (100%) rename src/{ => ssj}/sort/insert_sort.py (100%) rename src/{ => ssj}/sort/merge_sort.py (100%) rename src/{ => ssj}/sort/quick_sort.py (100%) rename src/{ => ssj}/sort/random_quick_sort.py (100%) rename src/{ => ssj}/sort/random_two_partition_quick_sort.py (100%) rename src/{ => ssj}/sort/recursive_insert_sort.py (100%) rename src/{ => ssj}/sort/select_sort.py (100%) delete mode 100644 src/string/kmp.py delete mode 100644 src/string/rabin-karp.py delete mode 100644 src/string/simple.py delete mode 100644 src/tree/BTree.py delete mode 100644 src/tree/__init__.py delete mode 100644 src/tree/avltree.py delete mode 100644 src/tree/binarystree.py delete mode 100644 src/tree/binarytree.py delete mode 100644 src/tree/interval_tree.py delete mode 100644 src/tree/lchild_rbro_tree.py delete mode 100644 src/tree/order_statistic_tree.py delete mode 100644 src/tree/red_black_tree.py delete mode 100644 src/tree/tries.py diff --git a/src/leecode/__init__.py b/src/ssj/__init__.py similarity index 100% rename from src/leecode/__init__.py rename to src/ssj/__init__.py diff --git a/src/clrs/9/9-2(b).py b/src/ssj/clrs/9/9-2(b).py similarity index 100% rename from src/clrs/9/9-2(b).py rename to src/ssj/clrs/9/9-2(b).py diff --git a/src/clrs/9/9-2(c).py b/src/ssj/clrs/9/9-2(c).py similarity index 100% rename from src/clrs/9/9-2(c).py rename to src/ssj/clrs/9/9-2(c).py diff --git a/src/clrs/9/__init__.py b/src/ssj/clrs/9/__init__.py similarity index 100% rename from src/clrs/9/__init__.py rename to src/ssj/clrs/9/__init__.py diff --git a/src/clrs/__init__.py b/src/ssj/clrs/__init__.py similarity index 100% rename from src/clrs/__init__.py rename to src/ssj/clrs/__init__.py diff --git a/src/divide_conquer/__init__.py b/src/ssj/divide_conquer/__init__.py similarity index 100% rename from src/divide_conquer/__init__.py rename to src/ssj/divide_conquer/__init__.py diff --git a/src/divide_conquer/find_max_sublist.py b/src/ssj/divide_conquer/find_max_sublist.py similarity index 90% rename from src/divide_conquer/find_max_sublist.py rename to src/ssj/divide_conquer/find_max_sublist.py index 8d46eca..71104a0 100755 --- a/src/divide_conquer/find_max_sublist.py +++ b/src/ssj/divide_conquer/find_max_sublist.py @@ -13,17 +13,17 @@ def find_max_sublist(li): li_len = len(li) if li_len < 2: - return (0, 0, sum(li)) + return 0, 0, sum(li) middle = li_len / 2 m_x, m_y, m_sum = find_max_in_middle(li, middle) l_x, l_y, l_sum = find_max_sublist(li[:middle]) r_x, r_y, r_sum = find_max_sublist(li[middle + 1:]) if m_sum >= l_sum and m_sum >= r_sum: - return (m_x, m_y, m_sum) + return m_x, m_y, m_sum elif l_sum >= m_sum and l_sum >= r_sum: - return (l_x, l_y, l_sum) + return l_x, l_y, l_sum else: - return (r_x, r_y, r_sum) + return r_x, r_y, r_sum """ @@ -53,7 +53,7 @@ def find_max_in_middle(li, middle): right_max_sum = cur_sum right_max_index = x # 这里并没有判断一端结果为负的情况,因为这个时候可以在其中一端的列表中得到最大子数列 - return (left_max_index, right_max_index, right_max_sum + left_max_sum) + return left_max_index, right_max_index, right_max_sum + left_max_sum def main(): diff --git a/src/divide_conquer/find_max_sublist_without_ recursion.py b/src/ssj/divide_conquer/find_max_sublist_without_ recursion.py similarity index 100% rename from src/divide_conquer/find_max_sublist_without_ recursion.py rename to src/ssj/divide_conquer/find_max_sublist_without_ recursion.py diff --git a/src/divide_conquer/power.py b/src/ssj/divide_conquer/power.py similarity index 100% rename from src/divide_conquer/power.py rename to src/ssj/divide_conquer/power.py diff --git a/src/divide_conquer/yong_matrix.py b/src/ssj/divide_conquer/yong_matrix.py similarity index 100% rename from src/divide_conquer/yong_matrix.py rename to src/ssj/divide_conquer/yong_matrix.py diff --git a/src/dynamic/__init__.py b/src/ssj/dynamic/__init__.py similarity index 100% rename from src/dynamic/__init__.py rename to src/ssj/dynamic/__init__.py diff --git a/src/dynamic/fabo/__init__.py b/src/ssj/dynamic/fabo/__init__.py similarity index 100% rename from src/dynamic/fabo/__init__.py rename to src/ssj/dynamic/fabo/__init__.py diff --git a/src/dynamic/fabo/fabo_loop.py b/src/ssj/dynamic/fabo/fabo_loop.py similarity index 100% rename from src/dynamic/fabo/fabo_loop.py rename to src/ssj/dynamic/fabo/fabo_loop.py diff --git a/src/dynamic/fabo/fabo_math.py b/src/ssj/dynamic/fabo/fabo_math.py similarity index 100% rename from src/dynamic/fabo/fabo_math.py rename to src/ssj/dynamic/fabo/fabo_math.py diff --git a/src/dynamic/fabo/fabo_up_down.py b/src/ssj/dynamic/fabo/fabo_up_down.py similarity index 100% rename from src/dynamic/fabo/fabo_up_down.py rename to src/ssj/dynamic/fabo/fabo_up_down.py diff --git a/src/dynamic/lcs/__init__.py b/src/ssj/dynamic/lcs/__init__.py similarity index 100% rename from src/dynamic/lcs/__init__.py rename to src/ssj/dynamic/lcs/__init__.py diff --git a/src/dynamic/lcs/down_up.py b/src/ssj/dynamic/lcs/down_up.py similarity index 100% rename from src/dynamic/lcs/down_up.py rename to src/ssj/dynamic/lcs/down_up.py diff --git a/src/dynamic/lcs/up_down.py b/src/ssj/dynamic/lcs/up_down.py similarity index 100% rename from src/dynamic/lcs/up_down.py rename to src/ssj/dynamic/lcs/up_down.py diff --git a/src/dynamic/lps/__init__.py b/src/ssj/dynamic/lps/__init__.py similarity index 100% rename from src/dynamic/lps/__init__.py rename to src/ssj/dynamic/lps/__init__.py diff --git a/src/dynamic/lps/down_up.py b/src/ssj/dynamic/lps/down_up.py similarity index 100% rename from src/dynamic/lps/down_up.py rename to src/ssj/dynamic/lps/down_up.py diff --git a/src/dynamic/lps/up_down.py b/src/ssj/dynamic/lps/up_down.py similarity index 100% rename from src/dynamic/lps/up_down.py rename to src/ssj/dynamic/lps/up_down.py diff --git a/src/dynamic/task/__init__.py b/src/ssj/dynamic/task/__init__.py similarity index 100% rename from src/dynamic/task/__init__.py rename to src/ssj/dynamic/task/__init__.py diff --git a/src/dynamic/task/max_weighted_action.py b/src/ssj/dynamic/task/max_weighted_action.py similarity index 100% rename from src/dynamic/task/max_weighted_action.py rename to src/ssj/dynamic/task/max_weighted_action.py diff --git a/src/graph/__init__.py b/src/ssj/graph/__init__.py similarity index 100% rename from src/graph/__init__.py rename to src/ssj/graph/__init__.py diff --git a/src/graph/general_graph.py b/src/ssj/graph/general_graph.py similarity index 99% rename from src/graph/general_graph.py rename to src/ssj/graph/general_graph.py index e1b6e1f..b9f8871 100644 --- a/src/graph/general_graph.py +++ b/src/ssj/graph/general_graph.py @@ -6,8 +6,8 @@ reload(sys) sys.setdefaultencoding('UTF-8') -from lib import queue -from lib.stack import Stack +from ssj.lib import queue +from ssj.lib import Stack __author__ = 'shenshijun' diff --git a/src/graph/weighted_graph.py b/src/ssj/graph/weighted_graph.py similarity index 99% rename from src/graph/weighted_graph.py rename to src/ssj/graph/weighted_graph.py index 1cbc1e9..41bc024 100644 --- a/src/graph/weighted_graph.py +++ b/src/ssj/graph/weighted_graph.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from lib.queue import Queue +from ssj.lib import Queue __author__ = 'shenshijun' """ diff --git a/src/greedy/__init__.py b/src/ssj/greedy/__init__.py similarity index 100% rename from src/greedy/__init__.py rename to src/ssj/greedy/__init__.py diff --git a/src/greedy/max_task_count.py b/src/ssj/greedy/max_task_count.py similarity index 100% rename from src/greedy/max_task_count.py rename to src/ssj/greedy/max_task_count.py diff --git a/src/heap/__init__.py b/src/ssj/heap/__init__.py similarity index 100% rename from src/heap/__init__.py rename to src/ssj/heap/__init__.py diff --git a/src/heap/max_heap.py b/src/ssj/heap/max_heap.py similarity index 100% rename from src/heap/max_heap.py rename to src/ssj/heap/max_heap.py diff --git a/src/heap/max_queue.py b/src/ssj/heap/max_queue.py similarity index 100% rename from src/heap/max_queue.py rename to src/ssj/heap/max_queue.py diff --git a/src/string/__init__.py b/src/ssj/leecode/__init__.py similarity index 71% rename from src/string/__init__.py rename to src/ssj/leecode/__init__.py index fb57e2f..286f8de 100644 --- a/src/string/__init__.py +++ b/src/ssj/leecode/__init__.py @@ -1,3 +1,3 @@ #!/usr/bin/env python -# -*- coding:UTF-8 +#-*- coding:UTF-8 __author__ = 'shenshijun' diff --git a/src/leecode/add_two_numbers.py b/src/ssj/leecode/add_two_numbers.py similarity index 100% rename from src/leecode/add_two_numbers.py rename to src/ssj/leecode/add_two_numbers.py diff --git a/src/ssj/leecode/find_median_sorted_arrays.py b/src/ssj/leecode/find_median_sorted_arrays.py new file mode 100644 index 0000000..f7dc618 --- /dev/null +++ b/src/ssj/leecode/find_median_sorted_arrays.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). +""" +""" +思路一:遍历一遍就可以把两个数组排序,然后取中点的值就可以了,这样的复杂度是O(m+n) +思路二:排序显然做了许多无用功,因为只需要一个中间数就可以了 +参考:http://www.cnblogs.com/lichen782/p/leetcode_Median_of_Two_Sorted_Arrays.html +可以分成四种情况考虑 +1,两个列表都没有数据,那么返回0 +2,两个列表中只有一个列表有数据,那么返回其中一个列表的中间点 +3,两个列表中的一个列表整体大于另一个列表,那么可以在逻辑上把这两个列表合并起来求出合并后的中点 +4,问题可以简化成从两个排序列表中求出第k个数,也就是从两个数组的开头取出k个数字,这k个数字比留在数组中的数字要小 +那么可以开始从两个数组中取出k/2的数字(这样做每次可以把问题的规模减小一半,整体的复杂度也就是指数级的), +比较k/2位置处数字的大小,小的那一部分一定是在k小的数字之内(可以假设法证明),这样剩下的问题就是从剩下的列表中找 +第k/2位数了.等到这个数为1,那么就好计算了. + +""" + + +class Solution(object): + def findMedianSortedArrays(self, nums1, nums2): + """ + :type nums1: List[int] + :type nums2: List[int] + :rtype: float + """ + if not nums1: + return self.__findMedian(nums2) + elif not nums2: + return self.__findMedian(nums1) + elif not nums1 and not nums2: + return 0 + + len1 = len(nums1) + len2 = len(nums2) + + if (len1 + len2) % 2 is 0: + return (self.__findKth((len1 + len2) / 2 + 1, nums1, nums2) + self.__findKth((len1 + len2) / 2, nums1, + nums2)) / 2.0 + else: + return self.__findKth((len1 + len2) / 2 + 1, nums1, nums2) + + @staticmethod + def __findMedian(li): + median = len(li) / 2 + if len(li) % 2 is 0: + return (li[median] + li[median - 1]) / 2.0 + else: + return li[median] + + @staticmethod + def __findKth(k, l1, l2): + l1_start = 0 + l2_start = 0 + k -= 1 + while (len(l1) + len(l2) - l1_start - l2_start - 1) >= k: + if k is 0: + return min(l1[l1_start], l2[l2_start]) + if len(l1) - l1_start < len(l2) - l2_start: + l1_comp_start = l1_start + min(len(l1), k / 2) + l2_comp_start = k - min(len(l1), k / 2) + l2_start + else: + l2_comp_start = min(len(l2), k / 2) + l2_start + l1_comp_start = k - min(len(l2), k / 2) + l1_start + + if l1[l1_comp_start] > l2[l2_comp_start]: + k -= (l2_comp_start - l2_start) + l2_start = l2_comp_start + 1 + elif l1[l1_comp_start] < l2[l2_comp_start]: + k -= (l1_comp_start - l1_start) + l1_start = l1_comp_start + 1 + else: + return l1[l1_comp_start] + return 0 + + +def main(): + print(Solution().findMedianSortedArrays([0, 1, 2, 3, 4], [0, 1, 2])) # 1 + print(Solution().findMedianSortedArrays([], [1])) # + + +if __name__ == "__main__": + main() diff --git a/src/ssj/leecode/longest_substring.py b/src/ssj/leecode/longest_substring.py new file mode 100644 index 0000000..b9d4381 --- /dev/null +++ b/src/ssj/leecode/longest_substring.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + +""" +Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1. +""" + +""" +思路:使用两个指针来遍历字符串,他们之间的字符是不重复的字符.前面的指针每次前进一步都会判断新扫描的字符是不是和两个指针的间的字符重复 +s a f b r g r e g + ^ ^ + | |index +start_index +为了这个目的,使用了哈希表. +如果重复,那么就找到一个连续的非重复字符串,这里就是afbrg(index现在在r的位置),判断这个字符串长度和已有的最大长度的大小, +并且记录下最大值.发生重复之后的处理非常重要,是把前面重复的部分丢弃掉,这样后面的字符串还是一个非重复的字符串(start_index在g的位置) +这样的目的是尽量构建一个长的非重复字符串 + +如果没有重复,那么就把字符和对应的索引放入哈希表,以备后面使用 + +如果限定了字符集,那么可以使用数组来模拟哈希表,这样的效率更高. +""" + + +class Solution(object): + def lengthOfLongestSubstring(self, s): + """ + :type s: str + :rtype: int + """ + if not s: + return 0 + tmp_dict = {} + # 字符串不为空,因此最小值是1 + max_length = 1 + start_index = 0 + for index, ch in enumerate(s): + if ch in tmp_dict: + if max_length < index - start_index: + max_length = index - start_index + dup_index = tmp_dict[ch] + for i in range(start_index, dup_index + 1): + del tmp_dict[s[i]] + start_index = dup_index + 1 + tmp_dict[ch] = index + # 注意结束的时候如果没有重复,那么会安静退出循环而不发生任何比较,所以在退出循环的时候要比较 + return len(tmp_dict) if len(tmp_dict) > max_length else max_length + + +def main(): + print(Solution().lengthOfLongestSubstring("bbbbbb")) # 1 + print(Solution().lengthOfLongestSubstring("abcabcbb")) # 3 + print(Solution().lengthOfLongestSubstring("dvdfefqwfqwef")) # 3 + + +if __name__ == "__main__": + main() diff --git a/src/leecode/two_sum.py b/src/ssj/leecode/two_sum.py similarity index 100% rename from src/leecode/two_sum.py rename to src/ssj/leecode/two_sum.py diff --git a/src/lib/__init__.py b/src/ssj/lib/__init__.py similarity index 100% rename from src/lib/__init__.py rename to src/ssj/lib/__init__.py diff --git a/src/lib/queue.py b/src/ssj/lib/queue.py similarity index 100% rename from src/lib/queue.py rename to src/ssj/lib/queue.py diff --git a/src/lib/set.py b/src/ssj/lib/set.py similarity index 100% rename from src/lib/set.py rename to src/ssj/lib/set.py diff --git a/src/lib/stack.py b/src/ssj/lib/stack.py similarity index 100% rename from src/lib/stack.py rename to src/ssj/lib/stack.py diff --git a/src/list/__init__.py b/src/ssj/list/__init__.py similarity index 100% rename from src/list/__init__.py rename to src/ssj/list/__init__.py diff --git a/src/list/linked_list.py b/src/ssj/list/linked_list.py similarity index 100% rename from src/list/linked_list.py rename to src/ssj/list/linked_list.py diff --git a/src/list/mutiarray_linkedlist.py b/src/ssj/list/mutiarray_linkedlist.py similarity index 100% rename from src/list/mutiarray_linkedlist.py rename to src/ssj/list/mutiarray_linkedlist.py diff --git a/src/list/skip_list.py b/src/ssj/list/skip_list.py similarity index 100% rename from src/list/skip_list.py rename to src/ssj/list/skip_list.py diff --git a/src/list/stack.py b/src/ssj/list/stack.py similarity index 100% rename from src/list/stack.py rename to src/ssj/list/stack.py diff --git a/src/map/__init__.py b/src/ssj/map/__init__.py similarity index 100% rename from src/map/__init__.py rename to src/ssj/map/__init__.py diff --git a/src/map/hash_map.py b/src/ssj/map/hash_map.py similarity index 98% rename from src/map/hash_map.py rename to src/ssj/map/hash_map.py index 9e831fd..0acf6e7 100644 --- a/src/map/hash_map.py +++ b/src/ssj/map/hash_map.py @@ -12,7 +12,7 @@ class HashMap(object): # 来自算法导论乘法哈希函数的值,暂时仅支持2**32个元素 HASH_CONST = 2654435769 DEFAULT_SIZE_POWER = 3 - DEFAULT_SIZE = 2 << DEFAULT_SIZE_POWER # aka16 + DEFAULT_SIZE = 2 << DEFAULT_SIZE_POWER # aka8 DEFAULT_LOAD_FACTOR = 0.75 # 默认装载因子0.75 class Node(object): diff --git a/src/map/open_address_map.py b/src/ssj/map/open_address_map.py similarity index 100% rename from src/map/open_address_map.py rename to src/ssj/map/open_address_map.py diff --git a/src/matrix/__init__.py b/src/ssj/matrix/__init__.py similarity index 100% rename from src/matrix/__init__.py rename to src/ssj/matrix/__init__.py diff --git a/src/matrix/strassen_matrix.py b/src/ssj/matrix/strassen_matrix.py similarity index 100% rename from src/matrix/strassen_matrix.py rename to src/ssj/matrix/strassen_matrix.py diff --git a/src/number_theory/__init__.py b/src/ssj/number_theory/__init__.py similarity index 100% rename from src/number_theory/__init__.py rename to src/ssj/number_theory/__init__.py diff --git a/src/number_theory/gcd.py b/src/ssj/number_theory/gcd.py similarity index 100% rename from src/number_theory/gcd.py rename to src/ssj/number_theory/gcd.py diff --git a/src/queue/__init__.py b/src/ssj/queue/__init__.py similarity index 100% rename from src/queue/__init__.py rename to src/ssj/queue/__init__.py diff --git a/src/queue/fifo_queue.py b/src/ssj/queue/fifo_queue.py similarity index 100% rename from src/queue/fifo_queue.py rename to src/ssj/queue/fifo_queue.py diff --git a/src/queue/list_queue.py b/src/ssj/queue/list_queue.py similarity index 100% rename from src/queue/list_queue.py rename to src/ssj/queue/list_queue.py diff --git a/src/search/__init__.py b/src/ssj/search/__init__.py similarity index 100% rename from src/search/__init__.py rename to src/ssj/search/__init__.py diff --git a/src/search/binary_search.py b/src/ssj/search/binary_search.py similarity index 100% rename from src/search/binary_search.py rename to src/ssj/search/binary_search.py diff --git a/src/search/find_kth_with_middle.py b/src/ssj/search/find_kth_with_middle.py similarity index 100% rename from src/search/find_kth_with_middle.py rename to src/ssj/search/find_kth_with_middle.py diff --git a/src/search/find_middle_of_two_sorted_array.py b/src/ssj/search/find_middle_of_two_sorted_array.py similarity index 100% rename from src/search/find_middle_of_two_sorted_array.py rename to src/ssj/search/find_middle_of_two_sorted_array.py diff --git a/src/search/find_min_max.py b/src/ssj/search/find_min_max.py similarity index 100% rename from src/search/find_min_max.py rename to src/ssj/search/find_min_max.py diff --git a/src/search/find_sum_equals.py b/src/ssj/search/find_sum_equals.py similarity index 100% rename from src/search/find_sum_equals.py rename to src/ssj/search/find_sum_equals.py diff --git a/src/search/random_loop_section.py b/src/ssj/search/random_loop_section.py similarity index 100% rename from src/search/random_loop_section.py rename to src/ssj/search/random_loop_section.py diff --git a/src/search/random_selection.py b/src/ssj/search/random_selection.py similarity index 100% rename from src/search/random_selection.py rename to src/ssj/search/random_selection.py diff --git a/src/search/split_nth.py b/src/ssj/search/split_nth.py similarity index 100% rename from src/search/split_nth.py rename to src/ssj/search/split_nth.py diff --git "a/src/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" "b/src/ssj/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" similarity index 100% rename from "src/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" rename to "src/ssj/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" diff --git a/src/sort/__init__.py b/src/ssj/sort/__init__.py similarity index 100% rename from src/sort/__init__.py rename to src/ssj/sort/__init__.py diff --git a/src/sort/bubble_sort.py b/src/ssj/sort/bubble_sort.py similarity index 100% rename from src/sort/bubble_sort.py rename to src/ssj/sort/bubble_sort.py diff --git a/src/sort/bucketsort.png b/src/ssj/sort/bucketsort.png similarity index 100% rename from src/sort/bucketsort.png rename to src/ssj/sort/bucketsort.png diff --git a/src/sort/counting_sort.py b/src/ssj/sort/counting_sort.py similarity index 100% rename from src/sort/counting_sort.py rename to src/ssj/sort/counting_sort.py diff --git a/src/sort/countingsort.png b/src/ssj/sort/countingsort.png similarity index 100% rename from src/sort/countingsort.png rename to src/ssj/sort/countingsort.png diff --git a/src/sort/fuzzy_space_quick_sort.py b/src/ssj/sort/fuzzy_space_quick_sort.py similarity index 100% rename from src/sort/fuzzy_space_quick_sort.py rename to src/ssj/sort/fuzzy_space_quick_sort.py diff --git a/src/sort/heap_sort.py b/src/ssj/sort/heap_sort.py similarity index 100% rename from src/sort/heap_sort.py rename to src/ssj/sort/heap_sort.py diff --git a/src/sort/hoare_quick_sort.py b/src/ssj/sort/hoare_quick_sort.py similarity index 100% rename from src/sort/hoare_quick_sort.py rename to src/ssj/sort/hoare_quick_sort.py diff --git a/src/sort/improve_fuzzy_space_quick_sort.py b/src/ssj/sort/improve_fuzzy_space_quick_sort.py similarity index 100% rename from src/sort/improve_fuzzy_space_quick_sort.py rename to src/ssj/sort/improve_fuzzy_space_quick_sort.py diff --git a/src/sort/insert_sort.py b/src/ssj/sort/insert_sort.py similarity index 100% rename from src/sort/insert_sort.py rename to src/ssj/sort/insert_sort.py diff --git a/src/sort/merge_sort.py b/src/ssj/sort/merge_sort.py similarity index 100% rename from src/sort/merge_sort.py rename to src/ssj/sort/merge_sort.py diff --git a/src/sort/quick_sort.py b/src/ssj/sort/quick_sort.py similarity index 100% rename from src/sort/quick_sort.py rename to src/ssj/sort/quick_sort.py diff --git a/src/sort/random_quick_sort.py b/src/ssj/sort/random_quick_sort.py similarity index 100% rename from src/sort/random_quick_sort.py rename to src/ssj/sort/random_quick_sort.py diff --git a/src/sort/random_two_partition_quick_sort.py b/src/ssj/sort/random_two_partition_quick_sort.py similarity index 100% rename from src/sort/random_two_partition_quick_sort.py rename to src/ssj/sort/random_two_partition_quick_sort.py diff --git a/src/sort/recursive_insert_sort.py b/src/ssj/sort/recursive_insert_sort.py similarity index 100% rename from src/sort/recursive_insert_sort.py rename to src/ssj/sort/recursive_insert_sort.py diff --git a/src/sort/select_sort.py b/src/ssj/sort/select_sort.py similarity index 100% rename from src/sort/select_sort.py rename to src/ssj/sort/select_sort.py diff --git a/src/string/kmp.py b/src/string/kmp.py deleted file mode 100644 index e92a8f0..0000000 --- a/src/string/kmp.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -__author__ = 'shenshijun' - - -def match(origin, pattern): - origin_len = len(origin) - pattern_len = len(pattern) - - def build_next(): - _next_list = [0 for x in xrange(pattern_len)] - last_match = 0 - for cur_index in xrange(1, pattern_len): - while last_match > 0 and pattern[last_match] != pattern[cur_index]: - last_match = _next_list[last_match] - if pattern[last_match] == pattern[cur_index]: - last_match += 1 - _next_list[cur_index] = last_match - return _next_list - - origin_index, pattern_index = 0, 0 - next_list = build_next() - while origin_index < origin_len: - # while需要放在前面,如果放在后面的话且有匹配的情况下pattern[pattern_index]就会越界 - while pattern_index > 0 and origin[origin_index] != pattern[pattern_index]: - pattern_index = next_list[pattern_index] - if pattern[pattern_index] == origin[origin_index]: - pattern_index += 1 - origin_index += 1 - - if pattern_index == pattern_len: - return origin_index - pattern_len - - -def main(): - print match("assssbsss", 'sb') - - -if __name__ == "__main__": - main() diff --git a/src/string/rabin-karp.py b/src/string/rabin-karp.py deleted file mode 100644 index 0f327d1..0000000 --- a/src/string/rabin-karp.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -__author__ = 'shenshijun' -""" -首先计算pattern字符串的hash值,然后在从目标字符串的开头,计算相同长度字符串的hash值。若hash值相同,则表示匹配,若不同,则向右移动一位,计算新的hash值。整个过程,与暴力的字符串匹配算法很相似, -但由于计算hash值时,可以利用上一次的hash值,从而使新的hash值只需要加上新字母的计算,并减去上一次的第一个字母的计算,即可。 -Rabin-Karp算法的预处理时间为O(m),最坏情况下该算法的匹配时间为O((n-m+1)m),期望复杂度O(m+n) -""" - - -def match(origin, pattern): - pattern_len = len(pattern) - - def _hash(string, start=0): - hash_code = 0 - for x in xrange(pattern_len): - hash_code += ord(string[start + x]) * 2 ** (pattern_len - x - 1) - return hash_code - - def _refresh(old_hash, old_char, new_char): - return (old_hash - ord(old_char) * 2 ** (pattern_len - 1)) * 2 + ord(new_char) - - def test_equal(start_index): - for x in xrange(pattern_len): - if origin[x + start_index] != pattern[x]: - return False - return True - - origin_index = 0 - pattern_hash = _hash(pattern) - origin_hash = _hash(origin) - while origin_index < len(origin) - pattern_len - 1: - if pattern_hash == origin_hash and test_equal(origin_index): - return origin_index - else: - print "origin hash:%s,pattern hash:%s" % (origin_hash, pattern_hash) - origin_hash = _refresh(origin_hash, origin[origin_index], origin[origin_index + pattern_len]) - origin_index += 1 - - -def main(): - print match("sbsfsdgdgfgasbssssfsfdfeferf", 'sb') - - -if __name__ == "__main__": - main() diff --git a/src/string/simple.py b/src/string/simple.py deleted file mode 100644 index 16ab766..0000000 --- a/src/string/simple.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -__author__ = 'shenshijun' - - -def match(origin, pattern): - origin_index, pattern_index = 0, 0 - match_flag = True - pattern_len = len(pattern) - while origin_index < len(origin): - for pattern_index in xrange(pattern_len): - if pattern[pattern_index] != origin[origin_index]: - origin_index -= (pattern_index - 1) - match_flag = False - break - else: - origin_index += 1 - pattern_index += 1 - match_flag = True - - if match_flag: - return origin_index - pattern_index - - -def main(): - print match("absabsvbshsbdhhd", 'sb') - - -if __name__ == "__main__": - main() diff --git a/src/tree/BTree.py b/src/tree/BTree.py deleted file mode 100644 index b2c704e..0000000 --- a/src/tree/BTree.py +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -from lib.stack import Stack - -__author__ = 'shenshijun' - - -class Node(object): - def __init__(self, is_leaf, keys, childs=None, parent=None): - """ - 在真实的实现中应该在加上一个数组表示指向真实数据的指针 - keys和childs都是一个数组,分别表示关键字和孩子 - """ - self.keys = list(sorted(keys)) - self.is_leaf = is_leaf - self.__size = len(self.keys) - if childs is None: - self.childs = [None for x in xrange(0, self.__size)] - self.childs.append(None) - else: - self.childs = childs - self.parent = parent - - def __str__(self): - return "".join(['Node(keys=', ",".join(map(lambda key: str(key), self.keys)), - ',leaf' if self.is_leaf else ',not leaf', - ',childs num=', str(len(self.childs)), ')\n']) - - def __len__(self): - return self.__size - - def append(self, key): - """ - 向B树的节点中插入一个关键字,返回这个关键字的下标 - """ - result = self.__size - self.__size += 1 - for x in xrange(0, result): - if self.keys[x] > key: - self.keys.insert(x, key) - self.childs.insert(x, None) - return x - self.keys.append(key) - self.childs.append(None) - return result - - def search_child(self, instance): - """ - 查找小于instance的子树 - """ - for x in xrange(0, self.__size): - if self.keys[x] > instance: - return self.childs[x] - return self.childs[self.__size] - - -class BTree(object): - """ - B树实现,注意,不是二叉树 - """ - - def __init__(self, load_factor=4, *vargs): - """Constructor for BTree""" - self.__root = None - self.__load_factor = load_factor - self.__size = len(vargs) - map(self.insert, vargs) - - def insert(self, key): - """ - 节点插入的时候不需要再检测节点是不是满了,因为load_factor>=2,每次插入节点前调整都是使得节点关键字个数为load_factor-1。 - 而插入一个关键字之后节点关键字个数是2*load_factor-1或者load_factor - :param key: - :return: - """ - if self.__root is None: - self.__root = Node(True, [key]) - return - cur_node = self.__root - while not cur_node.is_leaf: - self.__split(cur_node) - cur_node = cur_node.search_child(key) - left_node, right_node = self.__split(cur_node) - if left_node is None or right_node is None: - # 返回None表示叶节点没有满 - cur_node.append(key) - else: - if left_node.keys[-1] < key: - # 说明left_node中的所有节点都比key小,所以把新节点插入到右边 - right_node.append(key) - else: - left_node.append(key) - - def __split(self, node): - if self.full(node): - parent_node = node.parent - middle_key = node.keys[self.__load_factor - 1] - if parent_node is None: - # 处理根节点 - self.__root = Node(False, []) - parent_node = self.__root - parent_middle_index = parent_node.append(middle_key) - left_node = Node(node.is_leaf, node.keys[:self.__load_factor - 1], node.childs[:self.__load_factor], - parent_node) - # 注意设定分裂节点的子节点的父指针 - for child in left_node.childs: - if child is not None: - child.parent = left_node - right_node = Node(node.is_leaf, node.keys[self.__load_factor:], node.childs[self.__load_factor:], - parent_node) - for child in right_node.childs: - if child is not None: - child.parent = right_node - parent_node.childs[parent_middle_index] = left_node - parent_node.childs[parent_middle_index + 1] = right_node - self.__root.is_leaf = False - return left_node, right_node - return None, None - - def search(self, instance): - return self.__search(self.__root, instance) - - def full(self, node): - return len(node) >= (self.__load_factor * 2 - 1) - - @classmethod - def __search(cls, root, instance): - cur_node = root - while True: - cur_len = len(cur_node) - x = 0 - while x < cur_len and cur_node.keys[x] < instance: - x += 1 - if cur_node.keys[x] == instance: - return cur_node, x - elif cur_node.is_leaf: - return None, None - else: - cur_node = cur_node.childs[x] - - def min(self): - cur_node = self.__root - while not cur_node.is_leaf: - cur_node = cur_node.childs[0] - return cur_node.keys[0] - - def max(self): - cur_node = self.__root - while not cur_node.is_leaf: - cur_node = cur_node.childs[-1] - return cur_node.keys[-1] - - def midorder(self, f): - """ - B树中序遍历 - :param f: - :return: - """ - result = [] - stack = Stack() - cur_node = self.__root - if cur_node.is_leaf: - return map(f, cur_node.keys) - - while True: - if cur_node.is_leaf: - # 到叶节点了,开始把叶节点的所有关键字都遍历掉 - result.extend(map(f, cur_node.keys)) - # 开始从栈中取元素,遍历下一个节点叶节点 - if stack.empty(): - return result - cur_node, i = stack.pop() - result.append(f(cur_node.keys[i])) - if i < len(cur_node) - 1: - stack.push((cur_node, i + 1)) - cur_node = cur_node.childs[i + 1] - else: - stack.push((cur_node, 0)) - cur_node = cur_node.childs[0] - return result - - def __str__(self): - return "\n".join(self.midorder(lambda s: str(s))) - - def test(self): - print "-" * 20 - print self.__root - print self.__root.childs[0] - print self.__root.childs[1] - - -def main(): - btree = BTree(3, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', - 'V', 'X', 'Y', 'Z') - print btree - print btree.max() - print btree.min() - - -if __name__ == "__main__": - main() diff --git a/src/tree/__init__.py b/src/tree/__init__.py deleted file mode 100644 index fb57e2f..0000000 --- a/src/tree/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -__author__ = 'shenshijun' diff --git a/src/tree/avltree.py b/src/tree/avltree.py deleted file mode 100644 index 8d24c9b..0000000 --- a/src/tree/avltree.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -__author__ = 'shenshijun' - - -class AVLTree(object): - """""" - - def __init__(self): - """Constructor for """ - pass diff --git a/src/tree/binarystree.py b/src/tree/binarystree.py deleted file mode 100644 index ccede2f..0000000 --- a/src/tree/binarystree.py +++ /dev/null @@ -1,252 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf-8 -*- -from lib.queue import Queue -from lib.stack import Stack - - -class BSTree(object): - """ - 实现二叉搜索树,并没有任何平衡树的逻辑 - """ - - class Node(object): - """ - 表示树中的节点 - """ - - def __init__(self, value, left, right, parent): - self.value = value - self.left = left - self.right = right - self.parent = parent - - def __cmp__(self, other): - return cmp(self.value, other.value) - - def __str__(self): - return "".join(["Node(value=", str(self.value), ")"]) - - def __init__(self, *arg): - super(BSTree, self).__init__() - self.__root = None - self.__size = 0 - map(self.insert, arg) - - def __find(self, value): - if value is None: - raise ValueError("None value not allowed in BSTree") - cur_node = self.__root - while cur_node is not None and cur_node.value != value: - if cur_node.value < value: - cur_node = cur_node.right - else: - cur_node = cur_node.left - return cur_node - - def find(self, value): - return True if self.__find(value) is not None else False - - def insert(self, value): - if value is None: - raise ValueError("BSTree don't allow None") - self.__size += 1 - - node = self.Node(value, None, None, None) - if self.__root is None: - self.__root = node - else: - cur_node = self.__root - while True: - cur_child_node = cur_node.left if node <= cur_node else cur_node.right - if cur_child_node is not None: - cur_node = cur_child_node - else: - node.parent = cur_node - if cur_node <= node: - cur_node.right = node - else: - cur_node.left = node - break - - def preorder(self, f): - result = [] - stack = Stack(self.__root) - while True: - cur_node = stack.pop() - # 栈中没有元素的时候就表示所有的元素都已经遍历完了 - if cur_node is None: - break - result.append(f(cur_node.value)) - if cur_node.left is not None: - stack.push(cur_node.left) - if cur_node.right is not None: - stack.push(cur_node.right) - return result - - def midorder(self, f): - result = [] - stack = Stack(self.__root) - cur_node = self.__root.left - # 第一个阶段首先把所有树左边的节点放进栈里,这个时候并不遍历 - # 第二个阶段的时候由于左节点遍历了之后,再遍历右节点 - while not stack.empty() or cur_node is not None: - # 第二个判断条件比较重要,因为如果根节点没有左子树,这个时候栈就是空的,会直接退出循环 - if cur_node is not None: - stack.push(cur_node) - cur_node = cur_node.left - else: - cur_node = stack.pop() - result.append(f(cur_node.value)) - cur_node = cur_node.right - return result - - def postorder(self, f): - """ - 后序遍历最好实现了,把前序遍历调转下就是后序遍历 - """ - return reversed(self.preorder(f)) - - def flatorder(self, f): - result = [] - queue = Queue(self.__root) - while not queue.empty(): - cur_node = queue.exit() - result.append(f(cur_node.value)) - if cur_node.left is not None: - queue.enter(cur_node.left) - - if cur_node.right is not None: - queue.enter(cur_node.right) - return result - - def max(self): - max_node = BSTree.__max(self.__root) - return max_node.value if max_node is not None else None - - @classmethod - def __max(cls, root): - cur_node = root - while cur_node.right is not None: - cur_node = cur_node.right - return cur_node - - @classmethod - def __min(cls, root): - cur_node = root - while cur_node.left is not None: - cur_node = cur_node.left - return cur_node - - def min(self): - min_node = BSTree.__min(self.__root) - return min_node.value if min_node is not None else None - - def __str__(self): - return "\t".join(self.midorder(lambda s: str(s))) - - def successor(self, value): - find_node = self.__find(value) - if find_node is None: - # 处理节点不存在的情况 - return None - if find_node.right is not None: - min_node = BSTree.__min(find_node.right) - return min_node.value if min_node is not None else None - else: - cur_parent = find_node.parent - cur_sub = find_node - while cur_parent is not None and cur_parent.right is cur_sub: - # 第一个条件是为了处理没有找到符合条件的父节点的情况,这个时候搜索失败 - cur_parent, cur_sub = cur_parent.parent, cur_parent - return cur_parent.value if cur_parent is not None else None - - def predecessor(self, value): - find_node = self.__find(value) - if find_node is None: - # 处理节点不存在的情况 - return None - if find_node.left is not None: - max_node = BSTree.__max(find_node.left) - return max_node.value if max_node is not None else None - else: - cur_parent = find_node.parent - cur_sub = find_node - while cur_parent is not None and cur_parent.left is cur_sub: - cur_parent, cur_sub = cur_parent.parent, cur_parent - return cur_parent.value if cur_parent is not None else None - - def __delete__(self, instance): - """ - 删除节点 - :param instance: - :return: - """ - node = self.__find(instance) - if node is None: - # 没有找到相应的节点直接退出 - return None - if node.left is None: # 第一二种情况 - self.__transplant(node, node.right) - elif node.right is None: - self.__transplant(node, node.left) - else: # 第三种情况,有两个子节点 - successor = self.__find(self.successor(instance)) # 不考虑节点重复的问题,因此find方法可以正确找到对应的节点 - if node.right is not successor: - self.__transplant(successor, successor.right) - # 后面的是设置移动之后新位置的节点,后继节点净身出户 - successor.right = node.right - successor.right.parent = successor - self.__transplant(node, successor) - successor.left = node.left - successor.left.parent = successor - - def __transplant(self, old, new): - """ - 移植操作,用new子树替换new子树 - :param old:要被替换的子树 - :param new:替换的子树 - :return: - """ - if self.__root is old: - self.__root = new - parent = old.parent - if parent.left is old: - parent.left = new - else: - parent.right = new - if new is not None: - new.parent = parent - - -def main(): - print "\ncheck stack" - stack = Stack(1, 2, 34, 5) - for x in range(0, 5): - stack.push(x) - print stack - for x in range(0, 15): - print "".join(["size=", str(len(stack)), " cur_node=", str(stack.pop())]) - - print "\ncheck queue" - queue = Queue(1, 2, 34, 5) - for x in range(0, 5): - queue.enter(x) - print stack - for x in range(0, 15): - print "".join(["size=", str(len(queue)), " cur_node=", str(queue.exit())]) - - print "\ncheck BSTree" - tree = BSTree(1, 2, 34, 5) - print tree - print tree.find(10) - print tree.find(5) - print tree.max() - print tree.min() - print tree.successor(34) - print tree.successor(5) - print tree.predecessor(1) - print tree.predecessor(2) - - -if __name__ == '__main__': - main() diff --git a/src/tree/binarytree.py b/src/tree/binarytree.py deleted file mode 100644 index 978eb59..0000000 --- a/src/tree/binarytree.py +++ /dev/null @@ -1,117 +0,0 @@ -# /usr/bin/env python -# -*- coding:utf-8 -*- -import Queue - - -class Stack(object): - """ - 实现上还是有些问题的,因为没有考虑栈空间不够的时候扩展的问题 - """ - - def __init__(self, cap): - super(Stack, self).__init__() - self.__cap = cap # 栈大小 - self.__length = 0 # 栈长度 - if self.__cap < 0: - raise ValueError("length of Stack can not be negtive") - self.__values = [0 for x in xrange(0, self.__cap)] - - def empty(self): - return self.__length is 0 - - def push(self, x): - if self.__length >= self.__cap: - raise IndexError("stack is full, can not push any object") - self.__values[self.__length] = x - self.__length += 1 - - def pop(self): - if self.__length <= 0: - return None - self.__length -= 1 - return self.__values[self.__length] - - def __str__(self): - return "".join(["Stack, Value: ", str(self.__values), " cap: ", str(self.__cap), - " length:", str(self.__length)]) - - -class Btree(object): - """ - 实现一个通用的二叉树,这个二叉树并不包含任何别的性质 - """ - - class Node(object): - """docstring for Node""" - - def __init__(self, key, left, right): - self.key = key - self.left = left - self.right = right - - def __str__(self): - return "".join(["key: ", str(self.key)]) - - def __init__(self, nodes, root_index=0): - """ - node是一个元祖列表,默认第一个是根节点,例如[(key=12,left=7,right=3),(key=15,left=8,right=None)] - """ - super(Btree, self).__init__() - self.__root, self.__nodes = self.build_tree(nodes, root_index) - self.__size = len(nodes) - - def build_tree(self, nodes, root_index=0): - tree_nodes = [self.Node(ele[0], ele[1], ele[2]) for ele in nodes] - for node in tree_nodes: - node.left = tree_nodes[node.left] if node.left is not None else None - node.right = tree_nodes[node.right] if node.right is not None else None - return (tree_nodes[root_index], tree_nodes) - - def depth_walk(self, f): - """ - 使用栈实现深度遍历,每次都是把右节点放进栈里,这样的保证每次都是优先访问左节点 - """ - result = [] - stack = Stack(self.__size) - stack.push(self.__root) - while not stack.empty(): - cur_node = stack.pop() - result.append(f(cur_node.key)) - if cur_node.right is not None: - stack.push(cur_node.right) - - if cur_node.left is not None: - stack.push(cur_node.left) - return result - - def breadth_walk(self, f): - """ - 使用堆实现广度遍历 - """ - result = [] - q = Queue.Queue(maxsize=-1) - q.put(self.__root) - while not q.empty(): - cur_node = q.get() - result.append(f(cur_node.key)) - # 注意:这儿的顺序比较讲究,不能调换 - if cur_node.left is not None: - q.put(cur_node.left) - - if cur_node.right is not None: - q.put(cur_node.right) - return result - - def __str__(self): - return "\t".join(self.depth_walk(lambda key: str(key))) - - -def main(): - nodes = [(12, 6, 2), (15, 7, None), (4, 9, None), (10, 4, 8), (2, None, None), (18, 0, 3), (7, None, None), - (14, 5, 1), (21, None, None), (5, None, None)] - btree = Btree(nodes, 5) - print btree - - -if __name__ == '__main__': - main() diff --git a/src/tree/interval_tree.py b/src/tree/interval_tree.py deleted file mode 100644 index f878471..0000000 --- a/src/tree/interval_tree.py +++ /dev/null @@ -1,411 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -from lib.queue import Queue -from lib.stack import Stack - -__author__ = 'shenshijun' - - -class Node(object): - """ - 实现二叉树中的节点 - """ - - def __init__(self, low, high, sub_max, left, right, parent, color): - """ - color:true表示红色,false表示黑色 - """ - self.left = left - self.right = right - self.parent = parent - self.color = color - self.low = low - self.high = high - self.sub_max = sub_max - - def __cmp__(self, other): - return cmp(self.low, other.low) - - def __eq__(self, other): - return (self.low == other.low) and (other.sub_max == self.sub_max) - - def is_red(self): - return self.color - - def is_black(self): - return not self.color - - def __str__(self): - return "".join( - ["Node(low=", str(self.low), ',high=', str(self.high), ',max=', str(self.sub_max), ", color=", - 'Red)' if self.color else 'Black)']) - - def restore_max(self): - if self.not_empty(): - self.sub_max = max([self.left.sub_max, self.right.sub_max]) - - def not_empty(self): - return self.left is not None and self.right is not None - - @property - def key(self): - return self.low, self.high - - -class IntervalTree(object): - """ - 用红黑树实现区间树 - """ - - def __init__(self, *vargs): - - """ - 使用元组(low,high)来表示一个区间 - """ - self.Nil = Node(None, None, None, None, None, None, False) # 用Nil代替None可以简化逻辑 - self.__root = self.Nil - self.__size = 0 - map(self.insert, vargs) - - def __len__(self): - - return self.__size - - def __left_rotate(self, node): - - """ - 二叉搜索树左旋操作 - :param node:要旋转的分支的父节点 - :return:None - """ - - right_child = node.right - right_child_left = right_child.left - parent = node.parent - if right_child is self.Nil: - raise NotImplementedError("没有右叶节点不支持左旋转") - - # 判断node是parent的左节点还是右节点 - if parent is not self.Nil: - if parent.left is node: - parent.left = right_child - else: - parent.right = right_child - if node is self.__root: - self.__root = right_child - self.__root.parent = self.Nil - node.right = right_child_left - right_child.parent = node.parent - node.parent = right_child - right_child.left = node - node.restore_max() - right_child.restore_max() - - def __right_rotate(self, node): - """ - 二叉搜索树右旋操作 - 可以证明除了涉及到的两个节点,局部局部特性没有被破坏,全局的的特性则在插入或者删除的过程中维护 - :param node:要被旋转的分子的父节点 - :return:None - """ - - left_child = node.left - left_right_child = left_child.right - parent = node.parent - if left_child is self.Nil: - raise NotImplementedError('没有左节点不支持右旋转') - # 判断这个节点是在父节点的那个分支上 - if parent is not self.Nil: - if parent.left is node: - parent.left = left_child - else: - parent.right = left_child - if node is self.__root: - # 如果选择的正好是根节点,那么就需要宠幸设置根节点了 - self.__root = left_child - self.__root.parent = self.Nil - node.left = left_right_child - left_child.parent = node.parent - left_child.right = node - node.parent = left_child - node.restore_max() - left_child.restore_max() - - def insert(self, key): - cur_node = self.__root - node = Node(key[0], key[1], key[1], self.Nil, self.Nil, self.Nil, True) - if cur_node is self.Nil: # 根节点不存在的时候设置根节点 - self.__root = node - else: - parent_node = cur_node - while cur_node is not self.Nil: - parent_node = cur_node - # 插入过程中同时维护最大值,这样就不用在插入之后维护最大值了 - if node.high > cur_node.sub_max: - cur_node.sub_max = node.high - - if cur_node >= node: - cur_node = cur_node.left - else: - cur_node = cur_node.right - if parent_node >= node: - parent_node.left = node - else: - parent_node.right = node - node.parent = parent_node - self.__insert_fixup(node) - - def __insert_fixup(self, node): - - # 首先判断节点是不是根节点或者父节点是不是根节点 - if node.parent is self.Nil or node.parent.parent is self.Nil: - self.__root.color = False - return - - cur_node = node - while cur_node.parent.is_red(): - # 首先需要分清父节点在哪个分支 - parent_node = cur_node.parent - grand_node = parent_node.parent - if parent_node is grand_node.left: - if grand_node.right.is_red(): # 情况1:只需要调整颜色,祖父节点设置成红色,父节点和叔节点设置成黑色,满足了特性3 - grand_node.color = True - parent_node.color = False - grand_node.right.color = False - cur_node = grand_node # 这个时候只有祖父节点可能会违反特性3,所有再调节这个节点 - elif parent_node.right is cur_node: # 情况2:需要左旋 - self.__left_rotate(parent_node) - cur_node = parent_node # 左旋之后,父节点一定会违背特性3,所以需要调节父节点 - else: # 情况3:右旋加重新设色 - grand_node.color = True - parent_node.color = False - self.__right_rotate(grand_node) - break - else: # 和上面的情况类似,只是这个时候所有的操作都反了 - if grand_node.left.is_red(): - grand_node.color = True - parent_node.color = False - grand_node.left.color = False - cur_node = grand_node - elif parent_node.left is cur_node: - self.__right_rotate(parent_node) - cur_node = parent_node - else: - grand_node.color = True - parent_node.color = False - self.__left_rotate(grand_node) - break - self.__root.color = False # 根节点必须被设置为黑色 - - def __transplant(self, old, new): - parent = old.parent - if old is parent.left: - parent.left = new - else: - parent.right = new - if new is not self.Nil: - new.parent = parent - if parent is self.Nil: - self.__root = new - return parent - - def delete(self, instance): - node = self.__find(instance) - if node is self.Nil: - return node - deleted_color = node.color - if node.left is self.Nil: - self.__transplant(node, node.right) - replace_node = node.right - elif node.right is self.Nil: - self.__transplant(node, node.left) - replace_node = node.left - else: # 后继节点移动在右子树中,因为这个时候右子树一定存在 - successor = self.__successor(instance) - deleted_color = successor.color - replace_node = successor.right - if successor.parent is not node: - self.__transplant(successor, successor.right) - replace_node.parent = successor.parent - if successor is not self.Nil: # 在处理的过程中不希望改变Nil的值 - successor.right = node.right - successor.right.parent = successor - self.__transplant(node, successor) - if successor is not self.Nil: - successor.left = node.left - successor.left.parent = successor - successor.color = node.color - print "replace node : %s" % replace_node - print "replace parent node:%s" % replace_node.parent - self.__fix_sub_max(replace_node) - if not deleted_color: - self.__delete_fixup(replace_node) - if replace_node is self.Nil: - replace_node.parent = None - replace_node.left = None - replace_node.right = None - - def __fix_sub_max(self, node): - parent_node = node - while parent_node is not None: - parent_node.restore_max() - if parent_node is self.__root: - break - parent_node = parent_node.parent - - def __find(self, key): - if key is None: - raise ValueError("None value not allowed in BSTree") - cur_node = self.__root - while cur_node is not self.Nil and cur_node.key != key: - if cur_node.key < key: - cur_node = cur_node.right - else: - cur_node = cur_node.left - return cur_node - - def __successor(self, value): - find_node = self.__find(value) - if find_node is self.Nil: - # 处理节点不存在的情况 - return None - if find_node.right is not self.Nil: - return self.__min(find_node.right) - else: - cur_parent = find_node.parent - cur_sub = find_node - while cur_parent is not self.Nil and cur_parent.right is cur_sub: - # 第一个条件是为了处理没有找到符合条件的父节点的情况,这个时候搜索失败 - cur_parent, cur_sub = cur_parent.parent, cur_parent - return cur_parent - - def max(self): - max_node = self.__max(self.__root) - return max_node.value if max_node is not None else None - - def __max(self, root): - cur_node = root - while cur_node.right is not self.Nil: - cur_node = cur_node.right - return cur_node - - def __min(self, root): - cur_node = root - while cur_node.left is not self.Nil: - cur_node = cur_node.left - return cur_node - - def min(self): - min_node = self.__min(self.__root) - return min_node.value if min_node is not None else None - - def __delete_fixup(self, node): - cur_node = node - while cur_node is not self.__root and cur_node.is_black(): - parent = cur_node.parent - if parent.left is cur_node: - # 判断是左支还是右支,仅仅是实现所限 - uncle = parent.right - if uncle.is_red(): - # 情况一:叔节点是红色,则重新设色并左旋 - uncle.color = False - parent.color = True - self.__left_rotate(parent) - elif uncle.left.is_black() and uncle.right.is_black(): - # 情况二(1):叔节点和其两个子节点都是黑色.则设置叔节点为红色,这个时候如果parent是红色,那么循环就会退出 - uncle.color = True - cur_node = parent - elif uncle.right.is_black(): - uncle.color = True - uncle.left.color = False - # 情况二(2):叔节点红和其右节点是黑色,那么意味着叔节点的左节点是红色,这个时候叔节点右旋并且父子节点交换颜色 - self.__right_rotate(uncle) - else: - # 情况二(3):叔节点是黑色,其右节点红色(可以由前面的转换而来),这个时候叔节点设红,其父节点和右子节点设黑并且父节点左旋 - parent.color = False - uncle.color = True - uncle.right.color = False - self.__left_rotate(parent) - # 退出情况 - cur_node = self.__root - else: - uncle = parent.left - if uncle.is_red(): - uncle.color = False - parent.color = True - self.__right_rotate(parent) - elif uncle.left.is_black() and uncle.right.is_black(): - uncle.color = True - cur_node = parent - elif uncle.left.is_black(): - uncle.color = True - uncle.right.color = False - self.__left_rotate(uncle) - else: - parent.color = False - uncle.color = True - uncle.left.color = False - self.__right_rotate(parent) - cur_node = self.__root - cur_node.color = False - - def midorder(self, f): - """ - 中序遍历 - :param f:访问一个节点的时候要对节点进行处理的函数 - :return: - """ - result = [] - stack = Stack(self.__root) - cur_node = self.__root.left - # 第一个阶段首先把所有树左边的节点放进栈里,这个时候并不遍历 - # 第二个阶段的时候由于左节点遍历了之后,再遍历右节点 - while not stack.empty() or cur_node is not self.Nil: - # 第二个判断条件比较重要,因为如果根节点没有左子树,这个时候栈就是空的,会直接退出循环 - if cur_node is not self.Nil: - stack.push(cur_node) - cur_node = cur_node.left - else: - cur_node = stack.pop() - result.append(f(cur_node)) - cur_node = cur_node.right - return result - - def print_tree(self): - """ - 打印树的结构 - :return: - """ - queue = Queue(self.__root) - next_level = 1 - now_node_count = 0 - while not queue.empty(): - cur_node = queue.exit() - print str(cur_node) + "\t", - now_node_count += 1 - if now_node_count == next_level: - print - now_node_count = 0 - next_level *= 2 - if cur_node.left is not None: - queue.enter(cur_node.left) - - if cur_node.right is not None: - queue.enter(cur_node.right) - - def test(self): - print self.__successor(8) - - def __str__(self): - return "\t".join(self.midorder(lambda s: str(s))) - - -def main(): - tree = IntervalTree((16, 21), (8, 9), (5, 8), (15, 23), (0, 3), (6, 10), (25, 30), (17, 19), (26, 26), (19, 20)) - print tree - print tree.delete((25, 30)) - tree.print_tree() - - -if __name__ == "__main__": - main() diff --git a/src/tree/lchild_rbro_tree.py b/src/tree/lchild_rbro_tree.py deleted file mode 100644 index 8cf0398..0000000 --- a/src/tree/lchild_rbro_tree.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env -# !-*- coding:utf-8 -*- -import Queue - - -class Stack(object): - """ - 实现上还是有些问题的,因为没有考虑栈空间不够的时候扩展的问题 - """ - - def __init__(self, cap): - super(Stack, self).__init__() - self.__cap = cap # 栈大小 - self.__length = 0 # 栈长度 - if self.__cap < 0: - raise ValueError("length of Stack can not be negtive") - self.__values = [0 for x in xrange(0, self.__cap)] - - def empty(self): - return self.__length is 0 - - def push(self, x): - if self.__length >= self.__cap: - raise IndexError("stack is full, can not push any object") - self.__values[self.__length] = x - self.__length += 1 - - def pop(self): - if self.__length <= 0: - return None - self.__length -= 1 - return self.__values[self.__length] - - def __str__(self): - return "".join(["Stack, Value: ", str(self.__values), " cap: ", str(self.__cap), - " length:", str(self.__length)]) - - -class NTree(object): - """ - 用左孩子右兄弟的方式实现一个n可以有任意个子节点的树 - """ - - class Node(object): - """ - """ - - def __init__(self, key, child, brother): - self.key = key - self.child = child - self.brother = brother - - def __str__(self): - return str(key) - - def __init__(self, nodes, root_index=0): - """ - nodes是一个元祖列表,最前面的一个元素是节点值,后面的都是子节点的索引。 - 如果一个元祖中只有第一个元素,那么就认为这个元祖表示的是一个叶节点 - """ - super(NTree, self).__init__() - self.__root, self.__nodes = self.build_tree(nodes, root_index) - self.__size = len(nodes) - - def build_tree(self, nodes, root_index=0): - tree_nodes = [self.Node(node[0], node[1], node[2]) for node in nodes] - for node in tree_nodes: - node.child = tree_nodes[node.child] if node.child is not None else None - node.brother = tree_nodes[node.brother] if node.brother is not None else None - return (tree_nodes[root_index], tree_nodes) - - def depth_walk(self, f): - """ - 使用栈来实现深度遍历的时候,首先把兄弟节点进栈,然后把子节点放在栈中. - """ - result = [] - stack = Stack(self.__size) - stack.push(self.__root) - while not stack.empty(): - cur_node = stack.pop() - result.append(f(cur_node.key)) - if cur_node.brother is not None: - stack.push(cur_node.brother) - - if cur_node.child is not None: - stack.push(cur_node.child) - return result - - def breadth_walk(self, f): - """ - 使用队列实现广度遍历的思路是类似的,在访问到一个父节点的时候把所有的子节点都依次放到队列中 - """ - result = [] - q = Queue.Queue(maxsize=-1) - q.put(self.__root) - while not q.empty(): - cur_node = q.get() - result.append(f(cur_node.key)) - # 注意:这儿的顺序比较讲究,不能调换 - child = cur_node.child - while child is not None: - q.put(child) - child = child.brother - return result - - def __str__(self): - return "\t".join(self.depth_walk(lambda key: str(key))) - - -def main(): - nodes = [(12, 6, 2), (15, 7, None), (4, 9, None), (10, 4, 8), (2, None, None), (18, 0, 3), (7, None, None), - (14, 5, 1), (21, None, None), (5, None, None)] - btree = NTree(nodes, 5) - print btree - - -if __name__ == '__main__': - main() diff --git a/src/tree/order_statistic_tree.py b/src/tree/order_statistic_tree.py deleted file mode 100644 index 122369e..0000000 --- a/src/tree/order_statistic_tree.py +++ /dev/null @@ -1,452 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -from lib.queue import Queue -from lib.stack import Stack - -__author__ = 'shenshijun' - - -class OrderStatisticTree(object): - """ - 红黑树实现,红黑树的特性保证树的高度<=2lg(n+1),进而保证树中各个操作的性能. - 动态集合顺序统计底层使用红黑树实现,实现各个操作的复杂度都是lgn。 - 每一个子树的根节点在这个子树的相对顺序是左子节点的子树大小+1。因此根节点的序是根节点的左子节点的子树大小+1。 - """ - - class Node(object): - """ - 实现二叉树中的节点 - """ - - def __init__(self, key, left, right, parent, color, sub_size=1): - """ - color:true表示红色,false表示黑色 - """ - self.key = key - self.left = left - self.right = right - self.parent = parent - self.color = color - self.sub_size = sub_size - - def __cmp__(self, other): - return cmp(self.key, other.key) - - def __eq__(self, other): - return (self.key == other.key) and (other.color == self.color) - - def is_red(self): - return self.color - - def is_black(self): - return not self.color - - def __str__(self): - return "".join( - ["Node(key=", str(self.key), ", color=", - 'Red' if self.color else 'Black', - ', sub_size=', str(self.sub_size), ')']) - - def not_empty(self): - return self.left is not None and self.right is not None - - def inc(self): - if self.not_empty(): - self.sub_size += 1 - return self.sub_size - - def dec(self): - if self.not_empty(): - self.sub_size -= 1 - return self.sub_size - - def restore_sub_size(self): - if self.not_empty(): - self.sub_size = self.left.sub_size + self.right.sub_size + 1 - - def __init__(self, *vargs): - """""" - self.Nil = self.Node(None, None, None, None, False, 0) # 用Nil代替None可以简化逻辑 - self.__root = self.Nil - self.__size = 0 - map(self.insert, vargs) - - def __len__(self): - return self.__size - - def __left_rotate(self, node): - """ - 二叉搜索树左旋操作 - 可以证明旋转并不会影响node的父节点的sub_size,所以不需要修改node的父节点 - :param node:要旋转的分支的父节点 - :return:None - """ - right_child = node.right - right_left_child = right_child.left - parent = node.parent - if right_child is self.Nil: - raise NotImplementedError("没有右叶节点不支持左旋转") - - # 判断node是parent的左节点还是右节点 - if parent is not self.Nil: - if parent.left is node: - parent.left = right_child - else: - parent.right = right_child - if node is self.__root: - self.__root = right_child - self.__root.parent = self.Nil - node.right = right_left_child - right_child.parent = node.parent - node.parent = right_child - right_child.left = node - node.restore_sub_size() - right_child.restore_sub_size() - - def __right_rotate(self, node): - """ - 二叉搜索树右旋操作 - :param node:要被旋转的分子的父节点 - :return:None - """ - left_child = node.left - left_right_child = left_child.right - parent = node.parent - if left_child is self.Nil: - raise NotImplementedError('没有左节点不支持右旋转') - # 判断这个节点是在父节点的那个分支上 - if parent is not self.Nil: - if parent.left is node: - parent.left = left_child - else: - parent.right = left_child - if node is self.__root: - # 如果选择的正好是根节点,那么就需要宠幸设置根节点了 - self.__root = left_child - self.__root.parent = self.Nil - node.left = left_right_child - left_child.parent = node.parent - left_child.right = node - node.parent = left_child - node.restore_sub_size() - left_child.restore_sub_size() - - def insert(self, key): - cur_node = self.__root - node = self.Node(key, self.Nil, self.Nil, self.Nil, True) - if cur_node is self.Nil: # 根节点不存在的时候设置根节点 - self.__root = node - else: - parent_node = cur_node - while cur_node is not self.Nil: - parent_node = cur_node - cur_node.sub_size += 1 - if cur_node >= node: - cur_node = cur_node.left - else: - cur_node = cur_node.right - if parent_node >= node: - parent_node.left = node - else: - parent_node.right = node - node.parent = parent_node - self.__insert_fixup(node) - - def __insert_fixup(self, node): - # 首先判断节点是不是根节点或者父节点是不是根节点 - if node.parent is self.Nil or node.parent.parent is self.Nil: - self.__root.color = False - return - - cur_node = node - while cur_node.parent.is_red(): - # 首先需要分清父节点在哪个分支 - parent_node = cur_node.parent - grand_node = parent_node.parent - if parent_node is grand_node.left: - if grand_node.right.is_red(): # 情况1:只需要调整颜色,祖父节点设置成红色,父节点和叔节点设置成黑色,满足了特性3 - grand_node.color = True - parent_node.color = False - grand_node.right.color = False - cur_node = grand_node # 这个时候只有祖父节点可能会违反特性3,所有再调节这个节点 - elif parent_node.right is cur_node: # 情况2:需要左旋 - self.__left_rotate(parent_node) - cur_node = parent_node # 左旋之后,父节点一定会违背特性3,所以需要调节父节点 - else: # 情况3:右旋加重新设色 - grand_node.color = True - parent_node.color = False - self.__right_rotate(grand_node) - break - else: # 和上面的情况类似,只是这个时候所有的操作都反了 - if grand_node.left.is_red(): - grand_node.color = True - parent_node.color = False - grand_node.left.color = False - cur_node = grand_node - elif parent_node.left is cur_node: - self.__right_rotate(parent_node) - cur_node = parent_node - else: - grand_node.color = True - parent_node.color = False - self.__left_rotate(grand_node) - break - self.__root.color = False # 根节点必须被设置为黑色 - - def __transplant(self, old, new): - parent = old.parent - parent.sub_siz = parent.sub_size - old.sub_size + new.sub_size - if old is parent.left: - parent.left = new - else: - parent.right = new - if new is not self.Nil: - new.parent = parent - if parent is self.Nil: - self.__root = new - - def delete(self, instance): - node = self.__walk_find(instance, lambda n: n.dec()) - if node is self.Nil: - return node - deleted_color = node.color - if node.left is self.Nil: - self.__transplant(node, node.right) - replace_node = node.right - elif node.right is self.Nil: - self.__transplant(node, node.left) - replace_node = node.left - else: # 后继节点移动在右子树中,因为这个时候右子树一定存在 - successor = self.__walk_min(node.right, lambda n: n.dec()) - deleted_color = successor.color - replace_node = successor.right - if successor.parent is not node: - self.__transplant(successor, successor.right) - if replace_node is self.Nil: - replace_node.parent = successor.parent - if successor is not self.Nil: # 在处理的过程中不希望改变Nil的值 - successor.right = node.right - successor.right.parent = successor - self.__transplant(node, successor) - if successor is not self.Nil: - successor.left = node.left - successor.left.parent = successor - successor.color = node.color - successor.restore_sub_size() - successor.parent.restore_sub_size() - if not deleted_color: - self.__delete_fixup(replace_node) - if replace_node is self.Nil: - replace_node.parent = None - replace_node.left = None - replace_node.right = None - - def __find(self, key): - if key is None: - raise ValueError("None value not allowed in BSTree") - cur_node = self.__root - while cur_node is not self.Nil and cur_node.key != key: - if cur_node.key < key: - cur_node = cur_node.right - else: - cur_node = cur_node.left - return cur_node - - def __walk_find(self, key, func): - if key is None: - raise ValueError("None value not allowed in BSTree") - cur_node = self.__root - while cur_node is not self.Nil and cur_node.key != key: - func(cur_node) - if cur_node.key < key: - cur_node = cur_node.right - else: - cur_node = cur_node.left - return cur_node - - def __successor(self, value): - find_node = self.__find(value) - if find_node is self.Nil: - # 处理节点不存在的情况 - return None - if find_node.right is not self.Nil: - return self.__min(find_node.right) - else: - cur_parent = find_node.parent - cur_sub = find_node - while cur_parent is not self.Nil and cur_parent.right is cur_sub: - # 第一个条件是为了处理没有找到符合条件的父节点的情况,这个时候搜索失败 - cur_parent, cur_sub = cur_parent.parent, cur_parent - return cur_parent - - def max(self): - max_node = self.__max(self.__root) - return max_node.value if max_node is not None else None - - def __max(self, root): - cur_node = root - while cur_node.right is not self.Nil: - cur_node = cur_node.right - return cur_node - - def __min(self, root): - return self.__walk_min(root, lambda node: node) - - def __walk_min(self, root, func): - cur_node = root - while cur_node.left is not self.Nil: - func(cur_node) - cur_node = cur_node.left - return cur_node - - def min(self): - min_node = self.__min(self.__root) - return min_node.value if min_node is not None else None - - def __delete_fixup(self, node): - cur_node = node - while cur_node is not self.__root and cur_node.is_black(): - parent = cur_node.parent - if parent.left is cur_node: - # 判断是左支还是右支,仅仅是实现所限 - uncle = parent.right - if uncle.is_red(): - # 情况一:叔节点是红色,则重新设色并左旋 - uncle.color = False - parent.color = True - self.__left_rotate(parent) - elif uncle.left.is_black() and uncle.right.is_black(): - # 情况二(1):叔节点和其两个子节点都是黑色.则设置叔节点为红色,这个时候如果parent是红色,那么循环就会退出 - uncle.color = True - cur_node = parent - elif uncle.right.is_black(): - uncle.color = True - uncle.left.color = False - # 情况二(2):叔节点红和其右节点是黑色,那么意味着叔节点的左节点是红色,这个时候叔节点右旋并且父子节点交换颜色 - self.__right_rotate(uncle) - else: - # 情况二(3):叔节点是黑色,其右节点红色(可以由前面的转换而来),这个时候叔节点设红,其父节点和右子节点设黑并且父节点左旋 - parent.color = False - uncle.color = True - uncle.right.color = False - self.__left_rotate(parent) - # 退出情况 - cur_node = self.__root - else: - uncle = parent.left - if uncle.is_red(): - uncle.color = False - parent.color = True - self.__right_rotate(parent) - elif uncle.left.is_black() and uncle.right.is_black(): - uncle.color = True - cur_node = parent - elif uncle.left.is_black(): - uncle.color = True - uncle.right.color = False - self.__left_rotate(uncle) - else: - parent.color = False - uncle.color = True - uncle.left.color = False - self.__right_rotate(parent) - cur_node = self.__root - cur_node.color = False - - def midorder(self, f): - """ - 中序遍历 - :param f:访问一个节点的时候要对节点进行处理的函数 - :return: - """ - result = [] - stack = Stack(self.__root) - cur_node = self.__root.left - # 第一个阶段首先把所有树左边的节点放进栈里,这个时候并不遍历 - # 第二个阶段的时候由于左节点遍历了之后,再遍历右节点 - while not stack.empty() or cur_node is not self.Nil: - # 第二个判断条件比较重要,因为如果根节点没有左子树,这个时候栈就是空的,会直接退出循环 - if cur_node is not self.Nil: - stack.push(cur_node) - cur_node = cur_node.left - else: - cur_node = stack.pop() - result.append(f(cur_node)) - cur_node = cur_node.right - return result - - def print_tree(self): - """ - 打印树的结构 - :return: - """ - queue = Queue(self.__root) - next_level = 1 - now_node_count = 0 - while not queue.empty(): - cur_node = queue.exit() - print str(cur_node) + "\t", - now_node_count += 1 - if now_node_count == next_level: - print - now_node_count = 0 - next_level *= 2 - if cur_node.left is not None: - queue.enter(cur_node.left) - - if cur_node.right is not None: - queue.enter(cur_node.right) - - def test(self): - print self.__successor(8) - - def __str__(self): - return "\t".join(self.midorder(lambda s: str(s))) - - def os_select(self, index): - """ - 类似于二分查找,只是本来应该转向左边的逻辑变成了转向左子树 - 在转向右子树的时候要注意计算这个时候在右子树中的相对顺序 - 本质上就是把计算每一个节点的在本树的相对序,然后和需要查找的序对比看看是不是这个节点 - :param index: - :return: - """ - find_rank = index - cur_node = self.__root - while cur_node is not self.Nil: - cur_rank = cur_node.left.sub_size + 1 - if cur_rank == find_rank: - return cur_node.key - elif cur_rank < find_rank: - cur_node = cur_node.right - find_rank -= cur_rank - else: - cur_node = cur_node.left - return cur_node.key - - def os_rank(self, value): - cur_node = self.__root - move_right_incr = 0 - while cur_node is not self.Nil: - cur_rank = cur_node.left.sub_size + 1 - if cur_node.key == value: - return cur_rank + move_right_incr - elif cur_node.key >= value: - cur_node = cur_node.left - else: - cur_node = cur_node.right - # 在往右边移动的时候要记录下相对序和绝对序的差距 - move_right_incr += cur_rank - return -1 - - -def main(): - tree = OrderStatisticTree(7, 2, 1, 5, 4, 8, 11, 14, 14, 15) - print tree.os_select(1) - print tree.os_select(10) - print tree.os_select(5) - print tree.os_rank(11) - - -if __name__ == "__main__": - main() diff --git a/src/tree/red_black_tree.py b/src/tree/red_black_tree.py deleted file mode 100644 index bc193dc..0000000 --- a/src/tree/red_black_tree.py +++ /dev/null @@ -1,375 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -from lib.queue import Queue -from lib.stack import Stack - -__author__ = 'shenshijun' - -""" -实际上,在红黑树中使用单例空节点会出现一个根本的问题:也就是父节点没法保存。这是一个大问题。 -可能应该用多个对象表示,或者实现没有父节点的红黑树 -""" - - -class RedBlackTree(object): - """ - 红黑树实现,红黑树的特性保证树的高度<=2lg(n+1),进而保证树中各个操作的性能. - """ - - class Node(object): - """ - 实现二叉树中的节点 - """ - - def __init__(self, key, left, right, parent, color): - """ - color:true表示红色,false表示黑色 - """ - self.key = key - self.left = left - self.right = right - self.parent = parent - self.color = color - - def __cmp__(self, other): - return cmp(self.key, other.key) - - def __eq__(self, other): - return (self.key == other.key) and (other.color == self.color) - - def is_red(self): - return self.color - - def is_black(self): - return not self.color - - def __str__(self): - return "".join( - ["Node(key=", str(self.key), ", color=", - 'Red)' if self.color else 'Black)']) - - def __init__(self, *vargs): - """""" - self.Nil = self.Node(None, None, None, None, False) # 用Nil代替None可以简化逻辑 - self.__root = self.Nil - self.__size = 0 - map(self.insert, vargs) - - def __len__(self): - return self.__size - - def __left_rotate(self, node): - """ - 二叉搜索树左旋操作 - :param node:要旋转的分支的父节点 - :return:None - """ - right_child = node.right - right_child_left = right_child.left - parent = node.parent - if right_child is self.Nil: - raise NotImplementedError("没有右叶节点不支持左旋转") - - # 判断node是parent的左节点还是右节点 - if parent is not self.Nil: - if parent.left is node: - parent.left = right_child - else: - parent.right = right_child - if node is self.__root: - self.__root = right_child - self.__root.parent = self.Nil - node.right = right_child_left - right_child.parent = node.parent - node.parent = right_child - right_child.left = node - - def __right_rotate(self, node): - """ - 二叉搜索树右旋操作 - :param node:要被旋转的分子的父节点 - :return:None - """ - left_child = node.left - left_right_child = left_child.right - parent = node.parent - if left_child is self.Nil: - raise NotImplementedError('没有左节点不支持右旋转') - # 判断这个节点是在父节点的那个分支上 - if parent is not self.Nil: - if parent.left is node: - parent.left = left_child - else: - parent.right = left_child - if node is self.__root: - # 如果选择的正好是根节点,那么就需要宠幸设置根节点了 - self.__root = left_child - self.__root.parent = self.Nil - node.left = left_right_child - left_child.parent = node.parent - left_child.right = node - node.parent = left_child - - def insert(self, key): - cur_node = self.__root - node = self.Node(key, self.Nil, self.Nil, self.Nil, True) - if cur_node is self.Nil: # 根节点不存在的时候设置根节点 - self.__root = node - else: - parent_node = cur_node - while cur_node is not self.Nil: - parent_node = cur_node - if cur_node >= node: - cur_node = cur_node.left - else: - cur_node = cur_node.right - if parent_node >= node: - parent_node.left = node - else: - parent_node.right = node - node.parent = parent_node - self.__insert_fixup(node) - - def __insert_fixup(self, node): - # 首先判断节点是不是根节点或者父节点是不是根节点 - if node.parent is self.Nil or node.parent.parent is self.Nil: - self.__root.color = False - return - - cur_node = node - while cur_node.parent.is_red(): - # 首先需要分清父节点在哪个分支 - parent_node = cur_node.parent - grand_node = parent_node.parent - if parent_node is grand_node.left: - if grand_node.right.is_red(): # 情况1:只需要调整颜色,祖父节点设置成红色,父节点和叔节点设置成黑色,满足了特性3 - grand_node.color = True - parent_node.color = False - grand_node.right.color = False - cur_node = grand_node # 这个时候只有祖父节点可能会违反特性3,所有再调节这个节点 - elif parent_node.right is cur_node: # 情况2:需要左旋 - self.__left_rotate(parent_node) - cur_node = parent_node # 左旋之后,父节点一定会违背特性3,所以需要调节父节点 - else: # 情况3:右旋加重新设色 - grand_node.color = True - parent_node.color = False - self.__right_rotate(grand_node) - break - else: # 和上面的情况类似,只是这个时候所有的操作都反了 - if grand_node.left.is_red(): - grand_node.color = True - parent_node.color = False - grand_node.left.color = False - cur_node = grand_node - elif parent_node.left is cur_node: - self.__right_rotate(parent_node) - cur_node = parent_node - else: - grand_node.color = True - parent_node.color = False - self.__left_rotate(grand_node) - break - self.__root.color = False # 根节点必须被设置为黑色 - - def __transplant(self, old, new): - parent = old.parent - if old is parent.left: - parent.left = new - else: - parent.right = new - if new is not self.Nil: - new.parent = parent - if parent is self.Nil: - self.__root = new - - def delete(self, instance): - node = self.__find(instance) - if node is self.Nil: - return node - deleted_color = node.color - if node.left is self.Nil: - self.__transplant(node, node.right) - replace_node = node.right - elif node.right is self.Nil: - self.__transplant(node, node.left) - replace_node = node.left - else: # 后继节点移动在右子树中,因为这个时候右子树一定存在 - successor = self.__successor(instance) - deleted_color = successor.color - replace_node = successor.right - if successor.parent is not node: - self.__transplant(successor, successor.right) - if replace_node is self.Nil: - replace_node.parent = successor.parent - if successor is not self.Nil: # 在处理的过程中不希望改变Nil的值 - successor.right = node.right - successor.right.parent = successor - self.__transplant(node, successor) - if successor is not self.Nil: - successor.left = node.left - successor.left.parent = successor - successor.color = node.color - if not deleted_color: - self.__delete_fixup(replace_node) - if replace_node is self.Nil: - replace_node.parent = None - replace_node.left = None - replace_node.right = None - - def __find(self, key): - if key is None: - raise ValueError("None value not allowed in BSTree") - cur_node = self.__root - while cur_node is not self.Nil and cur_node.key != key: - if cur_node.key < key: - cur_node = cur_node.right - else: - cur_node = cur_node.left - return cur_node - - def __successor(self, value): - find_node = self.__find(value) - if find_node is self.Nil: - # 处理节点不存在的情况 - return None - if find_node.right is not self.Nil: - return self.__min(find_node.right) - else: - cur_parent = find_node.parent - cur_sub = find_node - while cur_parent is not self.Nil and cur_parent.right is cur_sub: - # 第一个条件是为了处理没有找到符合条件的父节点的情况,这个时候搜索失败 - cur_parent, cur_sub = cur_parent.parent, cur_parent - return cur_parent - - def max(self): - max_node = self.__max(self.__root) - return max_node.value if max_node is not None else None - - def __max(self, root): - cur_node = root - while cur_node.right is not self.Nil: - cur_node = cur_node.right - return cur_node - - def __min(self, root): - cur_node = root - while cur_node.left is not self.Nil: - cur_node = cur_node.left - return cur_node - - def min(self): - min_node = self.__min(self.__root) - return min_node.value if min_node is not None else None - - def __delete_fixup(self, node): - cur_node = node - while cur_node is not self.__root and cur_node.is_black(): - parent = cur_node.parent - if parent.left is cur_node: - # 判断是左支还是右支,仅仅是实现所限 - brother = parent.right - if brother.is_red(): - # 情况一:兄弟节点是红色,则重新设色并左旋 - brother.color = False - parent.color = True - self.__left_rotate(parent) - cur_node = brother - elif brother.left.is_black() and brother.right.is_black(): - # 情况二(1):兄弟节点和其两个子节点都是黑色.则设置兄弟节点为红色,这个时候如果parent是红色,那么循环就会退出 - brother.color = True - cur_node = parent - elif brother.right.is_black(): - brother.color = True - brother.left.color = False - # 情况二(2):兄弟节点红和其右节点是黑色,那么意味着兄弟节点的左节点是红色,这个时候兄弟节点右旋并且父子节点交换颜色 - self.__right_rotate(brother) - else: - # 情况二(3):兄弟节点是黑色,其右节点红色(可以由前面的转换而来),这个时候兄弟节点设红,其父节点和右子节点设黑并且父节点左旋 - parent.color = False - brother.color = True - brother.right.color = False - self.__left_rotate(parent) - # 退出情况 - cur_node = self.__root - else: - brother = parent.left - if brother.is_red(): - brother.color = False - parent.color = True - self.__right_rotate(parent) - elif brother.left.is_black() and brother.right.is_black(): - brother.color = True - cur_node = parent - elif brother.left.is_black(): - brother.color = True - brother.right.color = False - self.__left_rotate(brother) - else: - parent.color = False - brother.color = True - brother.left.color = False - self.__right_rotate(parent) - cur_node = self.__root - cur_node.color = False - - def midorder(self, f): - """ - 中序遍历 - :param f:访问一个节点的时候要对节点进行处理的函数 - :return: - """ - result = [] - stack = Stack(self.__root) - cur_node = self.__root.left - # 第一个阶段首先把所有树左边的节点放进栈里,这个时候并不遍历 - # 第二个阶段的时候由于左节点遍历了之后,再遍历右节点 - while not stack.empty() or cur_node is not self.Nil: - # 第二个判断条件比较重要,因为如果根节点没有左子树,这个时候栈就是空的,会直接退出循环 - if cur_node is not self.Nil: - stack.push(cur_node) - cur_node = cur_node.left - else: - cur_node = stack.pop() - result.append(f(cur_node)) - cur_node = cur_node.right - return result - - def print_tree(self): - """ - 打印树的结构 - :return: - """ - queue = Queue(self.__root) - next_level = 1 - now_node_count = 0 - while not queue.empty(): - cur_node = queue.exit() - print str(cur_node) + "\t", - now_node_count += 1 - if now_node_count == next_level: - print - now_node_count = 0 - next_level *= 2 - if cur_node.left is not None: - queue.enter(cur_node.left) - - if cur_node.right is not None: - queue.enter(cur_node.right) - - def test(self): - print self.__successor(8) - - def __str__(self): - return "\t".join(self.midorder(lambda s: str(s))) - - -def main(): - tree = RedBlackTree(7, 2, 1, 5, 4, 8, 11, 14, 14, 15) - print tree - print tree.delete(5) - tree.print_tree() - - -if __name__ == "__main__": - main() diff --git a/src/tree/tries.py b/src/tree/tries.py deleted file mode 100644 index 1dc2140..0000000 --- a/src/tree/tries.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -__author__ = 'shenshijun' - - -class Tries(object): - """ - 字符串前缀树实现 - """ - - def __init__(self): - """""" - pass From 61c7b019352e6f9ad7512b0da246022e90610296 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Thu, 24 Sep 2015 09:16:27 +0800 Subject: [PATCH 09/23] =?UTF-8?q?1,=E5=AE=8C=E6=88=90leecode=E7=9A=84?= =?UTF-8?q?=E7=AC=AC=E4=B8=89=E9=A2=98=EF=BC=8C=E7=AC=AC=E5=9B=9B=E9=A2=98?= =?UTF-8?q?=E8=BF=98=E6=9C=89bug=202,=E6=8A=8A=E6=89=80=E6=9C=89=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=94=BE=E5=9C=A8ssj=E5=8C=85=E4=B8=8B?= =?UTF-8?q?=EF=BC=8C=E5=9B=A0=E4=B8=BA=E4=B8=80=E4=BA=9B=E5=8C=85=E7=9A=84?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E8=B7=9Fpython=E8=87=AA=E5=B8=A6=E5=BA=93?= =?UTF-8?q?=E6=98=8E=E5=90=8D=E9=87=8D=E5=A4=8D=EF=BC=8C=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E4=BC=9A=E5=87=BA=E7=8E=B0=E4=B8=80=E4=BA=9B=E6=84=8F=E6=83=B3?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/string/__init__.py | 3 + src/ssj/string/kmp.py | 40 +++ src/ssj/string/rabin-karp.py | 46 +++ src/ssj/string/simple.py | 30 ++ src/ssj/tree/BTree.py | 201 ++++++++++++ src/ssj/tree/__init__.py | 3 + src/ssj/tree/avltree.py | 11 + src/ssj/tree/binarystree.py | 252 +++++++++++++++ src/ssj/tree/binarytree.py | 116 +++++++ src/ssj/tree/interval_tree.py | 411 ++++++++++++++++++++++++ src/ssj/tree/lchild_rbro_tree.py | 117 +++++++ src/ssj/tree/order_statistic_tree.py | 452 +++++++++++++++++++++++++++ src/ssj/tree/red_black_tree.py | 375 ++++++++++++++++++++++ src/ssj/tree/tries.py | 13 + 14 files changed, 2070 insertions(+) create mode 100644 src/ssj/string/__init__.py create mode 100644 src/ssj/string/kmp.py create mode 100644 src/ssj/string/rabin-karp.py create mode 100644 src/ssj/string/simple.py create mode 100644 src/ssj/tree/BTree.py create mode 100644 src/ssj/tree/__init__.py create mode 100644 src/ssj/tree/avltree.py create mode 100644 src/ssj/tree/binarystree.py create mode 100644 src/ssj/tree/binarytree.py create mode 100644 src/ssj/tree/interval_tree.py create mode 100644 src/ssj/tree/lchild_rbro_tree.py create mode 100644 src/ssj/tree/order_statistic_tree.py create mode 100644 src/ssj/tree/red_black_tree.py create mode 100644 src/ssj/tree/tries.py diff --git a/src/ssj/string/__init__.py b/src/ssj/string/__init__.py new file mode 100644 index 0000000..fb57e2f --- /dev/null +++ b/src/ssj/string/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/src/ssj/string/kmp.py b/src/ssj/string/kmp.py new file mode 100644 index 0000000..e92a8f0 --- /dev/null +++ b/src/ssj/string/kmp.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + + +def match(origin, pattern): + origin_len = len(origin) + pattern_len = len(pattern) + + def build_next(): + _next_list = [0 for x in xrange(pattern_len)] + last_match = 0 + for cur_index in xrange(1, pattern_len): + while last_match > 0 and pattern[last_match] != pattern[cur_index]: + last_match = _next_list[last_match] + if pattern[last_match] == pattern[cur_index]: + last_match += 1 + _next_list[cur_index] = last_match + return _next_list + + origin_index, pattern_index = 0, 0 + next_list = build_next() + while origin_index < origin_len: + # while需要放在前面,如果放在后面的话且有匹配的情况下pattern[pattern_index]就会越界 + while pattern_index > 0 and origin[origin_index] != pattern[pattern_index]: + pattern_index = next_list[pattern_index] + if pattern[pattern_index] == origin[origin_index]: + pattern_index += 1 + origin_index += 1 + + if pattern_index == pattern_len: + return origin_index - pattern_len + + +def main(): + print match("assssbsss", 'sb') + + +if __name__ == "__main__": + main() diff --git a/src/ssj/string/rabin-karp.py b/src/ssj/string/rabin-karp.py new file mode 100644 index 0000000..0f327d1 --- /dev/null +++ b/src/ssj/string/rabin-karp.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +首先计算pattern字符串的hash值,然后在从目标字符串的开头,计算相同长度字符串的hash值。若hash值相同,则表示匹配,若不同,则向右移动一位,计算新的hash值。整个过程,与暴力的字符串匹配算法很相似, +但由于计算hash值时,可以利用上一次的hash值,从而使新的hash值只需要加上新字母的计算,并减去上一次的第一个字母的计算,即可。 +Rabin-Karp算法的预处理时间为O(m),最坏情况下该算法的匹配时间为O((n-m+1)m),期望复杂度O(m+n) +""" + + +def match(origin, pattern): + pattern_len = len(pattern) + + def _hash(string, start=0): + hash_code = 0 + for x in xrange(pattern_len): + hash_code += ord(string[start + x]) * 2 ** (pattern_len - x - 1) + return hash_code + + def _refresh(old_hash, old_char, new_char): + return (old_hash - ord(old_char) * 2 ** (pattern_len - 1)) * 2 + ord(new_char) + + def test_equal(start_index): + for x in xrange(pattern_len): + if origin[x + start_index] != pattern[x]: + return False + return True + + origin_index = 0 + pattern_hash = _hash(pattern) + origin_hash = _hash(origin) + while origin_index < len(origin) - pattern_len - 1: + if pattern_hash == origin_hash and test_equal(origin_index): + return origin_index + else: + print "origin hash:%s,pattern hash:%s" % (origin_hash, pattern_hash) + origin_hash = _refresh(origin_hash, origin[origin_index], origin[origin_index + pattern_len]) + origin_index += 1 + + +def main(): + print match("sbsfsdgdgfgasbssssfsfdfeferf", 'sb') + + +if __name__ == "__main__": + main() diff --git a/src/ssj/string/simple.py b/src/ssj/string/simple.py new file mode 100644 index 0000000..16ab766 --- /dev/null +++ b/src/ssj/string/simple.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + + +def match(origin, pattern): + origin_index, pattern_index = 0, 0 + match_flag = True + pattern_len = len(pattern) + while origin_index < len(origin): + for pattern_index in xrange(pattern_len): + if pattern[pattern_index] != origin[origin_index]: + origin_index -= (pattern_index - 1) + match_flag = False + break + else: + origin_index += 1 + pattern_index += 1 + match_flag = True + + if match_flag: + return origin_index - pattern_index + + +def main(): + print match("absabsvbshsbdhhd", 'sb') + + +if __name__ == "__main__": + main() diff --git a/src/ssj/tree/BTree.py b/src/ssj/tree/BTree.py new file mode 100644 index 0000000..5b0ac05 --- /dev/null +++ b/src/ssj/tree/BTree.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +from ssj.lib import Stack + +__author__ = 'shenshijun' + + +class Node(object): + def __init__(self, is_leaf, keys, childs=None, parent=None): + """ + 在真实的实现中应该在加上一个数组表示指向真实数据的指针 + keys和childs都是一个数组,分别表示关键字和孩子 + """ + self.keys = list(sorted(keys)) + self.is_leaf = is_leaf + self.__size = len(self.keys) + if childs is None: + self.childs = [None for x in xrange(0, self.__size)] + self.childs.append(None) + else: + self.childs = childs + self.parent = parent + + def __str__(self): + return "".join(['Node(keys=', ",".join(map(lambda key: str(key), self.keys)), + ',leaf' if self.is_leaf else ',not leaf', + ',childs num=', str(len(self.childs)), ')\n']) + + def __len__(self): + return self.__size + + def append(self, key): + """ + 向B树的节点中插入一个关键字,返回这个关键字的下标 + """ + result = self.__size + self.__size += 1 + for x in xrange(0, result): + if self.keys[x] > key: + self.keys.insert(x, key) + self.childs.insert(x, None) + return x + self.keys.append(key) + self.childs.append(None) + return result + + def search_child(self, instance): + """ + 查找小于instance的子树 + """ + for x in xrange(0, self.__size): + if self.keys[x] > instance: + return self.childs[x] + return self.childs[self.__size] + + +class BTree(object): + """ + B树实现,注意,不是二叉树 + """ + + def __init__(self, load_factor=4, *vargs): + """Constructor for BTree""" + self.__root = None + self.__load_factor = load_factor + self.__size = len(vargs) + map(self.insert, vargs) + + def insert(self, key): + """ + 节点插入的时候不需要再检测节点是不是满了,因为load_factor>=2,每次插入节点前调整都是使得节点关键字个数为load_factor-1。 + 而插入一个关键字之后节点关键字个数是2*load_factor-1或者load_factor + :param key: + :return: + """ + if self.__root is None: + self.__root = Node(True, [key]) + return + cur_node = self.__root + while not cur_node.is_leaf: + self.__split(cur_node) + cur_node = cur_node.search_child(key) + left_node, right_node = self.__split(cur_node) + if left_node is None or right_node is None: + # 返回None表示叶节点没有满 + cur_node.append(key) + else: + if left_node.keys[-1] < key: + # 说明left_node中的所有节点都比key小,所以把新节点插入到右边 + right_node.append(key) + else: + left_node.append(key) + + def __split(self, node): + if self.full(node): + parent_node = node.parent + middle_key = node.keys[self.__load_factor - 1] + if parent_node is None: + # 处理根节点 + self.__root = Node(False, []) + parent_node = self.__root + parent_middle_index = parent_node.append(middle_key) + left_node = Node(node.is_leaf, node.keys[:self.__load_factor - 1], node.childs[:self.__load_factor], + parent_node) + # 注意设定分裂节点的子节点的父指针 + for child in left_node.childs: + if child is not None: + child.parent = left_node + right_node = Node(node.is_leaf, node.keys[self.__load_factor:], node.childs[self.__load_factor:], + parent_node) + for child in right_node.childs: + if child is not None: + child.parent = right_node + parent_node.childs[parent_middle_index] = left_node + parent_node.childs[parent_middle_index + 1] = right_node + self.__root.is_leaf = False + return left_node, right_node + return None, None + + def search(self, instance): + return self.__search(self.__root, instance) + + def full(self, node): + return len(node) >= (self.__load_factor * 2 - 1) + + @classmethod + def __search(cls, root, instance): + cur_node = root + while True: + cur_len = len(cur_node) + x = 0 + while x < cur_len and cur_node.keys[x] < instance: + x += 1 + if cur_node.keys[x] == instance: + return cur_node, x + elif cur_node.is_leaf: + return None, None + else: + cur_node = cur_node.childs[x] + + def min(self): + cur_node = self.__root + while not cur_node.is_leaf: + cur_node = cur_node.childs[0] + return cur_node.keys[0] + + def max(self): + cur_node = self.__root + while not cur_node.is_leaf: + cur_node = cur_node.childs[-1] + return cur_node.keys[-1] + + def midorder(self, f): + """ + B树中序遍历 + :param f: + :return: + """ + result = [] + stack = Stack() + cur_node = self.__root + if cur_node.is_leaf: + return map(f, cur_node.keys) + + while True: + if cur_node.is_leaf: + # 到叶节点了,开始把叶节点的所有关键字都遍历掉 + result.extend(map(f, cur_node.keys)) + # 开始从栈中取元素,遍历下一个节点叶节点 + if stack.empty(): + return result + cur_node, i = stack.pop() + result.append(f(cur_node.keys[i])) + if i < len(cur_node) - 1: + stack.push((cur_node, i + 1)) + cur_node = cur_node.childs[i + 1] + else: + stack.push((cur_node, 0)) + cur_node = cur_node.childs[0] + return result + + def __str__(self): + return "\n".join(self.midorder(lambda s: str(s))) + + def test(self): + print "-" * 20 + print self.__root + print self.__root.childs[0] + print self.__root.childs[1] + + +def main(): + btree = BTree(3, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', + 'V', 'X', 'Y', 'Z') + print btree + print btree.max() + print btree.min() + + +if __name__ == "__main__": + main() diff --git a/src/ssj/tree/__init__.py b/src/ssj/tree/__init__.py new file mode 100644 index 0000000..fb57e2f --- /dev/null +++ b/src/ssj/tree/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/src/ssj/tree/avltree.py b/src/ssj/tree/avltree.py new file mode 100644 index 0000000..8d24c9b --- /dev/null +++ b/src/ssj/tree/avltree.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + + +class AVLTree(object): + """""" + + def __init__(self): + """Constructor for """ + pass diff --git a/src/ssj/tree/binarystree.py b/src/ssj/tree/binarystree.py new file mode 100644 index 0000000..4c36b39 --- /dev/null +++ b/src/ssj/tree/binarystree.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- +from ssj.lib import Queue +from ssj.lib import Stack + + +class BSTree(object): + """ + 实现二叉搜索树,并没有任何平衡树的逻辑 + """ + + class Node(object): + """ + 表示树中的节点 + """ + + def __init__(self, value, left, right, parent): + self.value = value + self.left = left + self.right = right + self.parent = parent + + def __cmp__(self, other): + return cmp(self.value, other.value) + + def __str__(self): + return "".join(["Node(value=", str(self.value), ")"]) + + def __init__(self, *arg): + super(BSTree, self).__init__() + self.__root = None + self.__size = 0 + map(self.insert, arg) + + def __find(self, value): + if value is None: + raise ValueError("None value not allowed in BSTree") + cur_node = self.__root + while cur_node is not None and cur_node.value != value: + if cur_node.value < value: + cur_node = cur_node.right + else: + cur_node = cur_node.left + return cur_node + + def find(self, value): + return True if self.__find(value) is not None else False + + def insert(self, value): + if value is None: + raise ValueError("BSTree don't allow None") + self.__size += 1 + + node = self.Node(value, None, None, None) + if self.__root is None: + self.__root = node + else: + cur_node = self.__root + while True: + cur_child_node = cur_node.left if node <= cur_node else cur_node.right + if cur_child_node is not None: + cur_node = cur_child_node + else: + node.parent = cur_node + if cur_node <= node: + cur_node.right = node + else: + cur_node.left = node + break + + def preorder(self, f): + result = [] + stack = Stack(self.__root) + while True: + cur_node = stack.pop() + # 栈中没有元素的时候就表示所有的元素都已经遍历完了 + if cur_node is None: + break + result.append(f(cur_node.value)) + if cur_node.left is not None: + stack.push(cur_node.left) + if cur_node.right is not None: + stack.push(cur_node.right) + return result + + def midorder(self, f): + result = [] + stack = Stack(self.__root) + cur_node = self.__root.left + # 第一个阶段首先把所有树左边的节点放进栈里,这个时候并不遍历 + # 第二个阶段的时候由于左节点遍历了之后,再遍历右节点 + while not stack.empty() or cur_node is not None: + # 第二个判断条件比较重要,因为如果根节点没有左子树,这个时候栈就是空的,会直接退出循环 + if cur_node is not None: + stack.push(cur_node) + cur_node = cur_node.left + else: + cur_node = stack.pop() + result.append(f(cur_node.value)) + cur_node = cur_node.right + return result + + def postorder(self, f): + """ + 后序遍历最好实现了,把前序遍历调转下就是后序遍历 + """ + return reversed(self.preorder(f)) + + def flatorder(self, f): + result = [] + queue = Queue(self.__root) + while not queue.empty(): + cur_node = queue.exit() + result.append(f(cur_node.value)) + if cur_node.left is not None: + queue.enter(cur_node.left) + + if cur_node.right is not None: + queue.enter(cur_node.right) + return result + + def max(self): + max_node = BSTree.__max(self.__root) + return max_node.value if max_node is not None else None + + @classmethod + def __max(cls, root): + cur_node = root + while cur_node.right is not None: + cur_node = cur_node.right + return cur_node + + @classmethod + def __min(cls, root): + cur_node = root + while cur_node.left is not None: + cur_node = cur_node.left + return cur_node + + def min(self): + min_node = BSTree.__min(self.__root) + return min_node.value if min_node is not None else None + + def __str__(self): + return "\t".join(self.midorder(lambda s: str(s))) + + def successor(self, value): + find_node = self.__find(value) + if find_node is None: + # 处理节点不存在的情况 + return None + if find_node.right is not None: + min_node = BSTree.__min(find_node.right) + return min_node.value if min_node is not None else None + else: + cur_parent = find_node.parent + cur_sub = find_node + while cur_parent is not None and cur_parent.right is cur_sub: + # 第一个条件是为了处理没有找到符合条件的父节点的情况,这个时候搜索失败 + cur_parent, cur_sub = cur_parent.parent, cur_parent + return cur_parent.value if cur_parent is not None else None + + def predecessor(self, value): + find_node = self.__find(value) + if find_node is None: + # 处理节点不存在的情况 + return None + if find_node.left is not None: + max_node = BSTree.__max(find_node.left) + return max_node.value if max_node is not None else None + else: + cur_parent = find_node.parent + cur_sub = find_node + while cur_parent is not None and cur_parent.left is cur_sub: + cur_parent, cur_sub = cur_parent.parent, cur_parent + return cur_parent.value if cur_parent is not None else None + + def __delete__(self, instance): + """ + 删除节点 + :param instance: + :return: + """ + node = self.__find(instance) + if node is None: + # 没有找到相应的节点直接退出 + return None + if node.left is None: # 第一二种情况 + self.__transplant(node, node.right) + elif node.right is None: + self.__transplant(node, node.left) + else: # 第三种情况,有两个子节点 + successor = self.__find(self.successor(instance)) # 不考虑节点重复的问题,因此find方法可以正确找到对应的节点 + if node.right is not successor: + self.__transplant(successor, successor.right) + # 后面的是设置移动之后新位置的节点,后继节点净身出户 + successor.right = node.right + successor.right.parent = successor + self.__transplant(node, successor) + successor.left = node.left + successor.left.parent = successor + + def __transplant(self, old, new): + """ + 移植操作,用new子树替换new子树 + :param old:要被替换的子树 + :param new:替换的子树 + :return: + """ + if self.__root is old: + self.__root = new + parent = old.parent + if parent.left is old: + parent.left = new + else: + parent.right = new + if new is not None: + new.parent = parent + + +def main(): + print "\ncheck stack" + stack = Stack(1, 2, 34, 5) + for x in range(0, 5): + stack.push(x) + print stack + for x in range(0, 15): + print "".join(["size=", str(len(stack)), " cur_node=", str(stack.pop())]) + + print "\ncheck queue" + queue = Queue(1, 2, 34, 5) + for x in range(0, 5): + queue.enter(x) + print stack + for x in range(0, 15): + print "".join(["size=", str(len(queue)), " cur_node=", str(queue.exit())]) + + print "\ncheck BSTree" + tree = BSTree(1, 2, 34, 5) + print tree + print tree.find(10) + print tree.find(5) + print tree.max() + print tree.min() + print tree.successor(34) + print tree.successor(5) + print tree.predecessor(1) + print tree.predecessor(2) + + +if __name__ == '__main__': + main() diff --git a/src/ssj/tree/binarytree.py b/src/ssj/tree/binarytree.py new file mode 100644 index 0000000..2549d13 --- /dev/null +++ b/src/ssj/tree/binarytree.py @@ -0,0 +1,116 @@ +# /usr/bin/env python +# -*- coding:utf-8 -*- + + +class Stack(object): + """ + 实现上还是有些问题的,因为没有考虑栈空间不够的时候扩展的问题 + """ + + def __init__(self, cap): + super(Stack, self).__init__() + self.__cap = cap # 栈大小 + self.__length = 0 # 栈长度 + if self.__cap < 0: + raise ValueError("length of Stack can not be negtive") + self.__values = [0 for x in xrange(0, self.__cap)] + + def empty(self): + return self.__length is 0 + + def push(self, x): + if self.__length >= self.__cap: + raise IndexError("stack is full, can not push any object") + self.__values[self.__length] = x + self.__length += 1 + + def pop(self): + if self.__length <= 0: + return None + self.__length -= 1 + return self.__values[self.__length] + + def __str__(self): + return "".join(["Stack, Value: ", str(self.__values), " cap: ", str(self.__cap), + " length:", str(self.__length)]) + + +class Btree(object): + """ + 实现一个通用的二叉树,这个二叉树并不包含任何别的性质 + """ + + class Node(object): + """docstring for Node""" + + def __init__(self, key, left, right): + self.key = key + self.left = left + self.right = right + + def __str__(self): + return "".join(["key: ", str(self.key)]) + + def __init__(self, nodes, root_index=0): + """ + node是一个元祖列表,默认第一个是根节点,例如[(key=12,left=7,right=3),(key=15,left=8,right=None)] + """ + super(Btree, self).__init__() + self.__root, self.__nodes = self.build_tree(nodes, root_index) + self.__size = len(nodes) + + def build_tree(self, nodes, root_index=0): + tree_nodes = [self.Node(ele[0], ele[1], ele[2]) for ele in nodes] + for node in tree_nodes: + node.left = tree_nodes[node.left] if node.left is not None else None + node.right = tree_nodes[node.right] if node.right is not None else None + return (tree_nodes[root_index], tree_nodes) + + def depth_walk(self, f): + """ + 使用栈实现深度遍历,每次都是把右节点放进栈里,这样的保证每次都是优先访问左节点 + """ + result = [] + stack = Stack(self.__size) + stack.push(self.__root) + while not stack.empty(): + cur_node = stack.pop() + result.append(f(cur_node.key)) + if cur_node.right is not None: + stack.push(cur_node.right) + + if cur_node.left is not None: + stack.push(cur_node.left) + return result + + def breadth_walk(self, f): + """ + 使用堆实现广度遍历 + """ + result = [] + q = queue.Queue(maxsize=-1) + q.put(self.__root) + while not q.empty(): + cur_node = q.get() + result.append(f(cur_node.key)) + # 注意:这儿的顺序比较讲究,不能调换 + if cur_node.left is not None: + q.put(cur_node.left) + + if cur_node.right is not None: + q.put(cur_node.right) + return result + + def __str__(self): + return "\t".join(self.depth_walk(lambda key: str(key))) + + +def main(): + nodes = [(12, 6, 2), (15, 7, None), (4, 9, None), (10, 4, 8), (2, None, None), (18, 0, 3), (7, None, None), + (14, 5, 1), (21, None, None), (5, None, None)] + btree = Btree(nodes, 5) + print btree + + +if __name__ == '__main__': + main() diff --git a/src/ssj/tree/interval_tree.py b/src/ssj/tree/interval_tree.py new file mode 100644 index 0000000..6eaaa0c --- /dev/null +++ b/src/ssj/tree/interval_tree.py @@ -0,0 +1,411 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +from ssj.lib import Queue +from ssj.lib import Stack + +__author__ = 'shenshijun' + + +class Node(object): + """ + 实现二叉树中的节点 + """ + + def __init__(self, low, high, sub_max, left, right, parent, color): + """ + color:true表示红色,false表示黑色 + """ + self.left = left + self.right = right + self.parent = parent + self.color = color + self.low = low + self.high = high + self.sub_max = sub_max + + def __cmp__(self, other): + return cmp(self.low, other.low) + + def __eq__(self, other): + return (self.low == other.low) and (other.sub_max == self.sub_max) + + def is_red(self): + return self.color + + def is_black(self): + return not self.color + + def __str__(self): + return "".join( + ["Node(low=", str(self.low), ',high=', str(self.high), ',max=', str(self.sub_max), ", color=", + 'Red)' if self.color else 'Black)']) + + def restore_max(self): + if self.not_empty(): + self.sub_max = max([self.left.sub_max, self.right.sub_max]) + + def not_empty(self): + return self.left is not None and self.right is not None + + @property + def key(self): + return self.low, self.high + + +class IntervalTree(object): + """ + 用红黑树实现区间树 + """ + + def __init__(self, *vargs): + + """ + 使用元组(low,high)来表示一个区间 + """ + self.Nil = Node(None, None, None, None, None, None, False) # 用Nil代替None可以简化逻辑 + self.__root = self.Nil + self.__size = 0 + map(self.insert, vargs) + + def __len__(self): + + return self.__size + + def __left_rotate(self, node): + + """ + 二叉搜索树左旋操作 + :param node:要旋转的分支的父节点 + :return:None + """ + + right_child = node.right + right_child_left = right_child.left + parent = node.parent + if right_child is self.Nil: + raise NotImplementedError("没有右叶节点不支持左旋转") + + # 判断node是parent的左节点还是右节点 + if parent is not self.Nil: + if parent.left is node: + parent.left = right_child + else: + parent.right = right_child + if node is self.__root: + self.__root = right_child + self.__root.parent = self.Nil + node.right = right_child_left + right_child.parent = node.parent + node.parent = right_child + right_child.left = node + node.restore_max() + right_child.restore_max() + + def __right_rotate(self, node): + """ + 二叉搜索树右旋操作 + 可以证明除了涉及到的两个节点,局部局部特性没有被破坏,全局的的特性则在插入或者删除的过程中维护 + :param node:要被旋转的分子的父节点 + :return:None + """ + + left_child = node.left + left_right_child = left_child.right + parent = node.parent + if left_child is self.Nil: + raise NotImplementedError('没有左节点不支持右旋转') + # 判断这个节点是在父节点的那个分支上 + if parent is not self.Nil: + if parent.left is node: + parent.left = left_child + else: + parent.right = left_child + if node is self.__root: + # 如果选择的正好是根节点,那么就需要宠幸设置根节点了 + self.__root = left_child + self.__root.parent = self.Nil + node.left = left_right_child + left_child.parent = node.parent + left_child.right = node + node.parent = left_child + node.restore_max() + left_child.restore_max() + + def insert(self, key): + cur_node = self.__root + node = Node(key[0], key[1], key[1], self.Nil, self.Nil, self.Nil, True) + if cur_node is self.Nil: # 根节点不存在的时候设置根节点 + self.__root = node + else: + parent_node = cur_node + while cur_node is not self.Nil: + parent_node = cur_node + # 插入过程中同时维护最大值,这样就不用在插入之后维护最大值了 + if node.high > cur_node.sub_max: + cur_node.sub_max = node.high + + if cur_node >= node: + cur_node = cur_node.left + else: + cur_node = cur_node.right + if parent_node >= node: + parent_node.left = node + else: + parent_node.right = node + node.parent = parent_node + self.__insert_fixup(node) + + def __insert_fixup(self, node): + + # 首先判断节点是不是根节点或者父节点是不是根节点 + if node.parent is self.Nil or node.parent.parent is self.Nil: + self.__root.color = False + return + + cur_node = node + while cur_node.parent.is_red(): + # 首先需要分清父节点在哪个分支 + parent_node = cur_node.parent + grand_node = parent_node.parent + if parent_node is grand_node.left: + if grand_node.right.is_red(): # 情况1:只需要调整颜色,祖父节点设置成红色,父节点和叔节点设置成黑色,满足了特性3 + grand_node.color = True + parent_node.color = False + grand_node.right.color = False + cur_node = grand_node # 这个时候只有祖父节点可能会违反特性3,所有再调节这个节点 + elif parent_node.right is cur_node: # 情况2:需要左旋 + self.__left_rotate(parent_node) + cur_node = parent_node # 左旋之后,父节点一定会违背特性3,所以需要调节父节点 + else: # 情况3:右旋加重新设色 + grand_node.color = True + parent_node.color = False + self.__right_rotate(grand_node) + break + else: # 和上面的情况类似,只是这个时候所有的操作都反了 + if grand_node.left.is_red(): + grand_node.color = True + parent_node.color = False + grand_node.left.color = False + cur_node = grand_node + elif parent_node.left is cur_node: + self.__right_rotate(parent_node) + cur_node = parent_node + else: + grand_node.color = True + parent_node.color = False + self.__left_rotate(grand_node) + break + self.__root.color = False # 根节点必须被设置为黑色 + + def __transplant(self, old, new): + parent = old.parent + if old is parent.left: + parent.left = new + else: + parent.right = new + if new is not self.Nil: + new.parent = parent + if parent is self.Nil: + self.__root = new + return parent + + def delete(self, instance): + node = self.__find(instance) + if node is self.Nil: + return node + deleted_color = node.color + if node.left is self.Nil: + self.__transplant(node, node.right) + replace_node = node.right + elif node.right is self.Nil: + self.__transplant(node, node.left) + replace_node = node.left + else: # 后继节点移动在右子树中,因为这个时候右子树一定存在 + successor = self.__successor(instance) + deleted_color = successor.color + replace_node = successor.right + if successor.parent is not node: + self.__transplant(successor, successor.right) + replace_node.parent = successor.parent + if successor is not self.Nil: # 在处理的过程中不希望改变Nil的值 + successor.right = node.right + successor.right.parent = successor + self.__transplant(node, successor) + if successor is not self.Nil: + successor.left = node.left + successor.left.parent = successor + successor.color = node.color + print "replace node : %s" % replace_node + print "replace parent node:%s" % replace_node.parent + self.__fix_sub_max(replace_node) + if not deleted_color: + self.__delete_fixup(replace_node) + if replace_node is self.Nil: + replace_node.parent = None + replace_node.left = None + replace_node.right = None + + def __fix_sub_max(self, node): + parent_node = node + while parent_node is not None: + parent_node.restore_max() + if parent_node is self.__root: + break + parent_node = parent_node.parent + + def __find(self, key): + if key is None: + raise ValueError("None value not allowed in BSTree") + cur_node = self.__root + while cur_node is not self.Nil and cur_node.key != key: + if cur_node.key < key: + cur_node = cur_node.right + else: + cur_node = cur_node.left + return cur_node + + def __successor(self, value): + find_node = self.__find(value) + if find_node is self.Nil: + # 处理节点不存在的情况 + return None + if find_node.right is not self.Nil: + return self.__min(find_node.right) + else: + cur_parent = find_node.parent + cur_sub = find_node + while cur_parent is not self.Nil and cur_parent.right is cur_sub: + # 第一个条件是为了处理没有找到符合条件的父节点的情况,这个时候搜索失败 + cur_parent, cur_sub = cur_parent.parent, cur_parent + return cur_parent + + def max(self): + max_node = self.__max(self.__root) + return max_node.value if max_node is not None else None + + def __max(self, root): + cur_node = root + while cur_node.right is not self.Nil: + cur_node = cur_node.right + return cur_node + + def __min(self, root): + cur_node = root + while cur_node.left is not self.Nil: + cur_node = cur_node.left + return cur_node + + def min(self): + min_node = self.__min(self.__root) + return min_node.value if min_node is not None else None + + def __delete_fixup(self, node): + cur_node = node + while cur_node is not self.__root and cur_node.is_black(): + parent = cur_node.parent + if parent.left is cur_node: + # 判断是左支还是右支,仅仅是实现所限 + uncle = parent.right + if uncle.is_red(): + # 情况一:叔节点是红色,则重新设色并左旋 + uncle.color = False + parent.color = True + self.__left_rotate(parent) + elif uncle.left.is_black() and uncle.right.is_black(): + # 情况二(1):叔节点和其两个子节点都是黑色.则设置叔节点为红色,这个时候如果parent是红色,那么循环就会退出 + uncle.color = True + cur_node = parent + elif uncle.right.is_black(): + uncle.color = True + uncle.left.color = False + # 情况二(2):叔节点红和其右节点是黑色,那么意味着叔节点的左节点是红色,这个时候叔节点右旋并且父子节点交换颜色 + self.__right_rotate(uncle) + else: + # 情况二(3):叔节点是黑色,其右节点红色(可以由前面的转换而来),这个时候叔节点设红,其父节点和右子节点设黑并且父节点左旋 + parent.color = False + uncle.color = True + uncle.right.color = False + self.__left_rotate(parent) + # 退出情况 + cur_node = self.__root + else: + uncle = parent.left + if uncle.is_red(): + uncle.color = False + parent.color = True + self.__right_rotate(parent) + elif uncle.left.is_black() and uncle.right.is_black(): + uncle.color = True + cur_node = parent + elif uncle.left.is_black(): + uncle.color = True + uncle.right.color = False + self.__left_rotate(uncle) + else: + parent.color = False + uncle.color = True + uncle.left.color = False + self.__right_rotate(parent) + cur_node = self.__root + cur_node.color = False + + def midorder(self, f): + """ + 中序遍历 + :param f:访问一个节点的时候要对节点进行处理的函数 + :return: + """ + result = [] + stack = Stack(self.__root) + cur_node = self.__root.left + # 第一个阶段首先把所有树左边的节点放进栈里,这个时候并不遍历 + # 第二个阶段的时候由于左节点遍历了之后,再遍历右节点 + while not stack.empty() or cur_node is not self.Nil: + # 第二个判断条件比较重要,因为如果根节点没有左子树,这个时候栈就是空的,会直接退出循环 + if cur_node is not self.Nil: + stack.push(cur_node) + cur_node = cur_node.left + else: + cur_node = stack.pop() + result.append(f(cur_node)) + cur_node = cur_node.right + return result + + def print_tree(self): + """ + 打印树的结构 + :return: + """ + queue = Queue(self.__root) + next_level = 1 + now_node_count = 0 + while not queue.empty(): + cur_node = queue.exit() + print str(cur_node) + "\t", + now_node_count += 1 + if now_node_count == next_level: + print + now_node_count = 0 + next_level *= 2 + if cur_node.left is not None: + queue.enter(cur_node.left) + + if cur_node.right is not None: + queue.enter(cur_node.right) + + def test(self): + print self.__successor(8) + + def __str__(self): + return "\t".join(self.midorder(lambda s: str(s))) + + +def main(): + tree = IntervalTree((16, 21), (8, 9), (5, 8), (15, 23), (0, 3), (6, 10), (25, 30), (17, 19), (26, 26), (19, 20)) + print tree + print tree.delete((25, 30)) + tree.print_tree() + + +if __name__ == "__main__": + main() diff --git a/src/ssj/tree/lchild_rbro_tree.py b/src/ssj/tree/lchild_rbro_tree.py new file mode 100644 index 0000000..79dbcb4 --- /dev/null +++ b/src/ssj/tree/lchild_rbro_tree.py @@ -0,0 +1,117 @@ +#!/usr/bin/env +# !-*- coding:utf-8 -*- + + +class Stack(object): + """ + 实现上还是有些问题的,因为没有考虑栈空间不够的时候扩展的问题 + """ + + def __init__(self, cap): + super(Stack, self).__init__() + self.__cap = cap # 栈大小 + self.__length = 0 # 栈长度 + if self.__cap < 0: + raise ValueError("length of Stack can not be negtive") + self.__values = [0 for x in xrange(0, self.__cap)] + + def empty(self): + return self.__length is 0 + + def push(self, x): + if self.__length >= self.__cap: + raise IndexError("stack is full, can not push any object") + self.__values[self.__length] = x + self.__length += 1 + + def pop(self): + if self.__length <= 0: + return None + self.__length -= 1 + return self.__values[self.__length] + + def __str__(self): + return "".join(["Stack, Value: ", str(self.__values), " cap: ", str(self.__cap), + " length:", str(self.__length)]) + + +class NTree(object): + """ + 用左孩子右兄弟的方式实现一个n可以有任意个子节点的树 + """ + + class Node(object): + """ + """ + + def __init__(self, key, child, brother): + self.key = key + self.child = child + self.brother = brother + + def __str__(self): + return str(key) + + def __init__(self, nodes, root_index=0): + """ + nodes是一个元祖列表,最前面的一个元素是节点值,后面的都是子节点的索引。 + 如果一个元祖中只有第一个元素,那么就认为这个元祖表示的是一个叶节点 + """ + super(NTree, self).__init__() + self.__root, self.__nodes = self.build_tree(nodes, root_index) + self.__size = len(nodes) + + def build_tree(self, nodes, root_index=0): + tree_nodes = [self.Node(node[0], node[1], node[2]) for node in nodes] + for node in tree_nodes: + node.child = tree_nodes[node.child] if node.child is not None else None + node.brother = tree_nodes[node.brother] if node.brother is not None else None + return (tree_nodes[root_index], tree_nodes) + + def depth_walk(self, f): + """ + 使用栈来实现深度遍历的时候,首先把兄弟节点进栈,然后把子节点放在栈中. + """ + result = [] + stack = Stack(self.__size) + stack.push(self.__root) + while not stack.empty(): + cur_node = stack.pop() + result.append(f(cur_node.key)) + if cur_node.brother is not None: + stack.push(cur_node.brother) + + if cur_node.child is not None: + stack.push(cur_node.child) + return result + + def breadth_walk(self, f): + """ + 使用队列实现广度遍历的思路是类似的,在访问到一个父节点的时候把所有的子节点都依次放到队列中 + """ + result = [] + q = queue.Queue(maxsize=-1) + q.put(self.__root) + while not q.empty(): + cur_node = q.get() + result.append(f(cur_node.key)) + # 注意:这儿的顺序比较讲究,不能调换 + child = cur_node.child + while child is not None: + q.put(child) + child = child.brother + return result + + def __str__(self): + return "\t".join(self.depth_walk(lambda key: str(key))) + + +def main(): + nodes = [(12, 6, 2), (15, 7, None), (4, 9, None), (10, 4, 8), (2, None, None), (18, 0, 3), (7, None, None), + (14, 5, 1), (21, None, None), (5, None, None)] + btree = NTree(nodes, 5) + print btree + + +if __name__ == '__main__': + main() diff --git a/src/ssj/tree/order_statistic_tree.py b/src/ssj/tree/order_statistic_tree.py new file mode 100644 index 0000000..dbf1358 --- /dev/null +++ b/src/ssj/tree/order_statistic_tree.py @@ -0,0 +1,452 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +from ssj.lib import Queue +from ssj.lib import Stack + +__author__ = 'shenshijun' + + +class OrderStatisticTree(object): + """ + 红黑树实现,红黑树的特性保证树的高度<=2lg(n+1),进而保证树中各个操作的性能. + 动态集合顺序统计底层使用红黑树实现,实现各个操作的复杂度都是lgn。 + 每一个子树的根节点在这个子树的相对顺序是左子节点的子树大小+1。因此根节点的序是根节点的左子节点的子树大小+1。 + """ + + class Node(object): + """ + 实现二叉树中的节点 + """ + + def __init__(self, key, left, right, parent, color, sub_size=1): + """ + color:true表示红色,false表示黑色 + """ + self.key = key + self.left = left + self.right = right + self.parent = parent + self.color = color + self.sub_size = sub_size + + def __cmp__(self, other): + return cmp(self.key, other.key) + + def __eq__(self, other): + return (self.key == other.key) and (other.color == self.color) + + def is_red(self): + return self.color + + def is_black(self): + return not self.color + + def __str__(self): + return "".join( + ["Node(key=", str(self.key), ", color=", + 'Red' if self.color else 'Black', + ', sub_size=', str(self.sub_size), ')']) + + def not_empty(self): + return self.left is not None and self.right is not None + + def inc(self): + if self.not_empty(): + self.sub_size += 1 + return self.sub_size + + def dec(self): + if self.not_empty(): + self.sub_size -= 1 + return self.sub_size + + def restore_sub_size(self): + if self.not_empty(): + self.sub_size = self.left.sub_size + self.right.sub_size + 1 + + def __init__(self, *vargs): + """""" + self.Nil = self.Node(None, None, None, None, False, 0) # 用Nil代替None可以简化逻辑 + self.__root = self.Nil + self.__size = 0 + map(self.insert, vargs) + + def __len__(self): + return self.__size + + def __left_rotate(self, node): + """ + 二叉搜索树左旋操作 + 可以证明旋转并不会影响node的父节点的sub_size,所以不需要修改node的父节点 + :param node:要旋转的分支的父节点 + :return:None + """ + right_child = node.right + right_left_child = right_child.left + parent = node.parent + if right_child is self.Nil: + raise NotImplementedError("没有右叶节点不支持左旋转") + + # 判断node是parent的左节点还是右节点 + if parent is not self.Nil: + if parent.left is node: + parent.left = right_child + else: + parent.right = right_child + if node is self.__root: + self.__root = right_child + self.__root.parent = self.Nil + node.right = right_left_child + right_child.parent = node.parent + node.parent = right_child + right_child.left = node + node.restore_sub_size() + right_child.restore_sub_size() + + def __right_rotate(self, node): + """ + 二叉搜索树右旋操作 + :param node:要被旋转的分子的父节点 + :return:None + """ + left_child = node.left + left_right_child = left_child.right + parent = node.parent + if left_child is self.Nil: + raise NotImplementedError('没有左节点不支持右旋转') + # 判断这个节点是在父节点的那个分支上 + if parent is not self.Nil: + if parent.left is node: + parent.left = left_child + else: + parent.right = left_child + if node is self.__root: + # 如果选择的正好是根节点,那么就需要宠幸设置根节点了 + self.__root = left_child + self.__root.parent = self.Nil + node.left = left_right_child + left_child.parent = node.parent + left_child.right = node + node.parent = left_child + node.restore_sub_size() + left_child.restore_sub_size() + + def insert(self, key): + cur_node = self.__root + node = self.Node(key, self.Nil, self.Nil, self.Nil, True) + if cur_node is self.Nil: # 根节点不存在的时候设置根节点 + self.__root = node + else: + parent_node = cur_node + while cur_node is not self.Nil: + parent_node = cur_node + cur_node.sub_size += 1 + if cur_node >= node: + cur_node = cur_node.left + else: + cur_node = cur_node.right + if parent_node >= node: + parent_node.left = node + else: + parent_node.right = node + node.parent = parent_node + self.__insert_fixup(node) + + def __insert_fixup(self, node): + # 首先判断节点是不是根节点或者父节点是不是根节点 + if node.parent is self.Nil or node.parent.parent is self.Nil: + self.__root.color = False + return + + cur_node = node + while cur_node.parent.is_red(): + # 首先需要分清父节点在哪个分支 + parent_node = cur_node.parent + grand_node = parent_node.parent + if parent_node is grand_node.left: + if grand_node.right.is_red(): # 情况1:只需要调整颜色,祖父节点设置成红色,父节点和叔节点设置成黑色,满足了特性3 + grand_node.color = True + parent_node.color = False + grand_node.right.color = False + cur_node = grand_node # 这个时候只有祖父节点可能会违反特性3,所有再调节这个节点 + elif parent_node.right is cur_node: # 情况2:需要左旋 + self.__left_rotate(parent_node) + cur_node = parent_node # 左旋之后,父节点一定会违背特性3,所以需要调节父节点 + else: # 情况3:右旋加重新设色 + grand_node.color = True + parent_node.color = False + self.__right_rotate(grand_node) + break + else: # 和上面的情况类似,只是这个时候所有的操作都反了 + if grand_node.left.is_red(): + grand_node.color = True + parent_node.color = False + grand_node.left.color = False + cur_node = grand_node + elif parent_node.left is cur_node: + self.__right_rotate(parent_node) + cur_node = parent_node + else: + grand_node.color = True + parent_node.color = False + self.__left_rotate(grand_node) + break + self.__root.color = False # 根节点必须被设置为黑色 + + def __transplant(self, old, new): + parent = old.parent + parent.sub_siz = parent.sub_size - old.sub_size + new.sub_size + if old is parent.left: + parent.left = new + else: + parent.right = new + if new is not self.Nil: + new.parent = parent + if parent is self.Nil: + self.__root = new + + def delete(self, instance): + node = self.__walk_find(instance, lambda n: n.dec()) + if node is self.Nil: + return node + deleted_color = node.color + if node.left is self.Nil: + self.__transplant(node, node.right) + replace_node = node.right + elif node.right is self.Nil: + self.__transplant(node, node.left) + replace_node = node.left + else: # 后继节点移动在右子树中,因为这个时候右子树一定存在 + successor = self.__walk_min(node.right, lambda n: n.dec()) + deleted_color = successor.color + replace_node = successor.right + if successor.parent is not node: + self.__transplant(successor, successor.right) + if replace_node is self.Nil: + replace_node.parent = successor.parent + if successor is not self.Nil: # 在处理的过程中不希望改变Nil的值 + successor.right = node.right + successor.right.parent = successor + self.__transplant(node, successor) + if successor is not self.Nil: + successor.left = node.left + successor.left.parent = successor + successor.color = node.color + successor.restore_sub_size() + successor.parent.restore_sub_size() + if not deleted_color: + self.__delete_fixup(replace_node) + if replace_node is self.Nil: + replace_node.parent = None + replace_node.left = None + replace_node.right = None + + def __find(self, key): + if key is None: + raise ValueError("None value not allowed in BSTree") + cur_node = self.__root + while cur_node is not self.Nil and cur_node.key != key: + if cur_node.key < key: + cur_node = cur_node.right + else: + cur_node = cur_node.left + return cur_node + + def __walk_find(self, key, func): + if key is None: + raise ValueError("None value not allowed in BSTree") + cur_node = self.__root + while cur_node is not self.Nil and cur_node.key != key: + func(cur_node) + if cur_node.key < key: + cur_node = cur_node.right + else: + cur_node = cur_node.left + return cur_node + + def __successor(self, value): + find_node = self.__find(value) + if find_node is self.Nil: + # 处理节点不存在的情况 + return None + if find_node.right is not self.Nil: + return self.__min(find_node.right) + else: + cur_parent = find_node.parent + cur_sub = find_node + while cur_parent is not self.Nil and cur_parent.right is cur_sub: + # 第一个条件是为了处理没有找到符合条件的父节点的情况,这个时候搜索失败 + cur_parent, cur_sub = cur_parent.parent, cur_parent + return cur_parent + + def max(self): + max_node = self.__max(self.__root) + return max_node.value if max_node is not None else None + + def __max(self, root): + cur_node = root + while cur_node.right is not self.Nil: + cur_node = cur_node.right + return cur_node + + def __min(self, root): + return self.__walk_min(root, lambda node: node) + + def __walk_min(self, root, func): + cur_node = root + while cur_node.left is not self.Nil: + func(cur_node) + cur_node = cur_node.left + return cur_node + + def min(self): + min_node = self.__min(self.__root) + return min_node.value if min_node is not None else None + + def __delete_fixup(self, node): + cur_node = node + while cur_node is not self.__root and cur_node.is_black(): + parent = cur_node.parent + if parent.left is cur_node: + # 判断是左支还是右支,仅仅是实现所限 + uncle = parent.right + if uncle.is_red(): + # 情况一:叔节点是红色,则重新设色并左旋 + uncle.color = False + parent.color = True + self.__left_rotate(parent) + elif uncle.left.is_black() and uncle.right.is_black(): + # 情况二(1):叔节点和其两个子节点都是黑色.则设置叔节点为红色,这个时候如果parent是红色,那么循环就会退出 + uncle.color = True + cur_node = parent + elif uncle.right.is_black(): + uncle.color = True + uncle.left.color = False + # 情况二(2):叔节点红和其右节点是黑色,那么意味着叔节点的左节点是红色,这个时候叔节点右旋并且父子节点交换颜色 + self.__right_rotate(uncle) + else: + # 情况二(3):叔节点是黑色,其右节点红色(可以由前面的转换而来),这个时候叔节点设红,其父节点和右子节点设黑并且父节点左旋 + parent.color = False + uncle.color = True + uncle.right.color = False + self.__left_rotate(parent) + # 退出情况 + cur_node = self.__root + else: + uncle = parent.left + if uncle.is_red(): + uncle.color = False + parent.color = True + self.__right_rotate(parent) + elif uncle.left.is_black() and uncle.right.is_black(): + uncle.color = True + cur_node = parent + elif uncle.left.is_black(): + uncle.color = True + uncle.right.color = False + self.__left_rotate(uncle) + else: + parent.color = False + uncle.color = True + uncle.left.color = False + self.__right_rotate(parent) + cur_node = self.__root + cur_node.color = False + + def midorder(self, f): + """ + 中序遍历 + :param f:访问一个节点的时候要对节点进行处理的函数 + :return: + """ + result = [] + stack = Stack(self.__root) + cur_node = self.__root.left + # 第一个阶段首先把所有树左边的节点放进栈里,这个时候并不遍历 + # 第二个阶段的时候由于左节点遍历了之后,再遍历右节点 + while not stack.empty() or cur_node is not self.Nil: + # 第二个判断条件比较重要,因为如果根节点没有左子树,这个时候栈就是空的,会直接退出循环 + if cur_node is not self.Nil: + stack.push(cur_node) + cur_node = cur_node.left + else: + cur_node = stack.pop() + result.append(f(cur_node)) + cur_node = cur_node.right + return result + + def print_tree(self): + """ + 打印树的结构 + :return: + """ + queue = Queue(self.__root) + next_level = 1 + now_node_count = 0 + while not queue.empty(): + cur_node = queue.exit() + print str(cur_node) + "\t", + now_node_count += 1 + if now_node_count == next_level: + print + now_node_count = 0 + next_level *= 2 + if cur_node.left is not None: + queue.enter(cur_node.left) + + if cur_node.right is not None: + queue.enter(cur_node.right) + + def test(self): + print self.__successor(8) + + def __str__(self): + return "\t".join(self.midorder(lambda s: str(s))) + + def os_select(self, index): + """ + 类似于二分查找,只是本来应该转向左边的逻辑变成了转向左子树 + 在转向右子树的时候要注意计算这个时候在右子树中的相对顺序 + 本质上就是把计算每一个节点的在本树的相对序,然后和需要查找的序对比看看是不是这个节点 + :param index: + :return: + """ + find_rank = index + cur_node = self.__root + while cur_node is not self.Nil: + cur_rank = cur_node.left.sub_size + 1 + if cur_rank == find_rank: + return cur_node.key + elif cur_rank < find_rank: + cur_node = cur_node.right + find_rank -= cur_rank + else: + cur_node = cur_node.left + return cur_node.key + + def os_rank(self, value): + cur_node = self.__root + move_right_incr = 0 + while cur_node is not self.Nil: + cur_rank = cur_node.left.sub_size + 1 + if cur_node.key == value: + return cur_rank + move_right_incr + elif cur_node.key >= value: + cur_node = cur_node.left + else: + cur_node = cur_node.right + # 在往右边移动的时候要记录下相对序和绝对序的差距 + move_right_incr += cur_rank + return -1 + + +def main(): + tree = OrderStatisticTree(7, 2, 1, 5, 4, 8, 11, 14, 14, 15) + print tree.os_select(1) + print tree.os_select(10) + print tree.os_select(5) + print tree.os_rank(11) + + +if __name__ == "__main__": + main() diff --git a/src/ssj/tree/red_black_tree.py b/src/ssj/tree/red_black_tree.py new file mode 100644 index 0000000..2d81020 --- /dev/null +++ b/src/ssj/tree/red_black_tree.py @@ -0,0 +1,375 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +from ssj.lib import Queue +from ssj.lib import Stack + +__author__ = 'shenshijun' + +""" +实际上,在红黑树中使用单例空节点会出现一个根本的问题:也就是父节点没法保存。这是一个大问题。 +可能应该用多个对象表示,或者实现没有父节点的红黑树 +""" + + +class RedBlackTree(object): + """ + 红黑树实现,红黑树的特性保证树的高度<=2lg(n+1),进而保证树中各个操作的性能. + """ + + class Node(object): + """ + 实现二叉树中的节点 + """ + + def __init__(self, key, left, right, parent, color): + """ + color:true表示红色,false表示黑色 + """ + self.key = key + self.left = left + self.right = right + self.parent = parent + self.color = color + + def __cmp__(self, other): + return cmp(self.key, other.key) + + def __eq__(self, other): + return (self.key == other.key) and (other.color == self.color) + + def is_red(self): + return self.color + + def is_black(self): + return not self.color + + def __str__(self): + return "".join( + ["Node(key=", str(self.key), ", color=", + 'Red)' if self.color else 'Black)']) + + def __init__(self, *vargs): + """""" + self.Nil = self.Node(None, None, None, None, False) # 用Nil代替None可以简化逻辑 + self.__root = self.Nil + self.__size = 0 + map(self.insert, vargs) + + def __len__(self): + return self.__size + + def __left_rotate(self, node): + """ + 二叉搜索树左旋操作 + :param node:要旋转的分支的父节点 + :return:None + """ + right_child = node.right + right_child_left = right_child.left + parent = node.parent + if right_child is self.Nil: + raise NotImplementedError("没有右叶节点不支持左旋转") + + # 判断node是parent的左节点还是右节点 + if parent is not self.Nil: + if parent.left is node: + parent.left = right_child + else: + parent.right = right_child + if node is self.__root: + self.__root = right_child + self.__root.parent = self.Nil + node.right = right_child_left + right_child.parent = node.parent + node.parent = right_child + right_child.left = node + + def __right_rotate(self, node): + """ + 二叉搜索树右旋操作 + :param node:要被旋转的分子的父节点 + :return:None + """ + left_child = node.left + left_right_child = left_child.right + parent = node.parent + if left_child is self.Nil: + raise NotImplementedError('没有左节点不支持右旋转') + # 判断这个节点是在父节点的那个分支上 + if parent is not self.Nil: + if parent.left is node: + parent.left = left_child + else: + parent.right = left_child + if node is self.__root: + # 如果选择的正好是根节点,那么就需要宠幸设置根节点了 + self.__root = left_child + self.__root.parent = self.Nil + node.left = left_right_child + left_child.parent = node.parent + left_child.right = node + node.parent = left_child + + def insert(self, key): + cur_node = self.__root + node = self.Node(key, self.Nil, self.Nil, self.Nil, True) + if cur_node is self.Nil: # 根节点不存在的时候设置根节点 + self.__root = node + else: + parent_node = cur_node + while cur_node is not self.Nil: + parent_node = cur_node + if cur_node >= node: + cur_node = cur_node.left + else: + cur_node = cur_node.right + if parent_node >= node: + parent_node.left = node + else: + parent_node.right = node + node.parent = parent_node + self.__insert_fixup(node) + + def __insert_fixup(self, node): + # 首先判断节点是不是根节点或者父节点是不是根节点 + if node.parent is self.Nil or node.parent.parent is self.Nil: + self.__root.color = False + return + + cur_node = node + while cur_node.parent.is_red(): + # 首先需要分清父节点在哪个分支 + parent_node = cur_node.parent + grand_node = parent_node.parent + if parent_node is grand_node.left: + if grand_node.right.is_red(): # 情况1:只需要调整颜色,祖父节点设置成红色,父节点和叔节点设置成黑色,满足了特性3 + grand_node.color = True + parent_node.color = False + grand_node.right.color = False + cur_node = grand_node # 这个时候只有祖父节点可能会违反特性3,所有再调节这个节点 + elif parent_node.right is cur_node: # 情况2:需要左旋 + self.__left_rotate(parent_node) + cur_node = parent_node # 左旋之后,父节点一定会违背特性3,所以需要调节父节点 + else: # 情况3:右旋加重新设色 + grand_node.color = True + parent_node.color = False + self.__right_rotate(grand_node) + break + else: # 和上面的情况类似,只是这个时候所有的操作都反了 + if grand_node.left.is_red(): + grand_node.color = True + parent_node.color = False + grand_node.left.color = False + cur_node = grand_node + elif parent_node.left is cur_node: + self.__right_rotate(parent_node) + cur_node = parent_node + else: + grand_node.color = True + parent_node.color = False + self.__left_rotate(grand_node) + break + self.__root.color = False # 根节点必须被设置为黑色 + + def __transplant(self, old, new): + parent = old.parent + if old is parent.left: + parent.left = new + else: + parent.right = new + if new is not self.Nil: + new.parent = parent + if parent is self.Nil: + self.__root = new + + def delete(self, instance): + node = self.__find(instance) + if node is self.Nil: + return node + deleted_color = node.color + if node.left is self.Nil: + self.__transplant(node, node.right) + replace_node = node.right + elif node.right is self.Nil: + self.__transplant(node, node.left) + replace_node = node.left + else: # 后继节点移动在右子树中,因为这个时候右子树一定存在 + successor = self.__successor(instance) + deleted_color = successor.color + replace_node = successor.right + if successor.parent is not node: + self.__transplant(successor, successor.right) + if replace_node is self.Nil: + replace_node.parent = successor.parent + if successor is not self.Nil: # 在处理的过程中不希望改变Nil的值 + successor.right = node.right + successor.right.parent = successor + self.__transplant(node, successor) + if successor is not self.Nil: + successor.left = node.left + successor.left.parent = successor + successor.color = node.color + if not deleted_color: + self.__delete_fixup(replace_node) + if replace_node is self.Nil: + replace_node.parent = None + replace_node.left = None + replace_node.right = None + + def __find(self, key): + if key is None: + raise ValueError("None value not allowed in BSTree") + cur_node = self.__root + while cur_node is not self.Nil and cur_node.key != key: + if cur_node.key < key: + cur_node = cur_node.right + else: + cur_node = cur_node.left + return cur_node + + def __successor(self, value): + find_node = self.__find(value) + if find_node is self.Nil: + # 处理节点不存在的情况 + return None + if find_node.right is not self.Nil: + return self.__min(find_node.right) + else: + cur_parent = find_node.parent + cur_sub = find_node + while cur_parent is not self.Nil and cur_parent.right is cur_sub: + # 第一个条件是为了处理没有找到符合条件的父节点的情况,这个时候搜索失败 + cur_parent, cur_sub = cur_parent.parent, cur_parent + return cur_parent + + def max(self): + max_node = self.__max(self.__root) + return max_node.value if max_node is not None else None + + def __max(self, root): + cur_node = root + while cur_node.right is not self.Nil: + cur_node = cur_node.right + return cur_node + + def __min(self, root): + cur_node = root + while cur_node.left is not self.Nil: + cur_node = cur_node.left + return cur_node + + def min(self): + min_node = self.__min(self.__root) + return min_node.value if min_node is not None else None + + def __delete_fixup(self, node): + cur_node = node + while cur_node is not self.__root and cur_node.is_black(): + parent = cur_node.parent + if parent.left is cur_node: + # 判断是左支还是右支,仅仅是实现所限 + brother = parent.right + if brother.is_red(): + # 情况一:兄弟节点是红色,则重新设色并左旋 + brother.color = False + parent.color = True + self.__left_rotate(parent) + cur_node = brother + elif brother.left.is_black() and brother.right.is_black(): + # 情况二(1):兄弟节点和其两个子节点都是黑色.则设置兄弟节点为红色,这个时候如果parent是红色,那么循环就会退出 + brother.color = True + cur_node = parent + elif brother.right.is_black(): + brother.color = True + brother.left.color = False + # 情况二(2):兄弟节点红和其右节点是黑色,那么意味着兄弟节点的左节点是红色,这个时候兄弟节点右旋并且父子节点交换颜色 + self.__right_rotate(brother) + else: + # 情况二(3):兄弟节点是黑色,其右节点红色(可以由前面的转换而来),这个时候兄弟节点设红,其父节点和右子节点设黑并且父节点左旋 + parent.color = False + brother.color = True + brother.right.color = False + self.__left_rotate(parent) + # 退出情况 + cur_node = self.__root + else: + brother = parent.left + if brother.is_red(): + brother.color = False + parent.color = True + self.__right_rotate(parent) + elif brother.left.is_black() and brother.right.is_black(): + brother.color = True + cur_node = parent + elif brother.left.is_black(): + brother.color = True + brother.right.color = False + self.__left_rotate(brother) + else: + parent.color = False + brother.color = True + brother.left.color = False + self.__right_rotate(parent) + cur_node = self.__root + cur_node.color = False + + def midorder(self, f): + """ + 中序遍历 + :param f:访问一个节点的时候要对节点进行处理的函数 + :return: + """ + result = [] + stack = Stack(self.__root) + cur_node = self.__root.left + # 第一个阶段首先把所有树左边的节点放进栈里,这个时候并不遍历 + # 第二个阶段的时候由于左节点遍历了之后,再遍历右节点 + while not stack.empty() or cur_node is not self.Nil: + # 第二个判断条件比较重要,因为如果根节点没有左子树,这个时候栈就是空的,会直接退出循环 + if cur_node is not self.Nil: + stack.push(cur_node) + cur_node = cur_node.left + else: + cur_node = stack.pop() + result.append(f(cur_node)) + cur_node = cur_node.right + return result + + def print_tree(self): + """ + 打印树的结构 + :return: + """ + queue = Queue(self.__root) + next_level = 1 + now_node_count = 0 + while not queue.empty(): + cur_node = queue.exit() + print str(cur_node) + "\t", + now_node_count += 1 + if now_node_count == next_level: + print + now_node_count = 0 + next_level *= 2 + if cur_node.left is not None: + queue.enter(cur_node.left) + + if cur_node.right is not None: + queue.enter(cur_node.right) + + def test(self): + print self.__successor(8) + + def __str__(self): + return "\t".join(self.midorder(lambda s: str(s))) + + +def main(): + tree = RedBlackTree(7, 2, 1, 5, 4, 8, 11, 14, 14, 15) + print tree + print tree.delete(5) + tree.print_tree() + + +if __name__ == "__main__": + main() diff --git a/src/ssj/tree/tries.py b/src/ssj/tree/tries.py new file mode 100644 index 0000000..1dc2140 --- /dev/null +++ b/src/ssj/tree/tries.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + + +class Tries(object): + """ + 字符串前缀树实现 + """ + + def __init__(self): + """""" + pass From bdb61f3ef52f8eead9cb8a2fc686f9e1ffdf543e Mon Sep 17 00:00:00 2001 From: ssjssh Date: Fri, 25 Sep 2015 23:18:15 +0800 Subject: [PATCH 10/23] =?UTF-8?q?leecode=E7=9A=84=E7=AC=AC=E5=9B=9B?= =?UTF-8?q?=E9=A2=98=E8=B7=B3=E8=BF=87=E5=90=A7=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/leecode/find_median_sorted_arrays.py | 23 +++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/ssj/leecode/find_median_sorted_arrays.py b/src/ssj/leecode/find_median_sorted_arrays.py index f7dc618..b8a1224 100644 --- a/src/ssj/leecode/find_median_sorted_arrays.py +++ b/src/ssj/leecode/find_median_sorted_arrays.py @@ -17,6 +17,9 @@ 比较k/2位置处数字的大小,小的那一部分一定是在k小的数字之内(可以假设法证明),这样剩下的问题就是从剩下的列表中找 第k/2位数了.等到这个数为1,那么就好计算了. + +注意:本解答仍然有问题。 + """ @@ -38,6 +41,7 @@ def findMedianSortedArrays(self, nums1, nums2): len2 = len(nums2) if (len1 + len2) % 2 is 0: + return (self.__findKth(4, nums1, nums2)) return (self.__findKth((len1 + len2) / 2 + 1, nums1, nums2) + self.__findKth((len1 + len2) / 2, nums1, nums2)) / 2.0 else: @@ -55,22 +59,21 @@ def __findMedian(li): def __findKth(k, l1, l2): l1_start = 0 l2_start = 0 - k -= 1 - while (len(l1) + len(l2) - l1_start - l2_start - 1) >= k: - if k is 0: + while (len(l1) + len(l2) - l1_start - l2_start) >= k: + if k is 1: return min(l1[l1_start], l2[l2_start]) if len(l1) - l1_start < len(l2) - l2_start: - l1_comp_start = l1_start + min(len(l1), k / 2) - l2_comp_start = k - min(len(l1), k / 2) + l2_start + l1_comp_start = l1_start + min(len(l1) - l1_start, k / 2) + l2_comp_start = k - min(len(l1) - l1_start, k / 2) + l2_start - 1 else: - l2_comp_start = min(len(l2), k / 2) + l2_start - l1_comp_start = k - min(len(l2), k / 2) + l1_start + l2_comp_start = min(len(l2) - l2_start, k / 2) + l2_start + l1_comp_start = k - min(len(l2) - l2_start, k / 2) + l1_start - 1 if l1[l1_comp_start] > l2[l2_comp_start]: - k -= (l2_comp_start - l2_start) + k -= (l2_comp_start - l2_start + 1) l2_start = l2_comp_start + 1 elif l1[l1_comp_start] < l2[l2_comp_start]: - k -= (l1_comp_start - l1_start) + k -= (l1_comp_start - l1_start + 1) l1_start = l1_comp_start + 1 else: return l1[l1_comp_start] @@ -79,7 +82,7 @@ def __findKth(k, l1, l2): def main(): print(Solution().findMedianSortedArrays([0, 1, 2, 3, 4], [0, 1, 2])) # 1 - print(Solution().findMedianSortedArrays([], [1])) # + # print(Solution().findMedianSortedArrays([], [1])) # if __name__ == "__main__": From 65c1bd429853b0059d7cd46eeff1958869203e06 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sat, 26 Sep 2015 12:14:41 +0800 Subject: [PATCH 11/23] =?UTF-8?q?leecode=E7=9A=84=E7=AC=AC=E4=BA=94?= =?UTF-8?q?=E9=A2=98=E5=AE=8C=E6=88=90=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leecode/longest_palindromic_substring.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/ssj/leecode/longest_palindromic_substring.py diff --git a/src/ssj/leecode/longest_palindromic_substring.py b/src/ssj/leecode/longest_palindromic_substring.py new file mode 100644 index 0000000..29df72c --- /dev/null +++ b/src/ssj/leecode/longest_palindromic_substring.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. + +我的解法就是这个解法:http://taop.marchtea.com/01.05.html +感谢 +""" + + +class Solution(object): + def longestPalindrome(self, original): + """ + :type s: str + :rtype: str + """ + if not original: + return 0 + s = self.__preProcess(original) + longest_right_bound = 0 + longest_median = 0 + pali_list = [1 for i in range(len(s))] + # 注意迭代位置,为了不出现越界,最前和最后的字符串是不会被遍历的 + for i in range(1, len(s) - 1): + # 这边使用的是对称的原理,使得可以快速个p[i]一个基础的值 + if longest_right_bound > i: + if longest_right_bound - i <= pali_list[2 * longest_median - i]: + pali_list[i] = longest_right_bound - i + else: + pali_list[i] = pali_list[2 * longest_median - i] + # 在字符串的最前面和最后面都必须加上一个特殊字符,用于防止越界 + # 另一个方法是在每次循环的时候都判断边界,但是效率比直接加特殊字符低 + while s[i + pali_list[i]] == s[i - pali_list[i]]: + pali_list[i] += 1 + if pali_list[i] >= longest_right_bound - longest_median: + longest_right_bound = pali_list[i] + i + longest_median = i + return self.__clearString(s[2 * longest_median - longest_right_bound + 1:longest_right_bound]) + + def __clearString(self, sub_str): + return "".join([ch for ch in sub_str if ch != '#']) + + def __preProcess(self, s): + str_list = ['#{}'.format(ele) for ele in s] + str_list.append("#$") + str_list.insert(0, '^') + return "".join(str_list) + + +def main(): + print(Solution().longestPalindrome("bbbbbb")) # 6 + print(Solution().longestPalindrome("fqwefqwefqwadccdaafwfawef")) # 6 + print(Solution().longestPalindrome("qwefqwefqsjsjsssgsssjsjsg3q4gekwSKDFKALJKFIUWIUEFWEG")) # 15 + print(Solution().longestPalindrome("ababababa")) # 10 + + +if __name__ == "__main__": + main() From d89a2c8fee41ec36403b4b1cb26ed0f24b1d74b4 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sun, 27 Sep 2015 15:56:55 +0800 Subject: [PATCH 12/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9hashmap=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E4=B8=AD=E7=9A=84bug=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/map/hash_map.py | 99 ++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/src/ssj/map/hash_map.py b/src/ssj/map/hash_map.py index 0acf6e7..abd116e 100644 --- a/src/ssj/map/hash_map.py +++ b/src/ssj/map/hash_map.py @@ -20,14 +20,17 @@ class Node(object): 哈希表中存储的节点 """ - def __init__(self, key, value, hash_code, prev, nex): + def __init__(self, key, value, hash_code, nex, last_insert, next_insert): """ + nex用来解决链表的哈希冲突 + next_insert用来记录下一个插入的元素 """ self.key = key self.value = value self.hash_code = hash_code self.nex = nex - self.prev = prev + self.last_insert = last_insert + self.next_insert = next_insert def __cmp__(self, other): return cmp(self.key, other.key) @@ -44,13 +47,13 @@ def __init__(self): """""" self.__load_factor = 0 self.__size = 0 # 表示真正存储的元素有几个 - self.__power = HashMap.DEFAULT_SIZE_POWER + self.__power = HashMap.DEFAULT_SIZE_POWER # 把哈希表大小存储为幂数,这样的好处不用在扩展时再从头计算 self.__cap = HashMap.DEFAULT_SIZE # 表示哈希表的容量 self.__head = None - self.__last_put = None - self.__values = [[] for x in range(0, self.__cap)] + self.__last_put = None # 存储上一个插入时的元素,这样便于在插入新元素的时候用指针把他们按照插入顺序连接起来 + self.__values = [None for x in range(0, self.__cap)] # 主要使用的列表 - def hash(self, key): + def __get_index(self, key): """ 乘法哈希函数 :param key: @@ -72,67 +75,87 @@ def __resize(self): # 如果哈希表太满了,则把原来的所有元素都重新插入到哈希表中去 self.__cap *= 2 self.__power += 1 - old_values = self.__values - self.__values = [[] for x in xrange(0, self.__cap)] + self.__values = [None for x in xrange(0, self.__cap)] self.__size = 0 self.__load_factor = 0 self.__last_put = None cur_node = self.__head self.__head = None - while cur_node is not None: + while cur_node: self.__setitem__(cur_node.key, cur_node.value) - cur_node = cur_node.nex + cur_node = cur_node.next_insert def foreach(self, f): cur_node = self.__head - while cur_node is not None: + while cur_node: yield f(cur_node.key, cur_node.value) - cur_node = cur_node.nex + cur_node = cur_node.next_insert def __get(self, key): - index = self.hash(key) - indexed_nodes = self.__values[index] - for node in indexed_nodes: - if node.key == key: - return node + index = self.__get_index(key) + indexed_node = self.__values[index] + while indexed_node: + if indexed_node.key == key: + return indexed_node + indexed_node = indexed_node.nex return None def __contains__(self, key): node = self.__get(key) - return False if node is None else True + return node def __getitem__(self, item): node = self.__get(item) return None if node is None else node.value def __setitem__(self, key, value): - node = self.Node(key, value, HashMap.hash_code(key), self.__last_put, None) - index = self.hash(key) + index = self.__get_index(key) + exists_nodes = self.__values[index] exists_flag = False - for x in range(0, len(exists_nodes)): - if node == exists_nodes[x]: - exists_nodes[x] = node - exists_flag = True + if exists_nodes: + cur_node = exists_nodes + while cur_node: + if cur_node.key == key: + exists_flag = True + cur_node.value = value + node = cur_node + break + cur_node = cur_node.nex + if not exists_flag: - exists_nodes.append(node) + node = self.Node(key, value, HashMap.hash_code(key), exists_nodes, self.__last_put, None) + self.__values[index] = node self.__size += 1 - if self.__last_put is not None: - self.__last_put.nex = node + + if self.__last_put: + self.__last_put.next_insert = node self.__last_put = node - if self.__head is None: + if not self.__head: self.__head = node - self.__load_factor = float(self.__size) / self.__cap self.__resize() def __delitem__(self, key): old_value = None - index = self.hash(key) - indexed_nodes = self.__values[index] - for x in xrange(len(indexed_nodes)): - if indexed_nodes[x].key == key: - old_value = indexed_nodes[x].value - del indexed_nodes[x] + index = self.__get_index(key) + indexed_node = self.__values[index] + last_node = None + while indexed_node: + if indexed_node.key == key: + old_value = indexed_node.value + if last_node: + last_node.nex = indexed_node.nex + else: + self.__values[index] = indexed_node.nex + # 处理哈希表 + self.__size -= 1 + if indexed_node.last_insert: + indexed_node.last_insert.next_insert = indexed_node.next_insert + + if indexed_node.next_insert: + indexed_node.next_insert.last_insert = indexed_node.last_insert + last_node = indexed_node + indexed_node = indexed_node.nex return old_value def __len__(self): @@ -148,8 +171,10 @@ def main(): d["ssh" + str(x)] = x print len(d) print d - del d['ssj100'] - print d['ssj100'] + del d['ssh100'] + print d['ssh100'] + print(len(d)) + print(d) if __name__ == "__main__": From 88a78d8b56cd086ee80acb7014a7bdbb3869ca62 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sun, 27 Sep 2015 19:08:22 +0800 Subject: [PATCH 13/23] =?UTF-8?q?=E5=AE=8C=E6=88=90leecode=E7=AC=AC7?= =?UTF-8?q?=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 ++- src/ssj/leecode/reverse_integer.c | 71 +++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/ssj/leecode/reverse_integer.c diff --git a/.gitignore b/.gitignore index 886d710..f7dc621 100755 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,8 @@ docs/_build/ # PyBuilder target/ -test.py \ No newline at end of file +test.py + +#c out file +*.out +*.exe \ No newline at end of file diff --git a/src/ssj/leecode/reverse_integer.c b/src/ssj/leecode/reverse_integer.c new file mode 100644 index 0000000..08034dd --- /dev/null +++ b/src/ssj/leecode/reverse_integer.c @@ -0,0 +1,71 @@ +/** +*本题目使用C编写,因为Python的int类型是无限大的,要判断一个数字是否溢出非常简单,祝需要和2^32-1比较就好了 +*/ + +#include +#include +#include + + +int intToString(int i,char *arr){ + int t_len = sprintf(arr,"%d",i); + arr[t_len] = '\0'; + return t_len; +} +int willOverflow(char *result,int is_negative){ + char min_str[40]; + char max_str[40]; + int max_len = intToString(INT_MAX,max_str); + int min_len = intToString(INT_MIN,min_str); + int result_len = strlen(result); + if((is_negative&&result_len 0){ + *tar_c = x%10+'0'; + x /= 10; + tar_c++; + } + *tar_c='\0'; + if(willOverflow(intStr,is_negative)){ + return 0; + } + for(tar_c = intStr;(*tar_c)!='\0';tar_c++){ + if ((*tar_c)!='-'){ + + result *= 10; + result += (*tar_c)-'0'; + } + } + if(intStr[0]=='-'){ + result = -result; + } + + return result; +} + + + +int main(){ + printf("%d\n",reverse(1231312)); + printf("%d\n",reverse(123)); + printf("%d\n",reverse(-1231312)); + printf("%d\n",reverse(1000000003)); + printf("%d\n",reverse(-1000000003)); + return 0; +} \ No newline at end of file From 8091a521158e9d197b3395d985e78824ccfb7d2a Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sun, 27 Sep 2015 20:19:51 +0800 Subject: [PATCH 14/23] =?UTF-8?q?=E5=AE=8C=E6=88=90leecode=E7=AC=AC8?= =?UTF-8?q?=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/leecode/atoi.c | 98 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/ssj/leecode/atoi.c diff --git a/src/ssj/leecode/atoi.c b/src/ssj/leecode/atoi.c new file mode 100644 index 0000000..670ce17 --- /dev/null +++ b/src/ssj/leecode/atoi.c @@ -0,0 +1,98 @@ +#include +#include +#include + + +static int intToString(int i,char *arr){ + int t_len = sprintf(arr,"%d",i); + arr[t_len] = '\0'; + return t_len; +} +static int myStrcmp(char *start,char *end,char *other){ + for(char *c1 = start,*c2 = other;c1<=end&&c2!='\0';c1++,c2++){ + if (*c1 > *c2){ + return 1; + }else if(*c1 < *c2){ + return -1; + } + } + return 0; +} + +int myAtoi(char* str) { + int is_negative = 0; + char *start=NULL,*end=NULL; + for(char *c=str;c!='\0';c++){ + if(start==NULL && (*c == ' ' || *c =='\n' || *c == '\t')){ + continue; + }else if((*c=='-' || (*c >='0' && *c<='9') || *c=='+') && start==NULL){ + start = c; + if(*c == '-'){ + is_negative=1; + } + }else if(*c >='0' && *c<='9'&& start!=NULL){ + end = c; + }else{ + break; + } + } + + if(start==NULL){ + return 0; + }else if (end==NULL){ + end = start; + } + + if(*start == '+'){ + start++; + } + +// printf("%c:%c\n",*start,*end); + //检查是否越界 + int result_len = end - start + 1; + if(is_negative){ + char min_str[40]; + int min_len = intToString(INT_MIN,min_str); + if(result_len>min_len || (result_len == min_len && myStrcmp(start,end,min_str)>0)){ + return INT_MIN; + } + }else{ + char max_str[40]; + int max_len = intToString(INT_MAX,max_str); + if(result_len>max_len || (result_len == max_len && myStrcmp(start,end,max_str)>0)){ + return INT_MAX; + } + } + + int result = 0; + +// printf("%c:%c",*start,*end); + for(char *c=start;c<=end;c++){ + if(*c != '-' && *c != '+'){ + result *= 10; + result += (*c - '0'); + } + } + + if(*start=='-'){ + result = -result; + } + return result; +} + + +int main(){ + printf("%d\n",myAtoi("+1231312")); + printf("%d\n",myAtoi(" -11919730356x")); + printf("%d\n",myAtoi(" +1146905820n1")); + printf("%d\n",myAtoi("1")); + printf("%d\n",myAtoi("123")); + printf("%d\n",myAtoi("-1231312")); + printf("%d\n",myAtoi("-1231312fqwef")); + printf("%d\n",myAtoi("-1231312 992")); + printf("%d\n",myAtoi("3000000001")); + printf("%d\n",myAtoi("-3000000001")); + printf("%d\n",myAtoi("wefwqef-3000000001")); + printf("%d\n",myAtoi(" -3000000001")); + return 0; +} \ No newline at end of file From 6e42aa0fb3b1845135ae41135d6f9be3629457b1 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Wed, 30 Sep 2015 10:08:19 +0800 Subject: [PATCH 15/23] =?UTF-8?q?=E5=AE=8C=E6=88=90leecode=E7=AC=AC9?= =?UTF-8?q?=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/leecode/palindrome_number.c | 41 ++++++++++++++++++ src/ssj/leecode/reverse_integer.c | 64 ++++++----------------------- 2 files changed, 54 insertions(+), 51 deletions(-) create mode 100644 src/ssj/leecode/palindrome_number.c diff --git a/src/ssj/leecode/palindrome_number.c b/src/ssj/leecode/palindrome_number.c new file mode 100644 index 0000000..0232605 --- /dev/null +++ b/src/ssj/leecode/palindrome_number.c @@ -0,0 +1,41 @@ +/** +*Determine whether an integer is a palindrome. Do this without extra space. +*/ + +/** +可以直接把int逆转,然后只需要判断他们是不是相等就可以了 +关于溢出的问题 +1,如果原来的数字没有溢出,那么如果他们是回文,那么逆转后的数字也不会越界。这样保证如果是回文,那么就不会越界。 +2,如果原来的数字不是回文,那么逆转后的数字一定不会溢出,因此一旦在逆转数字的时候出现溢出,那么就可以判断这个数字不是回文 +**/ + +#include +#include +#include +#include + +bool isPalindrome(int x){ + if(x<0) return 0; + int res = 0; + int tmp = x; + while (x != 0) { + /** + * 假设INT_MAX / 10 = m,因为他是一个浮点数,那么假设他在n-1,n之间 + * 那么也就是abs(res)的最大值是n-1,这个数字是在接下来的计算中可能会越界(依赖于x % 10的值) + * 如果abs(res)为n,那么就一定会发生越界 + */ + if (abs(res) > INT_MAX / 10 || abs(res) * 10 > INT_MAX - abs(x) % 10) return 0; + res = res * 10 + x % 10; + x /= 10; + } + return res==tmp; +} + +int main(){ + printf("%d\n",isPalindrome(1)); + printf("%d\n",isPalindrome(0)); + printf("%d\n",isPalindrome(12311321)); + printf("%d\n",isPalindrome(-12311321)); + printf("%d\n",isPalindrome(-2147447412)); + return 0; +} diff --git a/src/ssj/leecode/reverse_integer.c b/src/ssj/leecode/reverse_integer.c index 08034dd..a991cb6 100644 --- a/src/ssj/leecode/reverse_integer.c +++ b/src/ssj/leecode/reverse_integer.c @@ -3,60 +3,22 @@ */ #include -#include #include +#include - -int intToString(int i,char *arr){ - int t_len = sprintf(arr,"%d",i); - arr[t_len] = '\0'; - return t_len; -} -int willOverflow(char *result,int is_negative){ - char min_str[40]; - char max_str[40]; - int max_len = intToString(INT_MAX,max_str); - int min_len = intToString(INT_MIN,min_str); - int result_len = strlen(result); - if((is_negative&&result_len 0){ - *tar_c = x%10+'0'; - x /= 10; - tar_c++; - } - *tar_c='\0'; - if(willOverflow(intStr,is_negative)){ - return 0; - } - for(tar_c = intStr;(*tar_c)!='\0';tar_c++){ - if ((*tar_c)!='-'){ - - result *= 10; - result += (*tar_c)-'0'; - } - } - if(intStr[0]=='-'){ - result = -result; - } - - return result; + int res = 0; + while (x != 0) { + /** + * 假设INT_MAX / 10 = m,因为他是一个浮点数,那么假设他在n-1,n之间 + * 那么也就是abs(res)的最大值是n-1,这个数字是在接下来的计算中可能会越界(依赖于x % 10的值) + * 如果abs(res)为n,那么就一定会发生越界 + */ + if (abs(res) > INT_MAX / 10 || abs(res) * 10 > INT_MAX - abs(x) % 10) return 0; + res = res * 10 + x % 10; + x /= 10; + } + return res; } From b1d84110ee5907697482bdab885ff83a9fb2a930 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sat, 10 Oct 2015 09:50:51 +0800 Subject: [PATCH 16/23] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/clrs/README.md | 1 + .../find_max_sublist_without_ recursion.py | 24 ------------ src/ssj/dynamic/README.md | 0 src/ssj/graph/README.md | 0 src/ssj/graph/general_graph.py | 3 +- src/ssj/graph/weighted_graph.py | 2 +- src/ssj/greedy/README.md | 0 src/ssj/heap/README.md | 0 src/ssj/leecode/README.md | 0 .../leecode/regular_expression_matching.py | 31 +++++++++++++++ src/ssj/lib/README.md | 0 src/ssj/list/README.md | 0 src/ssj/map/README.md | 0 src/ssj/matrix/README.md | 0 src/ssj/number_theory/README.md | 0 src/ssj/other/README.md | 3 ++ src/ssj/{divide_conquer => other}/__init__.py | 0 .../find_max_sublist.py | 8 +++- .../find_max_sublist_without_recursion.py | 39 +++++++++++++++++++ src/ssj/{divide_conquer => other}/power.py | 2 +- .../{divide_conquer => other}/yong_matrix.py | 0 src/ssj/queue/README.md | 0 src/ssj/search/README.md | 0 src/ssj/sort/README.md | 0 src/ssj/string/README.md | 0 src/ssj/tree/BTree.py | 2 +- src/ssj/tree/README.md | 0 src/ssj/tree/binarystree.py | 4 +- src/ssj/tree/interval_tree.py | 4 +- src/ssj/tree/order_statistic_tree.py | 4 +- src/ssj/tree/red_black_tree.py | 4 +- 31 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 src/ssj/clrs/README.md delete mode 100755 src/ssj/divide_conquer/find_max_sublist_without_ recursion.py create mode 100644 src/ssj/dynamic/README.md create mode 100644 src/ssj/graph/README.md create mode 100644 src/ssj/greedy/README.md create mode 100644 src/ssj/heap/README.md create mode 100644 src/ssj/leecode/README.md create mode 100644 src/ssj/leecode/regular_expression_matching.py create mode 100644 src/ssj/lib/README.md create mode 100644 src/ssj/list/README.md create mode 100644 src/ssj/map/README.md create mode 100644 src/ssj/matrix/README.md create mode 100644 src/ssj/number_theory/README.md create mode 100644 src/ssj/other/README.md rename src/ssj/{divide_conquer => other}/__init__.py (100%) rename src/ssj/{divide_conquer => other}/find_max_sublist.py (88%) create mode 100755 src/ssj/other/find_max_sublist_without_recursion.py rename src/ssj/{divide_conquer => other}/power.py (92%) rename src/ssj/{divide_conquer => other}/yong_matrix.py (100%) create mode 100644 src/ssj/queue/README.md create mode 100644 src/ssj/search/README.md create mode 100644 src/ssj/sort/README.md create mode 100644 src/ssj/string/README.md create mode 100644 src/ssj/tree/README.md diff --git a/src/ssj/clrs/README.md b/src/ssj/clrs/README.md new file mode 100644 index 0000000..5d405c2 --- /dev/null +++ b/src/ssj/clrs/README.md @@ -0,0 +1 @@ +算法导论里面的习题 \ No newline at end of file diff --git a/src/ssj/divide_conquer/find_max_sublist_without_ recursion.py b/src/ssj/divide_conquer/find_max_sublist_without_ recursion.py deleted file mode 100755 index 91810a9..0000000 --- a/src/ssj/divide_conquer/find_max_sublist_without_ recursion.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -*- -def find_max_sublist(li): - b, max_sum, left, right = 0, 0, 0, 0 - li_len = len(li) - for x in xrange(0, li_len): - if b < 0: - b = li[x] - left = x - else: - b += li[x] - if max_sum < b: - right = x - max_sum = b - - return left, right, max_sum - - -def main(): - print find_max_sublist([1, -2, 3, 10, -4, 7, 2, -5]) - - -if __name__ == '__main__': - main() diff --git a/src/ssj/dynamic/README.md b/src/ssj/dynamic/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/graph/README.md b/src/ssj/graph/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/graph/general_graph.py b/src/ssj/graph/general_graph.py index b9f8871..8bc02f8 100644 --- a/src/ssj/graph/general_graph.py +++ b/src/ssj/graph/general_graph.py @@ -2,12 +2,11 @@ # -*- coding:UTF-8 import sys +from ssj.lib.stack import Stack reload(sys) sys.setdefaultencoding('UTF-8') -from ssj.lib import queue -from ssj.lib import Stack __author__ = 'shenshijun' diff --git a/src/ssj/graph/weighted_graph.py b/src/ssj/graph/weighted_graph.py index 41bc024..e1eb1db 100644 --- a/src/ssj/graph/weighted_graph.py +++ b/src/ssj/graph/weighted_graph.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from ssj.lib import Queue +from ssj.lib.queue import Queue __author__ = 'shenshijun' """ diff --git a/src/ssj/greedy/README.md b/src/ssj/greedy/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/heap/README.md b/src/ssj/heap/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/leecode/README.md b/src/ssj/leecode/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/leecode/regular_expression_matching.py b/src/ssj/leecode/regular_expression_matching.py new file mode 100644 index 0000000..1f64edd --- /dev/null +++ b/src/ssj/leecode/regular_expression_matching.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +'.' Matches any single character. +'*' Matches zero or more of the preceding element. + +The matching should cover the entire input string (not partial). + +The function prototype should be: +bool isMatch(const char *s, const char *p) + +Some examples: +isMatch("aa","a") → false +isMatch("aa","aa") → true +isMatch("aaa","aa") → false +isMatch("aa", "a*") → true +isMatch("aa", ".*") → true +isMatch("ab", ".*") → true +isMatch("aab", "c*a*b") → true +""" + + +class Solution(object): + def isMatch(self, s, p): + """ + :type s: str + :type p: str + :rtype: bool + """ + pass diff --git a/src/ssj/lib/README.md b/src/ssj/lib/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/list/README.md b/src/ssj/list/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/map/README.md b/src/ssj/map/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/matrix/README.md b/src/ssj/matrix/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/number_theory/README.md b/src/ssj/number_theory/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/other/README.md b/src/ssj/other/README.md new file mode 100644 index 0000000..e64b270 --- /dev/null +++ b/src/ssj/other/README.md @@ -0,0 +1,3 @@ +#本文件夹里面的算法是一些很分散的算法,没有确切的来源 +* find_max_sublist.py 最大连续子数组和问题:从一个所有元素都是数字的数组中找出连续的最大的和,使用二分法可以解决 +* find_max_sublist_without_recursion.py 也是求最大连续子数组和问题,但是这是一种更加高效的算法,负责度只有O(lgN),而且没有递归 \ No newline at end of file diff --git a/src/ssj/divide_conquer/__init__.py b/src/ssj/other/__init__.py similarity index 100% rename from src/ssj/divide_conquer/__init__.py rename to src/ssj/other/__init__.py diff --git a/src/ssj/divide_conquer/find_max_sublist.py b/src/ssj/other/find_max_sublist.py similarity index 88% rename from src/ssj/divide_conquer/find_max_sublist.py rename to src/ssj/other/find_max_sublist.py index 71104a0..5bac8cd 100755 --- a/src/ssj/divide_conquer/find_max_sublist.py +++ b/src/ssj/other/find_max_sublist.py @@ -8,6 +8,12 @@ 3,跨越了左右半部分。这个时候只要从中点开始分别在左右找最大子数组就可以了。 边界条件是:列表中的元素只有一个的时候 """ +""" +复杂度,使用递归树来分析: +因为二分法,树的高度是lgN。 +每一层树的复杂度是N,因为find_max_in_middle中需要把所有节点都遍历一遍 +所以整体复杂度是O(NlgN) +""" def find_max_sublist(li): @@ -57,7 +63,7 @@ def find_max_in_middle(li, middle): def main(): - print find_max_sublist([0]) + print find_max_sublist([1, -2, 3, 10, -4, 7, 2, -5]) if __name__ == '__main__': diff --git a/src/ssj/other/find_max_sublist_without_recursion.py b/src/ssj/other/find_max_sublist_without_recursion.py new file mode 100755 index 0000000..b22a692 --- /dev/null +++ b/src/ssj/other/find_max_sublist_without_recursion.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*-coding:utf-8 -*- + +""" +复杂度是O(N),因为只需要遍历一遍数组就可以了 +""" + +""" +思想:采取打擂台的方法,也就是把最大值时刻放在擂台上和别的和比较。 +同样的方法我用来解决leecode的问题中的https://leetcode.com/problems/longest-palindromic-substring/ +采用打擂台的方法解决的问题有同样的特点就是:他们都要求连续,只要要求连续才能保证算法的正确性。 + +对于本题的算法正确性,可以使用递归法来证明: +基本情况:不用证明。 +""" + + +def find_max_sublist(li): + b, max_sum, left, right = 0, 0, 0, 0 + li_len = len(li) + for x in xrange(0, li_len): + if b < 0: + b = li[x] + left = x + else: + b += li[x] + if max_sum < b: + right = x + max_sum = b + + return left, right, max_sum + + +def main(): + print find_max_sublist([1, -2, 3, 10, -4, 7, 2, -5]) + + +if __name__ == '__main__': + main() diff --git a/src/ssj/divide_conquer/power.py b/src/ssj/other/power.py similarity index 92% rename from src/ssj/divide_conquer/power.py rename to src/ssj/other/power.py index caf5d42..0ecc96d 100755 --- a/src/ssj/divide_conquer/power.py +++ b/src/ssj/other/power.py @@ -13,7 +13,7 @@ def power(x, n): def main(): - print power(1000, 1) + print power(1000, 2) if __name__ == '__main__': diff --git a/src/ssj/divide_conquer/yong_matrix.py b/src/ssj/other/yong_matrix.py similarity index 100% rename from src/ssj/divide_conquer/yong_matrix.py rename to src/ssj/other/yong_matrix.py diff --git a/src/ssj/queue/README.md b/src/ssj/queue/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/search/README.md b/src/ssj/search/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/sort/README.md b/src/ssj/sort/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/string/README.md b/src/ssj/string/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/tree/BTree.py b/src/ssj/tree/BTree.py index 5b0ac05..bfb6ec4 100644 --- a/src/ssj/tree/BTree.py +++ b/src/ssj/tree/BTree.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from ssj.lib import Stack +from ssj.lib.stack import Stack __author__ = 'shenshijun' diff --git a/src/ssj/tree/README.md b/src/ssj/tree/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/tree/binarystree.py b/src/ssj/tree/binarystree.py index 4c36b39..22d8072 100644 --- a/src/ssj/tree/binarystree.py +++ b/src/ssj/tree/binarystree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding:utf-8 -*- -from ssj.lib import Queue -from ssj.lib import Stack +from ssj.lib.queue import Queue +from ssj.lib.stack import Stack class BSTree(object): diff --git a/src/ssj/tree/interval_tree.py b/src/ssj/tree/interval_tree.py index 6eaaa0c..862be7c 100644 --- a/src/ssj/tree/interval_tree.py +++ b/src/ssj/tree/interval_tree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from ssj.lib import Queue -from ssj.lib import Stack +from ssj.lib.queue import Queue +from ssj.lib.stack import Stack __author__ = 'shenshijun' diff --git a/src/ssj/tree/order_statistic_tree.py b/src/ssj/tree/order_statistic_tree.py index dbf1358..ff5ff92 100644 --- a/src/ssj/tree/order_statistic_tree.py +++ b/src/ssj/tree/order_statistic_tree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from ssj.lib import Queue -from ssj.lib import Stack +from ssj.lib.queue import Queue +from ssj.lib.stack import Stack __author__ = 'shenshijun' diff --git a/src/ssj/tree/red_black_tree.py b/src/ssj/tree/red_black_tree.py index 2d81020..a169eb0 100644 --- a/src/ssj/tree/red_black_tree.py +++ b/src/ssj/tree/red_black_tree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from ssj.lib import Queue -from ssj.lib import Stack +from ssj.lib.queue import Queue +from ssj.lib.stack import Stack __author__ = 'shenshijun' From c22487b17751683214cc802ed731e8b28ed5c97f Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sat, 24 Oct 2015 16:17:47 +0800 Subject: [PATCH 17/23] =?UTF-8?q?B=E6=A0=91bugfix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/tree/BTree.py | 91 +++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 29 deletions(-) diff --git a/src/ssj/tree/BTree.py b/src/ssj/tree/BTree.py index bfb6ec4..f318364 100644 --- a/src/ssj/tree/BTree.py +++ b/src/ssj/tree/BTree.py @@ -14,17 +14,16 @@ def __init__(self, is_leaf, keys, childs=None, parent=None): self.keys = list(sorted(keys)) self.is_leaf = is_leaf self.__size = len(self.keys) - if childs is None: - self.childs = [None for x in xrange(0, self.__size)] - self.childs.append(None) + if not self.is_leaf and childs is None: + self.childs = [None for x in xrange(0, self.__size + 1)] else: self.childs = childs self.parent = parent def __str__(self): return "".join(['Node(keys=', ",".join(map(lambda key: str(key), self.keys)), - ',leaf' if self.is_leaf else ',not leaf', - ',childs num=', str(len(self.childs)), ')\n']) + ',Leaf' if self.is_leaf else ',Not Leaf', + ',childs num=', '0' if self.is_leaf else str(len(self.childs)), ')\n']) def __len__(self): return self.__size @@ -35,13 +34,16 @@ def append(self, key): """ result = self.__size self.__size += 1 + for x in xrange(0, result): if self.keys[x] > key: self.keys.insert(x, key) - self.childs.insert(x, None) + if not self.is_leaf: + self.childs.insert(x, None) return x self.keys.append(key) - self.childs.append(None) + if not self.is_leaf: + self.childs.append(None) return result def search_child(self, instance): @@ -63,23 +65,26 @@ def __init__(self, load_factor=4, *vargs): """Constructor for BTree""" self.__root = None self.__load_factor = load_factor - self.__size = len(vargs) + self.__size = 0 map(self.insert, vargs) def insert(self, key): """ - 节点插入的时候不需要再检测节点是不是满了,因为load_factor>=2,每次插入节点前调整都是使得节点关键字个数为load_factor-1。 - 而插入一个关键字之后节点关键字个数是2*load_factor-1或者load_factor + 插入一个节点 :param key: :return: """ if self.__root is None: self.__root = Node(True, [key]) return + cur_node = self.__root while not cur_node.is_leaf: self.__split(cur_node) + # 这个地方cur_node并没有被改变,所以是可以继续搜索的。 cur_node = cur_node.search_child(key) + print(key) + left_node, right_node = self.__split(cur_node) if left_node is None or right_node is None: # 返回None表示叶节点没有满 @@ -90,27 +95,41 @@ def insert(self, key): right_node.append(key) else: left_node.append(key) + self.__size += 1 def __split(self, node): + """ + 在节点满的时候分裂节点。要注意两个问题: + 1,根节点分裂的时候需要重新设置根节点 + 2,叶节点是没有子节点的,一次要时刻判断 + :param node: + :return: + """ if self.full(node): parent_node = node.parent middle_key = node.keys[self.__load_factor - 1] if parent_node is None: # 处理根节点 - self.__root = Node(False, []) - parent_node = self.__root + parent_node = self.__root = Node(False, []) + parent_middle_index = parent_node.append(middle_key) - left_node = Node(node.is_leaf, node.keys[:self.__load_factor - 1], node.childs[:self.__load_factor], + left_node = Node(node.is_leaf, node.keys[:self.__load_factor - 1], + None if node.is_leaf else node.childs[:self.__load_factor], parent_node) - # 注意设定分裂节点的子节点的父指针 - for child in left_node.childs: - if child is not None: - child.parent = left_node - right_node = Node(node.is_leaf, node.keys[self.__load_factor:], node.childs[self.__load_factor:], + + right_node = Node(node.is_leaf, node.keys[self.__load_factor:], + None if node.is_leaf else node.childs[self.__load_factor:], parent_node) - for child in right_node.childs: - if child is not None: - child.parent = right_node + + # 注意设定分裂节点的子节点的父指针,因为如果node是叶节点,那么两个子节点肯定都是叶节点,反之同理 + if not node.is_leaf: + for child in left_node.childs: + if child is not None: + child.parent = left_node + for child in right_node.childs: + if child is not None: + child.parent = right_node + parent_node.childs[parent_middle_index] = left_node parent_node.childs[parent_middle_index + 1] = right_node self.__root.is_leaf = False @@ -125,6 +144,12 @@ def full(self, node): @classmethod def __search(cls, root, instance): + """ + 搜索树中节点 + :param root: + :param instance: + :return: + """ cur_node = root while True: cur_len = len(cur_node) @@ -139,12 +164,20 @@ def __search(cls, root, instance): cur_node = cur_node.childs[x] def min(self): + """ + 取出树中最小值 + :return: + """ cur_node = self.__root while not cur_node.is_leaf: cur_node = cur_node.childs[0] return cur_node.keys[0] def max(self): + """ + 取出树中最大值 + :return: + """ cur_node = self.__root while not cur_node.is_leaf: cur_node = cur_node.childs[-1] @@ -182,19 +215,19 @@ def midorder(self, f): def __str__(self): return "\n".join(self.midorder(lambda s: str(s))) - def test(self): - print "-" * 20 - print self.__root - print self.__root.childs[0] - print self.__root.childs[1] + def processor(self, key): + pass def main(): - btree = BTree(3, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', - 'V', 'X', 'Y', 'Z') - print btree + import random + test = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', + 'V', 'X', 'Y', 'Z'] + random.shuffle(test) + btree = BTree(3, *test) print btree.max() print btree.min() + btree.test() if __name__ == "__main__": From ffcb064fccf846bcbf6944bc04e4b8822ab0a34e Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sat, 24 Oct 2015 23:43:05 +0800 Subject: [PATCH 18/23] =?UTF-8?q?B=E6=A0=91=E5=88=A0=E9=99=A4=E5=92=8C?= =?UTF-8?q?=E5=89=8D=E5=90=8E=E7=BC=80=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/tree/BTree.py | 210 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 198 insertions(+), 12 deletions(-) diff --git a/src/ssj/tree/BTree.py b/src/ssj/tree/BTree.py index f318364..e11ab7a 100644 --- a/src/ssj/tree/BTree.py +++ b/src/ssj/tree/BTree.py @@ -55,6 +55,11 @@ def search_child(self, instance): return self.childs[x] return self.childs[self.__size] + def leaf_remove(self, index): + if self.is_leaf: + del self.keys[index] + self.__size -= 1 + class BTree(object): """ @@ -83,18 +88,25 @@ def insert(self, key): self.__split(cur_node) # 这个地方cur_node并没有被改变,所以是可以继续搜索的。 cur_node = cur_node.search_child(key) - print(key) left_node, right_node = self.__split(cur_node) if left_node is None or right_node is None: # 返回None表示叶节点没有满 cur_node.append(key) else: - if left_node.keys[-1] < key: + # 找到左右节点的共同关键字 + parent_key = None + parent = left_node.parent + for i in xrange(len(parent)): + if parent.childs[i] is left_node: + parent_key = parent.keys[i] + + if parent_key <= key: # 说明left_node中的所有节点都比key小,所以把新节点插入到右边 right_node.append(key) else: left_node.append(key) + self.__size += 1 def __split(self, node): @@ -137,6 +149,11 @@ def __split(self, node): return None, None def search(self, instance): + """ + 查找一个元素的位置,位置使用一个tuple表示,前面一个元素是Node,后面一个元素是元素的位置 + :param instance: + :return:(Node, index) + """ return self.__search(self.__root, instance) def full(self, node): @@ -156,7 +173,7 @@ def __search(cls, root, instance): x = 0 while x < cur_len and cur_node.keys[x] < instance: x += 1 - if cur_node.keys[x] == instance: + if x < cur_len and cur_node.keys[x] == instance: return cur_node, x elif cur_node.is_leaf: return None, None @@ -183,7 +200,7 @@ def max(self): cur_node = cur_node.childs[-1] return cur_node.keys[-1] - def midorder(self, f): + def mid_order(self, f): """ B树中序遍历 :param f: @@ -212,22 +229,191 @@ def midorder(self, f): cur_node = cur_node.childs[0] return result + def delete(self, key): + """ + 删除一个关键字 + :param key: + :return: + """ + node, index = self.search(key) + if node is None: + return False + + return self.__delete(node, index) + + def __delete(self, node, index): + if node is None: + return False + + if node.is_leaf: + self.__size -= 1 + + if self.will_starve(node): + # 检查是否能从兄弟节点借一个元素,会检查左右两个节点。如果不能从兄弟节点借,那么就只能和兄弟节点合并了 + change_index, bro_node, bro_index = self.__check_brother_borrow(node) + if bro_node is None: + del node.keys[index] + + self.__merge_brother(node) + else: + parent = node.parent + node.keys[index] = parent.keys[change_index] + parent.keys[change_index] = bro_node.keys[bro_index] + bro_node.leaf_remove(bro_index) + else: + # 删除之后节点还是有效的B树节点,因此直接从B树中删除元素 + node.leaf_remove(index) + else: + # 如果节点删除发生在内部节点上,那么先把后继节点上的关键字移动到被删除的元素的位置上,然后把后继节点删除 + succ, succ_index = self.__successor(node, index) + node.keys[index] = succ.keys[succ_index] + # 因为调用了自己,所有并没有把size减一 + return self.__delete(succ, succ_index) + return True + + def __successor(self, node, i): + """ + 查找在node的i处的节点的关键字的后继节点,位置使用一个元祖表示,前面的一个元素是node,后面的是index + 如果返回None表示没有后继,也就是说是最大元素 + :param node: + :param i: + :return:(Node,index)|None + """ + if not node.is_leaf: + child_node = node.childs[i + 1] + while not child_node.is_leaf: + child_node = child_node.childs[0] + return self.__successor(child_node, -1) + else: + if i < len(node) - 1: + return node, i + 1 + else: + return None, None + + def will_starve(self, node): + """ + 检查一个节点的元素是否小于load_factor,这样的话如果在删除一个关键字节点就不符合B树的节点定义了 + :param node: + :return: + """ + return len(node) < self.__load_factor + + def successor(self, key): + """ + 查找关键字的后继节点,位置使用一个元祖表示,前面的一个元素是node,后面的是index + 如果返回None表示没有后继,也就是说是最大元素 + :param key: + :return:(Node,index)|None + """ + node, index = self.search(key) + if node is None: + return None, None + return self.__successor(node, index) + def __str__(self): - return "\n".join(self.midorder(lambda s: str(s))) + return "\n".join(self.mid_order(lambda s: str(s))) + + def test(self): + node = self.successor('0') + print(node) + + def __check_brother_borrow(self, node): + """ + 检查左右的兄弟节点是否能够借出节点 + int:父节点中交换元素的位置 + Node:要借出元素的节点 + int:借出元素的位置 + + 如果不能借出,那么返回(None,None,None) + :param node: + :return:(int,Node,int)|(None,None,None) + """ + parent = node.parent + node_index = -1 + # 寻找node在parent的位置 + for i in xrange(len(parent.childs)): + if parent.childs[i] is node: + node_index = i - def processor(self, key): - pass + # 先从左边的兄弟节点借 + if node_index >= 1 and not self.will_starve(parent.childs[node_index - 1]): + return node_index - 1, parent.childs[node_index - 1], -1 + + if node_index >= 0 and not self.will_starve(parent.childs[node_index + 1]): + return node_index, parent.childs[node_index + 1], 0 + + return None, None, None + + def __merge_brother(self, node): + parent = node.parent + if parent is self.__root and len(parent.keys) > 0: + return + + node_index = -1 + # 寻找node在parent的位置 + for i in xrange(len(parent.childs)): + if parent.childs[i] is node: + node_index = i + + # 合并只和长度较小的节点合并 + smaller_node = None + is_left = True + if node_index >= 1: + smaller_node = parent.childs[node_index - 1] + + if node_index >= 0 and (smaller_node is None or len(smaller_node) > parent.childs[node_index + 1]): + smaller_node = parent.childs[node_index + 1] + is_left = False + + # 只有在必要的时候才合并 + if len(smaller_node) < self.__load_factor - 1 or len(node) < self.__load_factor - 1: + if is_left: + new_keys = smaller_node.keys + new_keys.append(parent.keys[node_index - 1]) + new_keys.extend(node.keys) + else: + new_keys = node.keys + new_keys.append(parent.keys[node_index - 1]) + new_keys.extend(smaller_node.keys) + + new_childs = None + if not node.is_leaf: + if is_left: + new_childs = smaller_node.childs + new_childs.extend(node.childs) + else: + new_childs = node.childs + new_childs.extend(smaller_node.childs) + + new_node = Node(node.is_leaf, new_keys, new_childs, parent) + + # 从父节点中删除被拿到子节点的节点 + if is_left: + del parent.childs[node_index - 1] + del parent.keys[node_index - 1] + parent.childs[node_index - 1] = new_node + else: + del parent.childs[node_index + 1] + del parent.keys[node_index + 1] + parent.childs[node_index] = new_node + + # 处理根节点,然后调用递归调用合并父节点 + if parent is self.__root and len(parent.keys): + new_node.parent = None + self.__root = new_node + else: + self.__merge_brother(parent) def main(): import random - test = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', - 'V', 'X', 'Y', 'Z'] + test = ['O', 'J', 'S', 'Y', 'C', 'M', 'B', 'R', 'N', 'F', 'L', 'Z', 'U', 'Q', 'A', 'G', 'V', 'E', 'D', 'W', 'I', + 'H', 'T', 'K', 'X', 'P'] + random.shuffle(test) btree = BTree(3, *test) - print btree.max() - print btree.min() - btree.test() + print(btree.delete('O')) + print(btree) if __name__ == "__main__": From a5f8fe08cf9f2a0e75c6fe736b8913d4c47f3854 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sat, 31 Oct 2015 12:35:53 +0800 Subject: [PATCH 19/23] =?UTF-8?q?=E6=96=90=E6=B3=A2=E9=82=A3=E5=A5=91?= =?UTF-8?q?=E6=A0=91=E5=AE=8C=E6=88=90=E6=8F=92=E5=85=A5=E5=92=8Cextra=5Fm?= =?UTF-8?q?in?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/heap/fibonacci_heap.py | 168 +++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/ssj/heap/fibonacci_heap.py diff --git a/src/ssj/heap/fibonacci_heap.py b/src/ssj/heap/fibonacci_heap.py new file mode 100644 index 0000000..c2559b5 --- /dev/null +++ b/src/ssj/heap/fibonacci_heap.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + + +class FibonacciHeap(object): + """实现斐波那契堆,斐波那契堆在一些操作执行的时候负责度比较低,而其他操作的复杂度和普通的堆是一样的""" + + class Node(object): + """节点实现""" + + def __init__(self, key, parent=None, child=None, left=None, right=None): + """Constructor for """ + self.key = key + self.degree = 0 + self.mark = False + self.parent = parent + self.child = child + self.left = left or self + self.right = right or self + + def __str__(self): + return str(self.key) + " : " + str(self.degree) + + def __init__(self, *argv): + """Constructor for """ + self.__root = None + self.__size = 0 + map(self.insert, argv) + + def insert(self, key): + self.__size += 1 + if self.__root is None: + self.__root = self.Node(key) + else: + new_node = self.Node(key, left=self.__root.left, right=self.__root) + self.__root.left.right = new_node + self.__root.left = new_node + if new_node.key < self.__root.key: + self.__root = new_node + + def extract_min(self): + if self.__root is None: + return None + + result = self.__root + self.__size -= 1 + + # 首先把根节点的子节点全部移到根链表上 + child = self.__root.child + for i in xrange(0, self.__root.degree): + next_node = child.right + self.__root.left.right = child + child.left = self.__root.left + self.__root.left = child + child.right = self.__root + child.parent = None + child = next_node + + # 移除根节点 + self.__root.left.right = self.__root.right + self.__root.right.left = self.__root.left + if self.__root.right is self.__root: + self.__root = None + else: + self.__root = self.__root.right + self.__extract_consolidating() + + return result.key + + def __extract_consolidating(self): + # 合并根链表 + node_degrees = {} + pass_root = False + cur_node = self.__root + after_merge = False + next_node = None + while cur_node is not self.__root or not pass_root or after_merge: + if cur_node == self.__root: + pass_root = True + + if not after_merge: + next_node = cur_node.right + + d = cur_node.degree + if d in node_degrees: + other_node = node_degrees[d] + sm_node = cur_node if cur_node.key <= other_node.key else other_node + bg_node = cur_node if cur_node.key > other_node.key else other_node + # 把大的节点连接到小的节点上面,然后继续在sm_node上面循环,因为sm_node的度数发生了变化 + self.__link_to(bg_node, sm_node) + del node_degrees[d] + after_merge = True + cur_node = sm_node + else: + after_merge = False + node_degrees[d] = cur_node + cur_node = next_node + + self.__root = None + + for d, node in node_degrees.iteritems(): + node.parent = None + if self.__root is None: + self.__root = node + self.__root.left = node + self.__root.right = node + else: + node.left = self.__root.left + node.right = self.__root + self.__root.left.right = node + self.__root.left = node + + if self.__root.key > node.key: + self.__root = node + + @staticmethod + def __link_to(src, dest): + """ + bugfix: 不能把src从根链表移除,这样的话会破坏根链表,导致在__extract_consolidating中的while找不到退出条件 + 我是为了避免重新创建根链表而把src从根链表中移除,这段注释只是为了提醒 + :param src: + :param dest: + :return: + """ + src.mark = False + + dest_child = dest.child + src.parent = dest + if dest_child is None: + dest.child = src + src.left = src + src.right = src + else: + src.left = dest_child.left + dest_child.left.right = src + dest_child.left = src + src.right = dest_child + dest.degree += 1 + + def union(self, other): + pass + + def min(self): + return None if self.__root is None else self.__root.key + + def change_key(self, node, new_key): + pass + + def __len__(self): + return self.__size + + def delete(self, node): + self.change_key(node, float('-Inf')) + self.extract_min() + + +def main(): + test = ['O', 'J', 'S', 'Y', 'C', 'M', 'B', 'R', 'N', 'F', 'L', 'Z', 'U', 'Q', 'A', 'G', 'V', 'E', 'D', 'W', 'I', + 'H', 'T', 'K', 'X', 'P'] + + heap = FibonacciHeap(*test) + for i in xrange(0, len(heap)): + print(heap.extract_min()) + + +if __name__ == "__main__": + main() From 9f0e76f382f830264a0db28a6f875c3b86f1ce02 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sat, 31 Oct 2015 16:24:59 +0800 Subject: [PATCH 20/23] =?UTF-8?q?=E6=96=90=E6=B3=A2=E9=82=A3=E5=A5=91?= =?UTF-8?q?=E6=A0=91=E5=AE=8C=E6=88=90=E5=88=A0=E9=99=A4=E5=92=8Cchange=5F?= =?UTF-8?q?key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/heap/fibonacci_heap.py | 140 +++++++++++++++++++++++++-------- 1 file changed, 107 insertions(+), 33 deletions(-) diff --git a/src/ssj/heap/fibonacci_heap.py b/src/ssj/heap/fibonacci_heap.py index c2559b5..cdc38b5 100644 --- a/src/ssj/heap/fibonacci_heap.py +++ b/src/ssj/heap/fibonacci_heap.py @@ -30,17 +30,26 @@ def __init__(self, *argv): def insert(self, key): self.__size += 1 - if self.__root is None: - self.__root = self.Node(key) + return self.__insert_root(self.Node(key)) + + def __insert_root(self, node, change_root=True): + node.parent = None + if not self.__root: + self.__root = node + self.__root.left = node + self.__root.right = node else: - new_node = self.Node(key, left=self.__root.left, right=self.__root) - self.__root.left.right = new_node - self.__root.left = new_node - if new_node.key < self.__root.key: - self.__root = new_node + node.left = self.__root.left + node.right = self.__root + self.__root.left.right = node + self.__root.left = node + + if self.__root.key > node.key and change_root: + self.__root = node + return node def extract_min(self): - if self.__root is None: + if not self.__root: return None result = self.__root @@ -50,24 +59,28 @@ def extract_min(self): child = self.__root.child for i in xrange(0, self.__root.degree): next_node = child.right - self.__root.left.right = child - child.left = self.__root.left - self.__root.left = child - child.right = self.__root - child.parent = None + self.__remove_self(child) + self.__insert_root(child) child = next_node # 移除根节点 - self.__root.left.right = self.__root.right - self.__root.right.left = self.__root.left + self.__remove_self(self.__root) if self.__root.right is self.__root: self.__root = None else: self.__root = self.__root.right self.__extract_consolidating() + result.left = result + result.right = result + result.parent = None return result.key + @classmethod + def __remove_self(cls, node): + node.left.right = node.right + node.right.left = node.left + def __extract_consolidating(self): # 合并根链表 node_degrees = {} @@ -100,19 +113,7 @@ def __extract_consolidating(self): self.__root = None for d, node in node_degrees.iteritems(): - node.parent = None - if self.__root is None: - self.__root = node - self.__root.left = node - self.__root.right = node - else: - node.left = self.__root.left - node.right = self.__root - self.__root.left.right = node - self.__root.left = node - - if self.__root.key > node.key: - self.__root = node + self.__insert_root(node) @staticmethod def __link_to(src, dest): @@ -127,7 +128,7 @@ def __link_to(src, dest): dest_child = dest.child src.parent = dest - if dest_child is None: + if not dest_child: dest.child = src src.left = src src.right = src @@ -139,13 +140,39 @@ def __link_to(src, dest): dest.degree += 1 def union(self, other): - pass + if not self.__root: + self.__root = other.__root + else: + self_left = self.__root.left + other_right = other.__root.right + self.__root.left = other.__root + other.__root.right = self.__root + self_left.right = other_right + other_right.left = self_left + self.__root = self.__root if self.__root.key < other.__root.key else other.__root + self.__size += other.__size + + return self def min(self): - return None if self.__root is None else self.__root.key + return None if self.__root else self.__root.key def change_key(self, node, new_key): - pass + """ + 给node设置一个比其key小的值 + :param node: + :param new_key: + :return: + """ + if node.key < new_key: + return + node.key = new_key + parent = node.parent + if parent and parent.key > node.key: + self.__cut(node) + self.__cascade_cut(parent) + if self.__root.key > node.key: + self.__root = node def __len__(self): return self.__size @@ -154,15 +181,62 @@ def delete(self, node): self.change_key(node, float('-Inf')) self.extract_min() + def __cut(self, node): + parent = node.parent + if not parent: + return node + + # 处理parent的child指针 + if node.right is node: + parent.child = None + else: + parent.child = node.right + self.__remove_self(node) + parent.degree -= 1 + self.__insert_root(node) + node.mark = False + return node + + def __cascade_cut(self, node): + parent = node.parent + # 如果parent为None,说明这个节点在根链表上,因此不需要继续处理 + if parent: + if not node.mark: + node.mark = True + else: + # 如果已经丢失了两个节点,那么要把本节点移到根链表上 + self.__cut(node) + self.__cascade_cut(parent) + def main(): + import random test = ['O', 'J', 'S', 'Y', 'C', 'M', 'B', 'R', 'N', 'F', 'L', 'Z', 'U', 'Q', 'A', 'G', 'V', 'E', 'D', 'W', 'I', 'H', 'T', 'K', 'X', 'P'] - + random.shuffle(test) + rele = 'Z' + test.remove(rele) heap = FibonacciHeap(*test) + rnode = heap.insert(rele) + + for i in xrange(0, random.randint(1, len(heap))): + print(heap.extract_min()) + + print("change a node key") + heap.change_key(rnode, 0) + for i in xrange(0, len(heap)): print(heap.extract_min()) + print("test union") + one = [10, 20, 0] + other = [15, 5, 30] + one_heap = FibonacciHeap(*one) + other_heap = FibonacciHeap(*other) + one_heap.union(other_heap) + for i in xrange(0, len(one_heap)): + print(one_heap.extract_min()) + if __name__ == "__main__": main() From 09dee38921ba1cbd11215c9bc0dee42cd0ed9b34 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Thu, 31 Mar 2016 23:24:35 +0800 Subject: [PATCH 21/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8D,=E6=B7=BB=E5=8A=A0=E4=B8=80?= =?UTF-8?q?=E4=BA=9BTODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/heap/fibonacci_heap.py | 2 +- src/ssj/tree/{avltree.py => avl_tree.py} | 1 + src/ssj/tree/{binarystree.py => binary_search_tree.py} | 0 src/ssj/tree/{binarytree.py => binary_tree.py} | 0 src/ssj/tree/bplus_tree.py | 6 ++++++ src/ssj/tree/tries.py | 1 + 6 files changed, 9 insertions(+), 1 deletion(-) rename src/ssj/tree/{avltree.py => avl_tree.py} (92%) rename src/ssj/tree/{binarystree.py => binary_search_tree.py} (100%) rename src/ssj/tree/{binarytree.py => binary_tree.py} (100%) create mode 100644 src/ssj/tree/bplus_tree.py diff --git a/src/ssj/heap/fibonacci_heap.py b/src/ssj/heap/fibonacci_heap.py index cdc38b5..7a90dc1 100644 --- a/src/ssj/heap/fibonacci_heap.py +++ b/src/ssj/heap/fibonacci_heap.py @@ -4,7 +4,7 @@ class FibonacciHeap(object): - """实现斐波那契堆,斐波那契堆在一些操作执行的时候负责度比较低,而其他操作的复杂度和普通的堆是一样的""" + """实现斐波那契堆,斐波那契堆在一些操作执行的时候复杂度比较低,而其他操作的复杂度和普通的堆是一样的""" class Node(object): """节点实现""" diff --git a/src/ssj/tree/avltree.py b/src/ssj/tree/avl_tree.py similarity index 92% rename from src/ssj/tree/avltree.py rename to src/ssj/tree/avl_tree.py index 8d24c9b..9cf03cc 100644 --- a/src/ssj/tree/avltree.py +++ b/src/ssj/tree/avl_tree.py @@ -3,6 +3,7 @@ __author__ = 'shenshijun' +# TODO 实现 class AVLTree(object): """""" diff --git a/src/ssj/tree/binarystree.py b/src/ssj/tree/binary_search_tree.py similarity index 100% rename from src/ssj/tree/binarystree.py rename to src/ssj/tree/binary_search_tree.py diff --git a/src/ssj/tree/binarytree.py b/src/ssj/tree/binary_tree.py similarity index 100% rename from src/ssj/tree/binarytree.py rename to src/ssj/tree/binary_tree.py diff --git a/src/ssj/tree/bplus_tree.py b/src/ssj/tree/bplus_tree.py new file mode 100644 index 0000000..427d393 --- /dev/null +++ b/src/ssj/tree/bplus_tree.py @@ -0,0 +1,6 @@ +# TODO实现B+树 +class BplusTree: + def __init__(self): + pass + + pass diff --git a/src/ssj/tree/tries.py b/src/ssj/tree/tries.py index 1dc2140..6a267bf 100644 --- a/src/ssj/tree/tries.py +++ b/src/ssj/tree/tries.py @@ -3,6 +3,7 @@ __author__ = 'shenshijun' +# TODO实现 class Tries(object): """ 字符串前缀树实现 From 2f81411faa0f7118767e8b515c2d796488eb505c Mon Sep 17 00:00:00 2001 From: ssjssh Date: Wed, 11 May 2016 01:04:42 +0800 Subject: [PATCH 22/23] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=97=A0=E5=90=91?= =?UTF-8?q?=E5=9B=BE=E7=9A=84BFS=E5=92=8C=E6=8B=93=E6=89=91=E6=8E=92?= =?UTF-8?q?=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ssj/graph/__init__.py | 4 + src/ssj/graph/digraph.py | 122 +++++++++++++++++++++ src/ssj/graph/general_graph.py | 189 --------------------------------- src/ssj/tree/avl_tree.py | 27 ++++- 4 files changed, 152 insertions(+), 190 deletions(-) create mode 100644 src/ssj/graph/digraph.py delete mode 100644 src/ssj/graph/general_graph.py diff --git a/src/ssj/graph/__init__.py b/src/ssj/graph/__init__.py index fb57e2f..b91606e 100644 --- a/src/ssj/graph/__init__.py +++ b/src/ssj/graph/__init__.py @@ -1,3 +1,7 @@ #!/usr/bin/env python # -*- coding:UTF-8 __author__ = 'shenshijun' + + +class GraphError(StandardError): + pass diff --git a/src/ssj/graph/digraph.py b/src/ssj/graph/digraph.py new file mode 100644 index 0000000..2e32c4d --- /dev/null +++ b/src/ssj/graph/digraph.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 + +__author__ = 'shenshijun' +from ssj.lib.queue import Queue +from ssj.graph import GraphError + + +class Vertex(object): + def __init__(self, key, weight=None): + """ + adjust_list 表示邻接节点 + """ + self.key = key + self.weight_list = [] + self.adjust_list = [] + self.in_degree = 0 + self.backup_in_degree = self.in_degree + self.out_degree = 0 + self.backup_out_degree = self.out_degree + self.dist = 0 + + def add_adjust(self, to_vertex): + self.adjust_list.append(to_vertex) + self.out_degree += 1 + self.backup_out_degree += 1 + + +class Digraph(object): + def __init__(self): + self._vertexes = {} + + def add_vertex(self, key): + """ + Args: + :param key:顶点关键字 + Returns: + :rtype: bool + """ + if key in self._vertexes: + return False + else: + self._vertexes[key] = Vertex(key) + return True + + def add_edge(self, from_key, to_key): + # 首先把两个节点查入到图中 + self.add_vertex(from_key) + self.add_vertex(to_key) + self._vertexes[from_key].add_adjust(self._vertexes[to_key]) + self._vertexes[to_key].in_degree += 1 + self._vertexes[to_key].backup_in_degree += 1 + + def top_sort(self, func): + zero_in_degree_queue = Queue() + + # 首先找到所有入度为0的顶点,遍历从这里开始 + for key, vertex in self._vertexes.iteritems(): + vertex.backup_in_degree = vertex.in_degree + if vertex.in_degree is 0: + zero_in_degree_queue.enter(vertex) + + if zero_in_degree_queue.empty(): + raise GraphError('图中有环,无法执行图的拓扑排序') + + result = [] + while not zero_in_degree_queue.empty(): + zero_vertex = zero_in_degree_queue.exit() + result.append(func(zero_vertex.key)) + for vertex in zero_vertex.adjust_list: + vertex.in_degree -= 1 + if vertex.in_degree is 0: + zero_in_degree_queue.enter(vertex) + + # 恢复 + for key, vertex in self._vertexes.iteritems(): + vertex.in_degree = vertex.backup_in_degree + return result + + def bfs(self, key, func): + next_vertex_queue = Queue() + for k, vertex in self._vertexes.iteritems(): + vertex.dist = -1 + + result = [] + self._vertexes[key].dist = 0 + next_vertex_queue.enter(self._vertexes[key]) + + while not next_vertex_queue.empty(): + vertex = next_vertex_queue.exit() + result.append(func(vertex.key, vertex.dist)) + for adjust_vertex in vertex.adjust_list: + if adjust_vertex.dist is -1: + adjust_vertex.dist = vertex.dist + 1 + next_vertex_queue.enter(adjust_vertex) + + for k, vertex in self._vertexes.iteritems(): + if vertex.dist is -1: + result.extend(self.bfs(vertex.key, func)) + return result + + +def main(): + graph = Digraph() + graph.add_edge('v1', 'v2') + graph.add_edge('v1', 'v3') + graph.add_edge('v1', 'v4') + graph.add_edge('v2', 'v4') + graph.add_edge('v4', 'v3') + graph.add_edge('v4', 'v7') + graph.add_edge('v4', 'v6') + graph.add_edge('v3', 'v6') + graph.add_edge('v2', 'v5') + graph.add_edge('v5', 'v4') + graph.add_edge('v5', 'v7') + graph.add_edge('v7', 'v6') + print graph.top_sort(lambda key: key) + print graph.bfs('v1', lambda key, dist: (key, dist)) + + +if __name__ == "__main__": + main() diff --git a/src/ssj/graph/general_graph.py b/src/ssj/graph/general_graph.py deleted file mode 100644 index 8bc02f8..0000000 --- a/src/ssj/graph/general_graph.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 - -import sys -from ssj.lib.stack import Stack - -reload(sys) -sys.setdefaultencoding('UTF-8') - - -__author__ = 'shenshijun' - - -class Node(object): - """ - 图中存储数据的结点 - """ - - def __init__(self, key, color): - """ - color - -1:白色 - 0:灰色 - 1:黑色 - """ - - self.key = key - self.color = color - self.depth = 0 - self.parent = None - self.start_time = None - self.end_time = None - - def set_gray(self): - self.color = 0 - - def set_black(self): - self.color = 1 - - def set_white(self): - self.color = -1 - - def is_gray(self): - return self.color is 0 - - def is_white(self): - return self.color is -1 - - def is_black(self): - return self.color is 1 - - def __eq__(self, other): - return self.key == other.key and self.color == other.color and self.depth == other.depth - - def __str__(self): - return "".join(['Node(key=', unicode(self.key), - ',depth=', str(self.depth), ',start_time=', str(self.start_time), ',end_time=', - str(self.end_time), - ',color:', 'white' if self.color is -1 else 'gray' if self.color is 0 else 'black', ')']) - - -class GeneralGraph(object): - """ - 使用邻接链表法存储一个通用的图结构。 - 使用一个元组来表示一个图中的边 - 要注意一个实现上的问题:邻接链表中的元素和关键字元素必须指向同一个对象 - """ - - def __init__(self, *vargs): - """ """ - self.__dict = {} - map(self.insert, vargs) - - def insert(self, edge): - start_node = self.__find(edge[0]) - end_node = self.__find(edge[1]) - linked_node = self.__dict.setdefault(start_node, []) - linked_node.append(end_node) - - def delete_edge(self, edge): - start_node = self.__find(edge[0]) - linked_list = self.__dict.get(start_node, []) - for x in xrange(0, len(linked_list)): - if linked_list[x].key == edge[1]: - del linked_list[x] - return True - return False - - def __find(self, instance): - for key_node in self.__dict.iterkeys(): - if key_node.key == instance: - return key_node - node = Node(instance, -1) - self.__dict[node] = [] - return node - - def bfs(self, instance, gray_func, black_func): - """ - 图的广度遍历 - :param gray_func:当节点在灰色的时候遍历的函数 - :param black_func:当节点在黑色的时候执行的函数 - :return:结果 - """ - gray_list = [] - black_list = [] - node = self.__find(instance) - if node is None: - return None - graph_queue = queue.Queue() - # 初始化节点 - node.set_white() - node.depth = 0 - node.parent = None - for end_node in self.__dict.iterkeys(): - end_node.set_white() - end_node.depth = 0 - end_node.parent = Node - - # 开始遍历 - node.set_gray() - graph_queue.enter(node) - while not graph_queue.empty(): - cur_node = graph_queue.exit() - gray_list.append(gray_func(cur_node)) - for end_node in self.__dict[cur_node]: - if end_node.is_white(): - end_node.set_gray() - end_node.depth += cur_node.depth - end_node.parent = cur_node - graph_queue.enter(end_node) - cur_node.set_black() - black_list.append(black_func(cur_node)) - return gray_list, black_list - - def dfs(self, gray_func, black_func): - """ - 图的深度遍历 - :param gray_func: - :param black_func: - :return: - """ - gray_list = [] - black_list = [] - - # 初始化 - for key in self.__dict.iterkeys(): - key.start_time = None - key.end_time = None - key.set_white() - - # 开始遍历 - counter = 0 - for key in self.__dict.iterkeys(): - if key.is_white(): - dfs_stack = Stack() - key.set_gray() - key.start_time = counter - counter += 1 - dfs_stack.push(key) - while not dfs_stack.empty(): - cur_node = dfs_stack.pop() - gray_list.append(gray_func(key)) - for end_node in self.__dict[cur_node]: - if end_node.is_white(): - end_node.set_gray() - end_node.start_time = counter - counter += 1 - dfs_stack.push(end_node) - cur_node.set_black() - black_list.append(black_func(cur_node)) - cur_node.end_time = counter - counter += 1 - return gray_list, black_list - - def topology_sort(self): - gray_list, black_list = self.dfs(lambda node: node, lambda node: node) - return reversed(black_list) - - -def main(): - graph = GeneralGraph(('内裤', '鞋'), ('内裤', '裤子'), ('裤子', '腰带'), ('腰带', '夹克'), ('衬衣', '腰带'), ('衬衣', '领带'), ('袜子', '鞋'), - ('手表', '手表')) - gray_list, black_list = graph.dfs(lambda node: str(node), lambda node: str(node)) - print gray_list - print black_list - - -if __name__ == "__main__": - main() diff --git a/src/ssj/tree/avl_tree.py b/src/ssj/tree/avl_tree.py index 9cf03cc..1f3a1f6 100644 --- a/src/ssj/tree/avl_tree.py +++ b/src/ssj/tree/avl_tree.py @@ -2,11 +2,36 @@ # -*- coding:UTF-8 __author__ = 'shenshijun' +""" +定义: +AVL树是高度平衡的二叉搜索树,平衡的方式是每一个节点左右子树高度差顶多为1. +每一个节点中会存储这个节点的高度。节点高度是指从这个节点到叶节点的最大距离。 + +高度: +AVL树的高度大约是1.44log(N)。 +高度为n的AVL树的最小节点数:s(h)=s(h-1)+s(h-2)+1 +""" + + +class Node(object): + """""" + + def __init__(self, value, parent, left, right, height=0): + """Constructor for Node""" + self.value = value + self.height = height + self.parent = parent + self.left = left + self.right = right + -# TODO 实现 class AVLTree(object): """""" def __init__(self): """Constructor for """ + self.__root = None + self.__size = 0 + + def insert(self, value): pass From 2db90930340ba4a9bf5a37b3386e9dbb48673e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E4=B8=96=E5=86=9B?= Date: Mon, 29 Aug 2016 20:47:15 +0800 Subject: [PATCH 23/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4e58ec..372e16d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ algorithm ========= -在阅读算法导论的时候。我用Python写的一些算法,这些算法大部分使用list来作为底层存储数据的结构。但是python的list用的是链表实现,因此有些操作性能不高。 +在阅读算法导论的时候。我用Python写的一些算法,这些算法大部分使用list来作为底层存储数据的结构。 #算法 ##排序算法:sort文件夹下面