From 53510bfc8e67462fd01bfdb8944aaf6599aa0988 Mon Sep 17 00:00:00 2001 From: ssjssh Date: Sun, 20 Sep 2015 19:25:09 +0800 Subject: [PATCH 01/18] =?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 02/18] =?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 03/18] =?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 04/18] =?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 05/18] =?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 06/18] =?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 07/18] =?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 08/18] =?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 09/18] =?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 10/18] =?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 11/18] =?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 12/18] =?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 13/18] =?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 14/18] =?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 15/18] =?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 16/18] =?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 17/18] =?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 18/18] 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文件夹下面